From: jblum Date: Tue, 23 Jun 2009 20:38:18 +0000 (+0000) Subject: Merging r11186:11273 from grc branch. X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=9988664127b367fa8fee4409f8460673d6f265e1;p=debian%2Fgnuradio Merging r11186:11273 from grc branch. Fixes, features, and reorganization for grc. Minor fixes and features for wxgui forms. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@11274 221aa14e-8319-0410-a670-987f0aec2ac5 --- diff --git a/config/grc_grc.m4 b/config/grc_grc.m4 index d8bc02a2..ce23e3c2 100644 --- a/config/grc_grc.m4 +++ b/config/grc_grc.m4 @@ -1,4 +1,4 @@ -dnl Copyright 2008 Free Software Foundation, Inc. +dnl Copyright 2008, 2009 Free Software Foundation, Inc. dnl dnl This file is part of GNU Radio dnl @@ -47,27 +47,15 @@ AC_DEFUN([GRC_GRC],[ AC_SUBST(PYTHONW) AC_CONFIG_FILES([ \ - 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/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/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/base/Makefile \ + grc/blocks/Makefile \ + grc/examples/Makefile \ grc/freedesktop/Makefile \ + grc/grc_gnuradio/Makefile \ + grc/gui/Makefile \ + grc/python/Makefile \ + grc/scripts/Makefile \ ]) GRC_BUILD_CONDITIONAL(grc) diff --git a/gr-wxgui/src/python/forms/converters.py b/gr-wxgui/src/python/forms/converters.py index 123aefeb..e535cb2d 100644 --- a/gr-wxgui/src/python/forms/converters.py +++ b/gr-wxgui/src/python/forms/converters.py @@ -85,22 +85,28 @@ class eval_converter(abstract_converter): Possible uses, set a complex number, constellation points. Used in text box. """ - def external_to_internal(self, s): - return str(s) + def __init__(self, formatter=lambda x: '%s'%(x)): + self._formatter = formatter + def external_to_internal(self, v): + return self._formatter(v) def internal_to_external(self, s): return eval(s) def help(self): return "Value must be evaluatable by python's eval." class str_converter(abstract_converter): + def __init__(self, formatter=lambda x: '%s'%(x)): + self._formatter = formatter def external_to_internal(self, v): - return str(v) + return self._formatter(v) def internal_to_external(self, s): return str(s) class int_converter(abstract_converter): + def __init__(self, formatter=lambda x: '%d'%round(x)): + self._formatter = formatter def external_to_internal(self, v): - return str(int(round(v))) + return self._formatter(v) def internal_to_external(self, s): return int(s, 0) def help(self): @@ -127,7 +133,8 @@ class slider_converter(abstract_converter): self._scaler = float(maximum - minimum)/num_steps self._cast = cast def external_to_internal(self, v): - return (v - self._offset)/self._scaler + #slider's internal representation is an integer + return int(round((v - self._offset)/self._scaler)) def internal_to_external(self, v): return self._cast(v*self._scaler + self._offset) def help(self): diff --git a/gr-wxgui/src/python/forms/forms.py b/gr-wxgui/src/python/forms/forms.py index 10f6a482..c69315b0 100644 --- a/gr-wxgui/src/python/forms/forms.py +++ b/gr-wxgui/src/python/forms/forms.py @@ -115,7 +115,6 @@ class _form_base(pubsub, wx.BoxSizer): self.subscribe(INT_KEY, update) self.subscribe(INT_KEY, self._translate_internal_to_external) self.subscribe(EXT_KEY, self._translate_external_to_internal) - if self._callback: self.subscribe(EXT_KEY, self._callback) def _translate_external_to_internal(self, external): try: @@ -134,6 +133,7 @@ class _form_base(pubsub, wx.BoxSizer): except Exception, e: self._err_msg(internal, e) self[EXT_KEY] = self[EXT_KEY] #reset to last good setting + if self._callback: self._callback(self[EXT_KEY]) def _err_msg(self, value, e): print >> sys.stderr, self, 'Error translating value: "%s"\n\t%s\n\t%s'%(value, e, self._converter.help()) diff --git a/grc/Makefile.am b/grc/Makefile.am index 0583e88b..a921fdd3 100644 --- a/grc/Makefile.am +++ b/grc/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2008 Free Software Foundation, Inc. +# Copyright 2008, 2009 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -23,13 +23,43 @@ include $(top_srcdir)/grc/Makefile.inc if PYTHON SUBDIRS = \ - data \ + base \ + blocks \ examples \ - scripts \ - src + grc_gnuradio \ + gui \ + python \ + scripts ## append freedesktop to the list of subdirs when xdg utils are present if XDG_UTILS SUBDIRS += freedesktop endif + +ourpythondir = $(grc_src_prefix) +ourpython_PYTHON = __init__.py + +etcdir = $(gr_sysconfdir) +dist_etc_DATA = grc.conf + +EXTRA_DIST = \ + $(srcdir)/__init__.py.in \ + $(srcdir)/grc.conf.in + +BUILT_SOURCES = \ + __init__.py \ + grc.conf + +__init__.py: $(srcdir)/__init__.py.in Makefile + sed \ + -e 's|@VERSION[@]|$(VERSION)|g' \ + $< > $@ + +grc.conf: $(srcdir)/grc.conf.in Makefile + sed \ + -e 's|@pythonw[@]|$(PYTHONW)|g' \ + -e 's|@blocksdir[@]|$(grc_blocksdir)|g' \ + -e 's|@docdir[@]|$(gr_docdir)|g' \ + $< > $@ + endif diff --git a/grc/Makefile.inc b/grc/Makefile.inc index c400e532..96ee11b6 100644 --- a/grc/Makefile.inc +++ b/grc/Makefile.inc @@ -20,8 +20,5 @@ # include $(top_srcdir)/Makefile.common -grc_gnuradio_prefix = $(pythondir)/grc_gnuradio grc_src_prefix = $(pythondir)/gnuradio/grc -grc_base_data_reldir = grc/base -grc_python_data_reldir = grc/python -grc_blocks_data_reldir = grc/blocks +grc_blocksdir = $(pkgdatadir)/grc/blocks diff --git a/grc/__init__.py.in b/grc/__init__.py.in new file mode 100644 index 00000000..4c146f95 --- /dev/null +++ b/grc/__init__.py.in @@ -0,0 +1,21 @@ +""" +Copyright 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +#package and version constants +VERSION = '@VERSION@' diff --git a/grc/base/Block.py b/grc/base/Block.py new file mode 100644 index 00000000..867a14f5 --- /dev/null +++ b/grc/base/Block.py @@ -0,0 +1,261 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from . 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 __call__ or () method can return the param evaluated to a raw python data type. + """ + + def __init__(self, param): + UserDict.__init__(self) + self._param = param + if param.is_enum(): + for key in param.get_opt_keys(): + self[key] = str(param.get_opt(key)) + + def __str__(self): + return str(self._param.to_code()) + + def __call__(self): + return self._param.get_evaluated() + +class Block(Element): + + def __init__(self, flow_graph, n): + """ + Make a new block from nested data. + @param flow graph the parent element + @param n the nested odict + @return block a new block + """ + #build the block + Element.__init__(self, flow_graph) + #grab the data + params = n.findall('param') + sources = n.findall('source') + sinks = n.findall('sink') + self._name = n.find('name') + self._key = n.find('key') + self._category = n.find('category') or '' + self._block_wrapper_path = n.find('block_wrapper_path') + #create the param objects + self._params = odict() + #add the id param + self._params['id'] = self.get_parent().get_parent().Param( + self, + odict({ + 'name': 'ID', + 'key': 'id', + 'type': 'id', + }) + ) + self._params['_enabled'] = self.get_parent().get_parent().Param( + self, + odict({ + '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: raise Exception, '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: raise Exception, '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: raise Exception, '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. + """ + Element.validate(self) + for c in self.get_params() + self.get_ports() + self.get_connections(): + try: + c.validate() + assert c.is_valid() + except AssertionError: + for msg in c.get_error_messages(): + self.add_error_message('>>> %s:\n\t%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_name(self): return self._name + def get_key(self): return self._key + def get_category(self): return self._category + def get_doc(self): return '' + def get_ports(self): return self.get_sources() + self.get_sinks() + def get_block_wrapper_path(self): return self._block_wrapper_path + + ############################################## + # 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) + + ############################################## + # Controller Modify + ############################################## + def type_controller_modify(self, direction): + """ + Change the type controller. + @param direction +1 or -1 + @return true for change + """ + changed = False + type_param = None + for param in filter(lambda p: p.is_enum(), self.get_params()): + children = self.get_ports() + self.get_params() + #priority to the type controller + if param.get_key() in ' '.join(map(lambda p: p._type, children)): type_param = param + #use param if type param is unset + if not type_param: type_param = param + if type_param: + #try to increment the enum by direction + try: + keys = type_param.get_option_keys() + old_index = keys.index(type_param.get_value()) + new_index = (old_index + direction + len(keys))%len(keys) + type_param.set_value(keys[new_index]) + changed = True + except: pass + return changed + + def port_controller_modify(self, direction): + """ + Change the port controller. + @param direction +1 or -1 + @return true for change + """ + return False + + ############################################## + ## Import/Export Methods + ############################################## + def export_data(self): + """ + Export this block's params to nested data. + @return a nested data odict + """ + n = odict() + n['key'] = self.get_key() + n['param'] = map(lambda p: p.export_data(), self.get_params()) + return n + + def import_data(self, n): + """ + Import this block's params from nested data. + Any param keys that do not exist will be ignored. + @param n the nested data odict + """ + params_n = n.findall('param') + for param_n in params_n: + key = param_n.find('key') + value = param_n.find('value') + #the key must exist in this block's params + if key in self.get_param_keys(): + self.get_param(key).set_value(value) diff --git a/grc/base/Connection.py b/grc/base/Connection.py new file mode 100644 index 00000000..94d4751b --- /dev/null +++ b/grc/base/Connection.py @@ -0,0 +1,95 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from Element import Element +from . import odict + +class Connection(Element): + + def __init__(self, flow_graph, porta, portb): + """ + Make a new connection given the parent and 2 ports. + @param flow_graph the parent of this element + @param porta a port (any direction) + @param portb a port (any direction) + @throws Error cannot make connection + @return a new connection + """ + Element.__init__(self, flow_graph) + source = sink = None + #separate the source and sink + for port in (porta, portb): + if port.is_source(): source = port + if port.is_sink(): sink = port + assert(source and sink) + #ensure that this connection (source -> sink) is unique + for connection in self.get_parent().get_connections(): + assert not (connection.get_source() is source and connection.get_sink() is sink) + self._source = source + self._sink = sink + + def __str__(self): + return 'Connection (\n\t%s\n\t\t%s\n\t%s\n\t\t%s\n)'%( + self.get_source().get_parent(), + self.get_source(), + self.get_sink().get_parent(), + self.get_sink(), + ) + + def is_connection(self): return True + + def validate(self): + """ + Validate the connections. + The ports must match in type. + """ + Element.validate(self) + source_type = self.get_source().get_type() + sink_type = self.get_sink().get_type() + 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/base/Constants.py b/grc/base/Constants.py new file mode 100644 index 00000000..ef45be8d --- /dev/null +++ b/grc/base/Constants.py @@ -0,0 +1,25 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import os + +#data files +DATA_DIR = os.path.dirname(__file__) +FLOW_GRAPH_DTD = os.path.join(DATA_DIR, 'flow_graph.dtd') +BLOCK_TREE_DTD = os.path.join(DATA_DIR, 'block_tree.dtd') diff --git a/grc/base/Element.py b/grc/base/Element.py new file mode 100644 index 00000000..16000c46 --- /dev/null +++ b/grc/base/Element.py @@ -0,0 +1,67 @@ +""" +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.flag() + + def test(self): + """ + Test the element against failures. + Overload this method in sub-classes. + """ + pass + + ################################################## + # Element Validation API + ################################################## + def validate(self): self._error_messages = list() + def is_valid(self): return not self.get_error_messages() or not self.get_enabled() + def add_error_message(self, msg): self._error_messages.append(msg) + def get_error_messages(self): return self._error_messages + + def get_enabled(self): return True + + def get_parent(self): return self._parent + + ############################################## + ## 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/base/FlowGraph.py b/grc/base/FlowGraph.py new file mode 100644 index 00000000..ea489e94 --- /dev/null +++ b/grc/base/FlowGraph.py @@ -0,0 +1,227 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from . 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 + """ + #initialize + Element.__init__(self, platform) + #inital blank import + self.import_data() + + def _get_unique_id(self, base_id=''): + """ + Get a unique id starting with the base id. + @param base_id the id starts with this and appends a count + @return a unique id + """ + index = 0 + while True: + id = '%s_%d'%(base_id, index) + index = index + 1 + #make sure that the id is not used by another block + if not filter(lambda b: b.get_id() == id, self.get_blocks()): return id + + def __str__(self): return 'FlowGraph - %s(%s)'%(self.get_option('title'), self.get_option('id')) + + def get_option(self, key): + """ + Get the option for a given key. + The option comes from the special options block. + @param key the param key for the options block + @return the value held by that param + """ + return self._options_block.get_param(key).get_evaluated() + + def is_flow_graph(self): return True + + ############################################## + ## Access Elements + ############################################## + def get_block(self, id): return filter(lambda b: b.get_id() == id, self.get_blocks())[0] + def get_blocks(self): return filter(lambda e: e.is_block(), self.get_elements()) + def get_connections(self): return filter(lambda e: e.is_connection(), self.get_elements()) + def get_elements(self): + """ + Get a list of all the elements. + Always ensure that the options block is in the list (only once). + @return the element list + """ + options_block_count = self._elements.count(self._options_block) + if not options_block_count: + self._elements.append(self._options_block) + for i in range(options_block_count-1): + self._elements.remove(self._options_block) + return self._elements + + def get_enabled_blocks(self): + """ + Get a list of all blocks that are enabled. + @return a list of blocks + """ + return filter(lambda b: b.get_enabled(), self.get_blocks()) + + def get_enabled_connections(self): + """ + Get a list of all connections that are enabled. + @return a list of connections + """ + return filter(lambda c: c.get_enabled(), self.get_connections()) + + def get_new_block(self, key): + """ + Get a new block of the specified key. + Add the block to the list of elements. + @param key the block key + @return the new block or None if not found + """ + 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(self.remove_element, port.get_connections()) + self.get_elements().remove(element) + + def evaluate(self, expr): + """ + Evaluate the expression. + @param expr the string expression + @throw NotImplementedError + """ + raise NotImplementedError + + def validate(self): + """ + Validate the flow graph. + All connections and blocks must be valid. + """ + Element.validate(self) + for c in self.get_elements(): + try: + c.validate() + 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 odict({'flow_graph': n}) + + def import_data(self, n=None): + """ + Import blocks and connections into this flow graph. + Clear this flowgraph of all previous blocks and connections. + Any blocks or connections in error will be ignored. + @param n the nested data odict + """ + #remove previous elements + self._elements = list() + #use blank data if none provided + fg_n = n and n.find('flow_graph') or odict() + blocks_n = fg_n.findall('block') + connections_n = fg_n.findall('connection') + #create option block + self._options_block = self.get_parent().get_new_block(self, 'options') + #build the blocks + for block_n in blocks_n: + key = block_n.find('key') + if key == 'options': block = self._options_block + else: block = self.get_new_block(key) + #only load the block when the block key was valid + if block: block.import_data(block_n) + else: Messages.send_error_load('Block key "%s" not found in %s'%(key, self.get_parent())) + self.validate() #validate all blocks before connections are made (in case of nports) + #build the connections + for connection_n in connections_n: + #try to make the connection + try: + #get the block ids + source_block_id = connection_n.find('source_block_id') + sink_block_id = connection_n.find('sink_block_id') + #get the port keys + source_key = connection_n.find('source_key') + sink_key = connection_n.find('sink_key') + #verify the blocks + block_ids = map(lambda b: b.get_id(), self.get_blocks()) + 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)) diff --git a/grc/base/Makefile.am b/grc/base/Makefile.am new file mode 100644 index 00000000..e489601d --- /dev/null +++ b/grc/base/Makefile.am @@ -0,0 +1,41 @@ +# +# Copyright 2008, 2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +ourpythondir = $(grc_src_prefix)/base +ourpython_PYTHON = \ + odict.py \ + ParseXML.py \ + Block.py \ + Connection.py \ + Constants.py \ + Element.py \ + FlowGraph.py \ + Param.py \ + Platform.py \ + Port.py \ + __init__.py + +ourdatadir = $(grc_src_prefix)/base +dist_ourdata_DATA = \ + block_tree.dtd \ + flow_graph.dtd diff --git a/grc/base/Param.py b/grc/base/Param.py new file mode 100644 index 00000000..8166d54e --- /dev/null +++ b/grc/base/Param.py @@ -0,0 +1,261 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from . import odict +from Element import Element +import pygtk +pygtk.require('2.0') +import gtk + +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 + def set_color(self, color): pass + +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() + def set_color(self, color): self.entry.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color)) + +class EnumParam(InputParam): + """Provide an entry box for Enum types with a drop down menu.""" + + def __init__(self, *args, **kwargs): + InputParam.__init__(self, *args, **kwargs) + self._input = gtk.combo_box_new_text() + for option in self.param.get_options(): self._input.append_text(option.get_name()) + self._input.set_active(self.param.get_option_keys().index(self.param.get_value())) + self._input.connect('changed', self._handle_changed) + self.pack_start(self._input, False) + def get_text(self): return self.param.get_option_keys()[self._input.get_active()] + +class EnumEntryParam(InputParam): + """Provide an entry box and drop down menu for Raw Enum types.""" + + def __init__(self, *args, **kwargs): + InputParam.__init__(self, *args, **kwargs) + self._input = gtk.combo_box_entry_new_text() + for option in self.param.get_options(): self._input.append_text(option.get_name()) + try: self._input.set_active(self.param.get_option_keys().index(self.param.get_value())) + except: + self._input.set_active(-1) + self._input.get_child().set_text(self.param.get_value()) + self._input.connect('changed', self._handle_changed) + self._input.get_child().connect('changed', self._handle_changed) + self.pack_start(self._input, False) + def get_text(self): + if self._input.get_active() == -1: return self._input.get_child().get_text() + return self.param.get_option_keys()[self._input.get_active()] + def set_color(self, color): + if self._input.get_active() == -1: #custom entry, use color + self._input.get_child().modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color)) + else: #from enum, make white background + self._input.get_child().modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse('#ffffff')) + +class Option(Element): + + def __init__(self, param, n): + Element.__init__(self, param) + self._name = n.find('name') + self._key = n.find('key') + self._opts = dict() + opts = n.findall('opt') + #test against opts when non enum + try: assert self.get_parent().is_enum() or not opts + except AssertionError: raise Exception, 'Options for non-enum types cannot have sub-options' + #extract opts + for opt in opts: + #separate the key:value + try: key, value = opt.split(':') + except: raise Exception, 'Error separating "%s" into key:value'%opt + #test against repeated keys + try: assert not self._opts.has_key(key) + except AssertionError: raise Exception, 'Key "%s" already exists in option'%key + #store the option + self._opts[key] = value + + def __str__(self): return 'Option %s(%s)'%(self.get_name(), self.get_key()) + def get_name(self): return self._name + def get_key(self): return self._key + + ############################################## + # Access Opts + ############################################## + def get_opt_keys(self): return self._opts.keys() + def get_opt(self, key): return self._opts[key] + def get_opts(self): return self._opts.values() + +class Param(Element): + + ##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 + self._name = n.find('name') + self._key = n.find('key') + value = n.find('value') or '' + self._type = n.find('type') + self._hide = n.find('hide') or '' + #build the param + Element.__init__(self, block) + #create the Option objects from the n data + self._options = odict() + for option in map(lambda o: Option(self, o), n.findall('option')): + key = option.get_key() + #test against repeated keys + try: assert key not in self.get_option_keys() + except AssertionError: raise Exception, 'Key "%s" already exists in options'%key + #store the option + self._options[key] = option + #test the enum options + if self.is_enum(): + #test against options with identical keys + try: assert len(set(self.get_option_keys())) == len(self._options) + except AssertionError: raise Exception, '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: raise Exception, 'Opt keys "%s" are not identical across all options.'%opt_keys + #if a value is specified, it must be in the options keys + self._value = value or self.get_option_keys()[0] + try: assert self.get_value() in self.get_option_keys() + except AssertionError: raise Exception, 'The value "%s" is not in the possible values of "%s".'%(self.get_value(), self.get_option_keys()) + else: self._value = value or '' + + def 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. + """ + Element.validate(self) + 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 get_evaluated(self): raise NotImplementedError + + def to_code(self): + """ + Convert the value to code. + @throw NotImplementedError + """ + raise NotImplementedError + + def get_color(self): return '#FFFFFF' + def __str__(self): return 'Param - %s(%s)'%(self.get_name(), self.get_key()) + def is_param(self): return True + def get_name(self): return self._name + def get_key(self): return self._key + def get_hide(self): return self.get_parent().resolve_dependencies(self._hide) + + 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 __repr__(self): + """ + Get the repr (nice string format) for this param. + Just return the value (special case enum). + Derived classes can handle complex formatting. + @return the string representation + """ + if self.is_enum(): return self.get_option(self.get_value()).get_name() + return self.get_value() + + def get_input_class(self): + """ + Get the graphical gtk class to represent this parameter. + An enum requires and combo parameter. + A non-enum with options gets a combined entry/combo parameter. + All others get a standard entry parameter. + @return gtk input class + """ + if self.is_enum(): return EnumParam + if self.get_options(): return EnumEntryParam + return EntryParam + + ############################################## + # 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/base/ParseXML.py b/grc/base/ParseXML.py new file mode 100644 index 00000000..078ebd07 --- /dev/null +++ b/grc/base/ParseXML.py @@ -0,0 +1,102 @@ +""" +Copyright 2008 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from lxml import etree +from . import odict + +class XMLSyntaxError(Exception): + def __init__(self, error_log): + self._error_log = error_log + def __str__(self): + return '\n'.join(map(str, self._error_log.filter_from_errors())) + +def validate_dtd(xml_file, dtd_file=None): + """ + Validate an xml file against its dtd. + @param xml_file the xml file + @param dtd_file the optional dtd file + @throws Exception validation fails + """ + #perform parsing, use dtd validation if dtd file is not specified + parser = etree.XMLParser(dtd_validation=not dtd_file) + xml = etree.parse(xml_file, parser=parser) + if parser.error_log: raise XMLSyntaxError(parser.error_log) + #perform dtd validation if the dtd file is specified + if not dtd_file: return + dtd = etree.DTD(dtd_file) + if not dtd.validate(xml.getroot()): raise XMLSyntaxError(dtd.error_log) + +def from_file(xml_file): + """ + Create nested data from an xml file using the from xml helper. + @param xml_file the xml file path + @return the nested data + """ + xml = etree.parse(xml_file).getroot() + return _from_file(xml) + +def _from_file(xml): + """ + Recursivly parse the xml tree into nested data format. + @param xml the xml tree + @return the nested data + """ + tag = xml.tag + if not len(xml): + return odict({tag: xml.text or ''}) #store empty tags (text is None) as empty string + nested_data = odict() + for elem in xml: + key, value = _from_file(elem).items()[0] + if nested_data.has_key(key): nested_data[key].append(value) + else: nested_data[key] = [value] + #delistify if the length of values is 1 + for key, values in nested_data.iteritems(): + if len(values) == 1: nested_data[key] = values[0] + return odict({tag: nested_data}) + +def to_file(nested_data, xml_file): + """ + Write an xml file and use the to xml helper method to load it. + @param nested_data the nested data + @param xml_file the xml file path + """ + xml = _to_file(nested_data)[0] + open(xml_file, 'w').write(etree.tostring(xml, xml_declaration=True, pretty_print=True)) + +def _to_file(nested_data): + """ + Recursivly parse the nested data into xml tree format. + @param nested_data the nested data + @return the xml tree filled with child nodes + """ + nodes = list() + for key, values in nested_data.iteritems(): + #listify the values if not a list + if not isinstance(values, (list, set, tuple)): + values = [values] + for value in values: + node = etree.Element(key) + if isinstance(value, (str, unicode)): node.text = value + else: node.extend(_to_file(value)) + nodes.append(node) + return nodes + +if __name__ == '__main__': + """Use the main method to test parse xml's functions.""" + pass diff --git a/grc/base/Platform.py b/grc/base/Platform.py new file mode 100644 index 00000000..6cbe741d --- /dev/null +++ b/grc/base/Platform.py @@ -0,0 +1,174 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import os +import sys +from .. base import ParseXML +from Element import Element as _Element +from FlowGraph import FlowGraph as _FlowGraph +from Connection import Connection as _Connection +from Block import Block as _Block +from Port import Port as _Port +from Param import Param as _Param +from Constants import BLOCK_TREE_DTD, FLOW_GRAPH_DTD + +class Platform(_Element): + + def __init__(self, name, version, key, + block_paths, block_dtd, default_flow_graph, generator, + license='', website=None, colors=[]): + """ + Make a platform from the arguments. + @param name the platform name + @param version the version string + @param key the unique platform key + @param block_paths the file paths to blocks in this platform + @param block_dtd the dtd validator for xml block wrappers + @param default_flow_graph the default flow graph file path + @param generator the generator class for this platform + @param colors a list of title, color_spec tuples + @param license a multi-line license (first line is copyright) + @param website the website url for this platform + @return a platform object + """ + _Element.__init__(self) + self._name = name + self._version = version + self._key = key + self._license = license + self._website = website + self._block_paths = block_paths + self._block_dtd = block_dtd + self._default_flow_graph = default_flow_graph + self._generator = generator + self._colors = colors + #create a dummy flow graph for the blocks + self._flow_graph = _Element(self) + #search for *.xml files in the given search path + xml_files = list() + for block_path in self._block_paths: + if os.path.isfile(block_path): xml_files.append(block_path) + elif os.path.isdir(block_path): + for dirpath, dirnames, filenames in os.walk(block_path): + for filename in filter(lambda f: f.endswith('.xml'), filenames): + xml_files.append(os.path.join(dirpath, filename)) + #load the blocks + self._blocks = dict() + self._blocks_n = dict() + self._block_tree_files = list() + for xml_file in xml_files: + try: #try to add the xml file as a block wrapper + ParseXML.validate_dtd(xml_file, self._block_dtd) + n = ParseXML.from_file(xml_file).find('block') + #inject block wrapper path + n['block_wrapper_path'] = xml_file + block = self.Block(self._flow_graph, n) + key = block.get_key() + #test against repeated keys + try: + assert key not in self.get_block_keys() + #store the block + self._blocks[key] = block + self._blocks_n[key] = n + except AssertionError: + print >> sys.stderr, 'Warning: Block with key "%s" already exists.\n\tIgnoring: %s'%(key, xml_file) + except ParseXML.XMLSyntaxError, e: + try: #try to add the xml file as a block tree + ParseXML.validate_dtd(xml_file, BLOCK_TREE_DTD) + self._block_tree_files.append(xml_file) + except ParseXML.XMLSyntaxError, e: + print >> sys.stderr, 'Warning: Block validation failed:\n\t%s\n\tIgnoring: %s'%(e, xml_file) + except Exception, e: + print >> sys.stderr, 'Warning: Block loading failed:\n\t%s\n\tIgnoring: %s'%(e, xml_file) + + def parse_flow_graph(self, flow_graph_file): + """ + Parse a saved flow graph file. + Ensure that the file exists, and passes the dtd check. + @param flow_graph_file the flow graph file + @return nested data + @throws exception if the validation fails + """ + flow_graph_file = flow_graph_file or self._default_flow_graph + open(flow_graph_file, 'r') #test open + ParseXML.validate_dtd(flow_graph_file, FLOW_GRAPH_DTD) + return ParseXML.from_file(flow_graph_file) + + def load_block_tree(self, block_tree): + """ + Load a block tree with categories and blocks. + Step 1: Load all blocks from the xml specification. + Step 2: Load blocks with builtin category specifications. + @param block_tree the block tree object + """ + #recursive function to load categories and blocks + def load_category(cat_n, parent=[]): + #add this category + parent = parent + [cat_n.find('name')] + block_tree.add_block(parent) + #recursive call to load sub categories + map(lambda c: load_category(c, parent), cat_n.findall('cat')) + #add blocks in this category + for block_key in cat_n.findall('block'): + if block_key not in self.get_block_keys(): + print >> sys.stderr, 'Warning: Block key "%s" not found when loading category tree.'%(block_key) + continue + block_tree.add_block(parent, self.get_block(block_key)) + #load the block tree + for block_tree_file in self._block_tree_files: + #recursivly add all blocks in the tree + load_category(ParseXML.from_file(block_tree_file).find('cat')) + #add all other blocks, use the catgory tag + for block in self.get_blocks(): + #blocks with empty categories are in the xml block tree or hidden + if not block.get_category(): continue + block_tree.add_block(block.get_category(), block) + + def __str__(self): return 'Platform - %s(%s)'%(self.get_key(), self.get_name()) + + def is_platform(self): return True + + def get_new_flow_graph(self): return self.FlowGraph(self) + + def get_generator(self): return self._generator + + ############################################## + # Access Blocks + ############################################## + def get_block_keys(self): return self._blocks.keys() + def get_block(self, key): return self._blocks[key] + def get_blocks(self): return self._blocks.values() + def get_new_block(self, flow_graph, key): return self.Block(flow_graph, n=self._blocks_n[key]) + + def get_name(self): return self._name + def get_version(self): return self._version + def get_key(self): return self._key + def get_license(self): return self._license + def get_website(self): return self._website + def get_colors(self): return self._colors + + ############################################## + # Constructors + ############################################## + FlowGraph = _FlowGraph + Connection = _Connection + Block = _Block + Source = _Port + Sink = _Port + Param = _Param diff --git a/grc/base/Port.py b/grc/base/Port.py new file mode 100644 index 00000000..f4e8e5e1 --- /dev/null +++ b/grc/base/Port.py @@ -0,0 +1,81 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from Element import Element + +class 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. + """ + Element.validate(self) + 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 get_enabled_connections(self): + """ + Get all enabled connections that use this port. + @return a list of connection objects + """ + return filter(lambda c: c.get_enabled(), self.get_connections()) diff --git a/grc/base/__init__.py b/grc/base/__init__.py new file mode 100644 index 00000000..2682db81 --- /dev/null +++ b/grc/base/__init__.py @@ -0,0 +1,20 @@ +""" +Copyright 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from odict import odict diff --git a/grc/base/block_tree.dtd b/grc/base/block_tree.dtd new file mode 100644 index 00000000..be1524a3 --- /dev/null +++ b/grc/base/block_tree.dtd @@ -0,0 +1,26 @@ + + + + + diff --git a/grc/base/flow_graph.dtd b/grc/base/flow_graph.dtd new file mode 100644 index 00000000..904147b3 --- /dev/null +++ b/grc/base/flow_graph.dtd @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + diff --git a/grc/base/odict.py b/grc/base/odict.py new file mode 100644 index 00000000..ac3cb207 --- /dev/null +++ b/grc/base/odict.py @@ -0,0 +1,93 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from UserDict import DictMixin + +class odict(DictMixin): + + def __init__(self, d={}): + self._keys = list(d.keys()) + self._data = dict(d.copy()) + + def __setitem__(self, key, value): + if key not in self._data: + self._keys.append(key) + self._data[key] = value + + def __getitem__(self, key): + return self._data[key] + + def __delitem__(self, key): + del self._data[key] + self._keys.remove(key) + + def keys(self): + return list(self._keys) + + def copy(self): + copy_dict = odict() + copy_dict._data = self._data.copy() + copy_dict._keys = list(self._keys) + return copy_dict + + def insert_after(self, pos_key, key, val): + """ + Insert the new key, value entry after the entry given by the position key. + If the positional key is None, insert at the end. + @param pos_key the positional key + @param key the key for the new entry + @param val the value for the new entry + """ + index = (pos_key is None) and len(self._keys) or self._keys.index(pos_key) + assert key not in self._keys + self._keys.insert(index+1, key) + self._data[key] = val + + def insert_before(self, pos_key, key, val): + """ + Insert the new key, value entry before the entry given by the position key. + If the positional key is None, insert at the begining. + @param pos_key the positional key + @param key the key for the new entry + @param val the value for the new entry + """ + index = (pos_key is not None) and self._keys.index(pos_key) or 0 + assert key not in self._keys + self._keys.insert(index, key) + self._data[key] = val + + def find(self, key): + """ + Get the value for this key if exists. + @param key the key to search for + @return the value or None + """ + if self.has_key(key): return self[key] + return None + + def findall(self, key): + """ + Get a list of values for this key. + @param key the key to search for + @return a list of values or empty list + """ + obj = self.find(key) + if obj is None: obj = list() + if isinstance(obj, list): return obj + return [obj] diff --git a/grc/blocks/Makefile.am b/grc/blocks/Makefile.am new file mode 100644 index 00000000..d6df9fca --- /dev/null +++ b/grc/blocks/Makefile.am @@ -0,0 +1,224 @@ +# +# Copyright 2008, 2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +ourdatadir = $(grc_blocksdir) +dist_ourdata_DATA = \ + block_tree.xml \ + audio_sink.xml \ + audio_source.xml \ + band_pass_filter.xml \ + band_reject_filter.xml \ + blks2_am_demod_cf.xml \ + blks2_analysis_filterbank.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_ofdm_demod.xml \ + blks2_ofdm_mod.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_tcp_sink.xml \ + blks2_tcp_source.xml \ + blks2_valve.xml \ + blks2_variable_sink_x.xml \ + blks2_wfm_rcv.xml \ + blks2_wfm_rcv_pll.xml \ + blks2_wfm_tx.xml \ + const_source_x.xml \ + gr_add_const_vxx.xml \ + gr_add_xx.xml \ + gr_agc2_xx.xml \ + gr_agc_xx.xml \ + gr_and_xx.xml \ + gr_argmax_xx.xml \ + gr_binary_slicer_fb.xml \ + gr_channel_model.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_descrambler_bb.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_xx.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_probe_avg_mag_sqrd_x.xml \ + gr_probe_density_b.xml \ + gr_probe_mpsk_snr_c.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_scrambler_bb.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 \ + probe_function.xml \ + random_source_x.xml \ + root_raised_cosine_filter.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 \ + usrp2_probe.xml \ + usrp2_sink_xxxx.xml \ + usrp2_source_xxxx.xml \ + usrp_dual_sink_x.xml \ + usrp_dual_source_x.xml \ + usrp_probe.xml \ + usrp_simple_sink_x.xml \ + usrp_simple_source_x.xml \ + variable.xml \ + variable_check_box.xml \ + variable_chooser.xml \ + variable_config.xml \ + variable_slider.xml \ + variable_static_text.xml \ + variable_text_box.xml \ + wxgui_constellationsink2.xml \ + wxgui_fftsink2.xml \ + wxgui_histosink2.xml \ + wxgui_numbersink2.xml \ + wxgui_scopesink2.xml \ + wxgui_waterfallsink2.xml \ + xmlrpc_client.xml \ + xmlrpc_server.xml diff --git a/grc/blocks/audio_sink.xml b/grc/blocks/audio_sink.xml new file mode 100644 index 00000000..75d58347 --- /dev/null +++ b/grc/blocks/audio_sink.xml @@ -0,0 +1,85 @@ + + + + Audio Sink + audio_sink + from gnuradio import audio + audio.sink($samp_rate, $device_name, $ok_to_block) + + Sample Rate + samp_rate + 32000 + int + + + + + + + + + Device Name + device_name + + string + #if $device_name() then 'none' else 'part'# + + + OK to Block + ok_to_block + True + enum + part + + + + + 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. \ +ALSA users with audio trouble may try setting the device name to plughw: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/blocks/audio_source.xml b/grc/blocks/audio_source.xml new file mode 100644 index 00000000..1f5d1033 --- /dev/null +++ b/grc/blocks/audio_source.xml @@ -0,0 +1,85 @@ + + + + Audio Source + audio_source + from gnuradio import audio + audio.source($samp_rate, $device_name, $ok_to_block) + + Sample Rate + samp_rate + 32000 + int + + + + + + + + + Device Name + device_name + + string + #if $device_name() then 'none' else 'part'# + + + OK to Block + ok_to_block + True + enum + part + + + + + 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. \ +ALSA users with audio trouble may try setting the device name to plughw: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/blocks/band_pass_filter.xml b/grc/blocks/band_pass_filter.xml new file mode 100644 index 00000000..e2e9acf4 --- /dev/null +++ b/grc/blocks/band_pass_filter.xml @@ -0,0 +1,165 @@ + + + + Band Pass Filter + band_pass_filter + from gnuradio import gr + from gnuradio.gr import firdes + gr.$(type)(#if str($type).startswith('interp') then $interp else $decim#, firdes.$(type.fcn)( + $gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, firdes.$window, $beta)) + set_taps(firdes.$(type.fcn)($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, firdes.$window, $beta)) + + FIR Type + type + enum + + + + + + + + + + + + + Decimation + decim + 1 + int + #if str($type).startswith('interp') then 'all' else 'none'# + + + Interpolation + interp + 1 + int + #if str($type).startswith('interp') then 'none' else 'all'# + + + 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. + +Sample rate, cutoff frequency, and transition width are in Hertz. + +The beta paramater only applies to the Kaiser window. + + diff --git a/grc/blocks/band_reject_filter.xml b/grc/blocks/band_reject_filter.xml new file mode 100644 index 00000000..3b58f0b5 --- /dev/null +++ b/grc/blocks/band_reject_filter.xml @@ -0,0 +1,131 @@ + + + + Band Reject Filter + band_reject_filter + from gnuradio import gr + from gnuradio.gr import firdes + gr.$(type)(#if str($type).startswith('interp') then $interp else $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 + #if str($type).startswith('interp') then 'all' else 'none'# + + + Interpolation + interp + 1 + int + #if str($type).startswith('interp') then 'none' else 'all'# + + + 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. + +Sample rate, cutoff frequency, and transition width are in Hertz. + +The beta paramater only applies to the Kaiser window. + + diff --git a/grc/blocks/blks2_am_demod_cf.xml b/grc/blocks/blks2_am_demod_cf.xml new file mode 100644 index 00000000..898c613b --- /dev/null +++ b/grc/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/blocks/blks2_analysis_filterbank.xml b/grc/blocks/blks2_analysis_filterbank.xml new file mode 100644 index 00000000..93cfa30a --- /dev/null +++ b/grc/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/blocks/blks2_dxpsk_demod.xml b/grc/blocks/blks2_dxpsk_demod.xml new file mode 100644 index 00000000..4c13b341 --- /dev/null +++ b/grc/blocks/blks2_dxpsk_demod.xml @@ -0,0 +1,127 @@ + + + + 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, + verbose=$verbose, + log=$log, +) + + 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 + + + + + Verbose + verbose + False + bool + #if str($verbose) == 'False' then 'part' else 'none'# + + + + + Logging + log + False + bool + #if str($log) == 'False' then 'part' else 'none'# + + + + + in + complex + + + out + byte + + diff --git a/grc/blocks/blks2_dxpsk_mod.xml b/grc/blocks/blks2_dxpsk_mod.xml new file mode 100644 index 00000000..28fd742f --- /dev/null +++ b/grc/blocks/blks2_dxpsk_mod.xml @@ -0,0 +1,99 @@ + + + + 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, + verbose=$verbose, + log=$log, +) + + Type + type + enum + + + + + + Samples/Symbol + samples_per_symbol + 2 + int + + + Excess BW + excess_bw + 0.35 + real + + + Gray Code + gray_code + True + enum + + + + + Verbose + verbose + False + bool + #if str($verbose) == 'False' then 'part' else 'none'# + + + + + Logging + log + False + bool + #if str($log) == 'False' then 'part' else 'none'# + + + + + in + byte + + + out + complex + + diff --git a/grc/blocks/blks2_error_rate.xml b/grc/blocks/blks2_error_rate.xml new file mode 100644 index 00000000..91a30320 --- /dev/null +++ b/grc/blocks/blks2_error_rate.xml @@ -0,0 +1,69 @@ + + + + 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 + $type.hide_bps + + + 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/blocks/blks2_fm_deemph.xml b/grc/blocks/blks2_fm_deemph.xml new file mode 100644 index 00000000..6f38dab6 --- /dev/null +++ b/grc/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/blocks/blks2_fm_demod_cf.xml b/grc/blocks/blks2_fm_demod_cf.xml new file mode 100644 index 00000000..2ce1fb97 --- /dev/null +++ b/grc/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/blocks/blks2_fm_preemph.xml b/grc/blocks/blks2_fm_preemph.xml new file mode 100644 index 00000000..672a7a7b --- /dev/null +++ b/grc/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/blocks/blks2_gmsk_demod.xml b/grc/blocks/blks2_gmsk_demod.xml new file mode 100644 index 00000000..13ecb334 --- /dev/null +++ b/grc/blocks/blks2_gmsk_demod.xml @@ -0,0 +1,88 @@ + + + + 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, + verbose=$verbose, + log=$log, +) + + 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 + + + Verbose + verbose + False + bool + #if str($verbose) == 'False' then 'part' else 'none'# + + + + + Logging + log + False + bool + #if str($log) == 'False' then 'part' else 'none'# + + + + + in + complex + + + out + byte + + diff --git a/grc/blocks/blks2_gmsk_mod.xml b/grc/blocks/blks2_gmsk_mod.xml new file mode 100644 index 00000000..e80264f1 --- /dev/null +++ b/grc/blocks/blks2_gmsk_mod.xml @@ -0,0 +1,67 @@ + + + + GMSK Mod + blks2_gmsk_mod + from gnuradio import blks2 + blks2.gmsk_mod( + samples_per_symbol=$samples_per_symbol, + bt=$bt, + verbose=$verbose, + log=$log, +) + + Samples/Symbol + samples_per_symbol + 2 + int + + + BT + bt + 0.35 + real + + + Verbose + verbose + False + bool + #if str($verbose) == 'False' then 'part' else 'none'# + + + + + Logging + log + False + bool + #if str($log) == 'False' then 'part' else 'none'# + + + + + in + byte + + + out + complex + + diff --git a/grc/blocks/blks2_logpwrfft_x.xml b/grc/blocks/blks2_logpwrfft_x.xml new file mode 100644 index 00000000..79a3bfc4 --- /dev/null +++ b/grc/blocks/blks2_logpwrfft_x.xml @@ -0,0 +1,90 @@ + + + + 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) + set_average($average) + + 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 + average + False + bool + + + + + Average Alpha + avg_alpha + 1.0 + real + + + in + $type + + + out + float + $fft_size + + diff --git a/grc/blocks/blks2_nbfm_rx.xml b/grc/blocks/blks2_nbfm_rx.xml new file mode 100644 index 00000000..d332b9a6 --- /dev/null +++ b/grc/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/blocks/blks2_nbfm_tx.xml b/grc/blocks/blks2_nbfm_tx.xml new file mode 100644 index 00000000..3aa7ede0 --- /dev/null +++ b/grc/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/blocks/blks2_ofdm_demod.xml b/grc/blocks/blks2_ofdm_demod.xml new file mode 100644 index 00000000..ac5ee479 --- /dev/null +++ b/grc/blocks/blks2_ofdm_demod.xml @@ -0,0 +1,122 @@ + + + + OFDM Demod + blks2_ofdm_demod + from grc_gnuradio import blks2 as grc_blks2 + from gnuradio import blks2 + grc_blks2.packet_demod_$(type.fcn)(blks2.ofdm_demod( + options=grc_blks2.options( + modulation="$modulation", + fft_length=$fft_length, + occupied_tones=$occupied_tones, + cp_length=$cp_length, + snr=$snr, + log=None, + verbose=None, + ), + callback=lambda ok, payload: self.$(id).recv_pkt(ok, payload), + ), +) + + Output Type + type + float + enum + + + + + + + + Modulation + modulation + enum + + + + + + + + + + FFT Length + fft_length + 512 + int + + + Occupied Tones + occupied_tones + 200 + int + + + Cyclic Prefix Length + cp_length + 128 + int + + + SNR + snr + 10 + real + + + in + complex + + + out + $type + + Payload Length: 0 for automatic. + diff --git a/grc/blocks/blks2_ofdm_mod.xml b/grc/blocks/blks2_ofdm_mod.xml new file mode 100644 index 00000000..2c54d10f --- /dev/null +++ b/grc/blocks/blks2_ofdm_mod.xml @@ -0,0 +1,135 @@ + + + + OFDM Mod + blks2_ofdm_mod + from grc_gnuradio import blks2 as grc_blks2 + from gnuradio import blks2 + grc_blks2.packet_mod_$(type.fcn)(blks2.ofdm_mod( + options=grc_blks2.options( + modulation="$modulation", + fft_length=$fft_length, + occupied_tones=$occupied_tones, + cp_length=$cp_length, + pad_for_usrp=$pad_for_usrp, + log=None, + verbose=None, + ), + ), + payload_length=$payload_length, +) + + Input Type + type + float + enum + + + + + + + + Modulation + modulation + enum + + + + + + + + + + FFT Length + fft_length + 512 + int + + + Occupied Tones + occupied_tones + 200 + int + + + Cyclic Prefix Length + cp_length + 128 + int + + + Pad for USRP + pad_for_usrp + enum + + + + + Payload Length + payload_length + 0 + int + + + in + $type + + + out + complex + + Payload Length: 0 for automatic. + diff --git a/grc/blocks/blks2_packet_decoder.xml b/grc/blocks/blks2_packet_decoder.xml new file mode 100644 index 00000000..07b0d1f2 --- /dev/null +++ b/grc/blocks/blks2_packet_decoder.xml @@ -0,0 +1,75 @@ + + + + Packet Decoder + blks2_packet_decoder + from grc_gnuradio import blks2 as grc_blks2 + grc_blks2.packet_demod_$(type.fcn)(grc_blks2.packet_decoder( + access_code=$access_code, + threshold=$threshold, + callback=lambda ok, payload: self.$(id).recv_pkt(ok, payload), + ), +) + + Output Type + type + float + enum + + + + + + + + Access Code + access_code + + string + + + Threshold + threshold + -1 + int + + + in + byte + + + out + $type + + +Packet decoder block, for use with the gnuradio demodulator blocks: gmsk, psk, qam. + +Access Code: string of 1's and 0's, leave blank for automatic. + +Threshold: -1 for automatic. + + diff --git a/grc/blocks/blks2_packet_encoder.xml b/grc/blocks/blks2_packet_encoder.xml new file mode 100644 index 00000000..b184ebd3 --- /dev/null +++ b/grc/blocks/blks2_packet_encoder.xml @@ -0,0 +1,110 @@ + + + + Packet Encoder + blks2_packet_encoder + from grc_gnuradio import blks2 as grc_blks2 + grc_blks2.packet_mod_$(type.fcn)(grc_blks2.packet_encoder( + samples_per_symbol=$samples_per_symbol, + bits_per_symbol=$bits_per_symbol, + access_code=$access_code, + pad_for_usrp=$pad_for_usrp, + ), + payload_length=$payload_length, +) + + 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 + 0 + int + + + in + $type + + + out + byte + + +Packet encoder block, for use with the gnuradio modulator blocks: gmsk, dpsk, qam. + +Access Code: string of 1's and 0's, leave blank for automatic. + +Payload Length: 0 for automatic. + +Bits/Symbol should be set accordingly: + gmsk -> 1 + dbpsk -> 1 + dqpsk -> 2 + d8psk -> 3 + qam8 -> 3 + qam16 -> 4 + qam64 -> 6 + qam256 -> 8 + + diff --git a/grc/blocks/blks2_qamx_demod.xml b/grc/blocks/blks2_qamx_demod.xml new file mode 100644 index 00000000..e332495a --- /dev/null +++ b/grc/blocks/blks2_qamx_demod.xml @@ -0,0 +1,131 @@ + + + + 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, + verbose=$verbose, + log=$log, +) + + 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 + + + + + Verbose + verbose + False + bool + #if str($verbose) == 'False' then 'part' else 'none'# + + + + + Logging + log + False + bool + #if str($log) == 'False' then 'part' else 'none'# + + + + + in + complex + + + out + byte + + diff --git a/grc/blocks/blks2_qamx_mod.xml b/grc/blocks/blks2_qamx_mod.xml new file mode 100644 index 00000000..69a2e9e7 --- /dev/null +++ b/grc/blocks/blks2_qamx_mod.xml @@ -0,0 +1,103 @@ + + + + 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, + verbose=$verbose, + log=$log, +) + + Type + type + enum + + + + + + + Samples/Symbol + samples_per_symbol + 2 + int + + + Excess BW + excess_bw + 0.35 + real + + + Gray Code + gray_code + True + enum + + + + + Verbose + verbose + False + bool + #if str($verbose) == 'False' then 'part' else 'none'# + + + + + Logging + log + False + bool + #if str($log) == 'False' then 'part' else 'none'# + + + + + in + byte + + + out + complex + + diff --git a/grc/blocks/blks2_rational_resampler_xxx.xml b/grc/blocks/blks2_rational_resampler_xxx.xml new file mode 100644 index 00000000..b92ec8ec --- /dev/null +++ b/grc/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() + taps=$taps, +#else + taps=None, +#end if +#if $fractional_bw() != 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/blocks/blks2_selector.xml b/grc/blocks/blks2_selector.xml new file mode 100644 index 00000000..2d89df18 --- /dev/null +++ b/grc/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(int($input_index)) + set_output_index(int($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/blocks/blks2_standard_squelch.xml b/grc/blocks/blks2_standard_squelch.xml new file mode 100644 index 00000000..fc60a31e --- /dev/null +++ b/grc/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/blocks/blks2_stream_to_vector_decimator.xml b/grc/blocks/blks2_stream_to_vector_decimator.xml new file mode 100644 index 00000000..25f8f7a6 --- /dev/null +++ b/grc/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/blocks/blks2_synthesis_filterbank.xml b/grc/blocks/blks2_synthesis_filterbank.xml new file mode 100644 index 00000000..5979ed3f --- /dev/null +++ b/grc/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/blocks/blks2_tcp_sink.xml b/grc/blocks/blks2_tcp_sink.xml new file mode 100644 index 00000000..cfe7b42d --- /dev/null +++ b/grc/blocks/blks2_tcp_sink.xml @@ -0,0 +1,89 @@ + + + + TCP Sink + blks2_tcp_sink + from grc_gnuradio import blks2 as grc_blks2 + grc_blks2.tcp_sink( + itemsize=$type.size*$vlen, + addr=$addr, + port=$port, + server=$server, +) + + Input Type + type + enum + + + + + + + + Address + addr + 127.0.0.1 + string + + + Port + port + 0 + int + + + Mode + server + False + enum + + + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + +In client mode, we attempt to connect to a server at the given address and port. \ +In server mode, we bind a socket to the given address and port and accept the first client. + + diff --git a/grc/blocks/blks2_tcp_source.xml b/grc/blocks/blks2_tcp_source.xml new file mode 100644 index 00000000..6bf742aa --- /dev/null +++ b/grc/blocks/blks2_tcp_source.xml @@ -0,0 +1,89 @@ + + + + TCP Source + blks2_tcp_source + from grc_gnuradio import blks2 as grc_blks2 + grc_blks2.tcp_source( + itemsize=$type.size*$vlen, + addr=$addr, + port=$port, + server=$server, +) + + Output Type + type + enum + + + + + + + + Address + addr + 127.0.0.1 + string + + + Port + port + 0 + int + + + Mode + server + True + enum + + + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + out + $type + $vlen + + +In client mode, we attempt to connect to a server at the given address and port. \ +In server mode, we bind a socket to the given address and port and accept the first client. + + diff --git a/grc/blocks/blks2_valve.xml b/grc/blocks/blks2_valve.xml new file mode 100644 index 00000000..47c55352 --- /dev/null +++ b/grc/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/blocks/blks2_variable_sink_x.xml b/grc/blocks/blks2_variable_sink_x.xml new file mode 100644 index 00000000..5709c9f7 --- /dev/null +++ b/grc/blocks/blks2_variable_sink_x.xml @@ -0,0 +1,77 @@ + + + + Variable Sink + blks2_variable_sink_x + from grc_gnuradio import blks2 as grc_blks2 + grc_blks2.variable_sink_$(type.fcn)( + vlen=$vlen, + decim=$decim, + callback=self.set_$(variable()), +) + set_decim($decim) + + Type + type + enum + + + + + + + + Variable + variable + + string + + + Decimation + decim + 1 + int + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + +Read samples from the input stream and \ +write one in every decimation samples to the variable. + +The variable must be the id of an existing variable block. + + diff --git a/grc/blocks/blks2_wfm_rcv.xml b/grc/blocks/blks2_wfm_rcv.xml new file mode 100644 index 00000000..37fb3ba8 --- /dev/null +++ b/grc/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/blocks/blks2_wfm_rcv_pll.xml b/grc/blocks/blks2_wfm_rcv_pll.xml new file mode 100644 index 00000000..2771350c --- /dev/null +++ b/grc/blocks/blks2_wfm_rcv_pll.xml @@ -0,0 +1,37 @@ + + + + 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 + + + Lout + float + + + Rout + float + + diff --git a/grc/blocks/blks2_wfm_tx.xml b/grc/blocks/blks2_wfm_tx.xml new file mode 100644 index 00000000..cff92d81 --- /dev/null +++ b/grc/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/blocks/block_tree.xml b/grc/blocks/block_tree.xml new file mode 100644 index 00000000..4f9b1cd2 --- /dev/null +++ b/grc/blocks/block_tree.xml @@ -0,0 +1,297 @@ + + + + + + Sources + const_source_x + 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 + blks2_tcp_source + gr_udp_source + audio_source + gr_wavfile_source + pad_source + + + Sinks + blks2_variable_sink_x + gr_vector_sink_x + gr_null_sink + gr_file_sink + blks2_tcp_sink + gr_udp_sink + audio_sink + gr_wavfile_sink + pad_sink + + + Graphical Sinks + wxgui_numbersink2 + wxgui_scopesink2 + wxgui_fftsink2 + wxgui_constellationsink2 + wxgui_waterfallsink2 + wxgui_histosink2 + + + Operators + gr_add_xx + gr_sub_xx + gr_multiply_xx + 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 + + blks2_packet_decoder + blks2_packet_encoder + + + 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 + root_raised_cosine_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 + gr_channel_model + + blks2_synthesis_filterbank + blks2_analysis_filterbank + + 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_ofdm_mod + blks2_ofdm_demod + + + Error Correction + + Trellis + trellis_encoder_xx + trellis_metrics_x + trellis_permutation + trellis_siso_combined_f + trellis_siso_f + trellis_viterbi_combined_xx + trellis_viterbi_x + + + gr_encode_ccsds_27_bb + gr_decode_ccsds_27_fb + + + Line Coding + gr_scrambler_bb + gr_descrambler_bb + + + Probes + gr_probe_avg_mag_sqrd_x + gr_probe_density_b + gr_probe_mpsk_snr_c + probe_function + + + USRP + usrp_simple_source_x + usrp_simple_sink_x + usrp_dual_source_x + usrp_dual_sink_x + usrp2_source_xxxx + usrp2_sink_xxxx + + + Variables + variable + variable_slider + variable_chooser + variable_check_box + variable_text_box + variable_static_text + variable_config + 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/blocks/const_source_x.xml b/grc/blocks/const_source_x.xml new file mode 100644 index 00000000..fe8e56ec --- /dev/null +++ b/grc/blocks/const_source_x.xml @@ -0,0 +1,52 @@ + + + + Constant Source + const_source_x + from gnuradio import gr + gr.sig_source_$(type.fcn)(0, gr.GR_CONST_WAVE, 0, 0, $const) + set_offset($const) + + Output Type + type + enum + + + + + + + Constant + const + 0 + $type.const_type + + + out + $type + + diff --git a/grc/blocks/gr_add_const_vxx.xml b/grc/blocks/gr_add_const_vxx.xml new file mode 100644 index 00000000..9f1c545a --- /dev/null +++ b/grc/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/blocks/gr_add_xx.xml b/grc/blocks/gr_add_xx.xml new file mode 100644 index 00000000..97ed9283 --- /dev/null +++ b/grc/blocks/gr_add_xx.xml @@ -0,0 +1,63 @@ + + + + Add + gr_add_xx + 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/blocks/gr_agc2_xx.xml b/grc/blocks/gr_agc2_xx.xml new file mode 100644 index 00000000..fb3ae570 --- /dev/null +++ b/grc/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/blocks/gr_agc_xx.xml b/grc/blocks/gr_agc_xx.xml new file mode 100644 index 00000000..c87d239e --- /dev/null +++ b/grc/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/blocks/gr_and_xx.xml b/grc/blocks/gr_and_xx.xml new file mode 100644 index 00000000..9ed00609 --- /dev/null +++ b/grc/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/blocks/gr_argmax_xx.xml b/grc/blocks/gr_argmax_xx.xml new file mode 100644 index 00000000..e3e4e3ea --- /dev/null +++ b/grc/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/blocks/gr_binary_slicer_fb.xml b/grc/blocks/gr_binary_slicer_fb.xml new file mode 100644 index 00000000..85d71e70 --- /dev/null +++ b/grc/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/blocks/gr_channel_model.xml b/grc/blocks/gr_channel_model.xml new file mode 100644 index 00000000..e23062df --- /dev/null +++ b/grc/blocks/gr_channel_model.xml @@ -0,0 +1,61 @@ + + + + Channel Model + gr_channel_model + from gnuradio import gr + from gnuradio.gr import firdes + gr.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) + set_timing_offset($epsilon) + + Noise Voltage + noise_voltage + 0.0 + real + + + Frequency Offset + freq_offset + 0.0 + real + + + Epsilon + epsilon + 1.0 + real + + + Taps + taps + 1.0 + 1.0j + complex_vector + + + Seed + seed + 42 + int + + + in + complex + + + out + complex + + diff --git a/grc/blocks/gr_char_to_float.xml b/grc/blocks/gr_char_to_float.xml new file mode 100644 index 00000000..9ab77805 --- /dev/null +++ b/grc/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/blocks/gr_chunks_to_symbols.xml b/grc/blocks/gr_chunks_to_symbols.xml new file mode 100644 index 00000000..b54e710e --- /dev/null +++ b/grc/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/blocks/gr_clock_recovery_mm_xx.xml b/grc/blocks/gr_clock_recovery_mm_xx.xml new file mode 100644 index 00000000..613cc23b --- /dev/null +++ b/grc/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/blocks/gr_cma_equalizer_cc.xml b/grc/blocks/gr_cma_equalizer_cc.xml new file mode 100644 index 00000000..142fb6d8 --- /dev/null +++ b/grc/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/blocks/gr_complex_to_arg.xml b/grc/blocks/gr_complex_to_arg.xml new file mode 100644 index 00000000..a7bbacd7 --- /dev/null +++ b/grc/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/blocks/gr_complex_to_float.xml b/grc/blocks/gr_complex_to_float.xml new file mode 100644 index 00000000..5b02c3d3 --- /dev/null +++ b/grc/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/blocks/gr_complex_to_imag.xml b/grc/blocks/gr_complex_to_imag.xml new file mode 100644 index 00000000..7c120eed --- /dev/null +++ b/grc/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/blocks/gr_complex_to_interleaved_short.xml b/grc/blocks/gr_complex_to_interleaved_short.xml new file mode 100644 index 00000000..5e999599 --- /dev/null +++ b/grc/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/blocks/gr_complex_to_mag.xml b/grc/blocks/gr_complex_to_mag.xml new file mode 100644 index 00000000..adc95f20 --- /dev/null +++ b/grc/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/blocks/gr_complex_to_mag_squared.xml b/grc/blocks/gr_complex_to_mag_squared.xml new file mode 100644 index 00000000..cd23bfb5 --- /dev/null +++ b/grc/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/blocks/gr_complex_to_real.xml b/grc/blocks/gr_complex_to_real.xml new file mode 100644 index 00000000..ae9ec7b1 --- /dev/null +++ b/grc/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/blocks/gr_conjugate_cc.xml b/grc/blocks/gr_conjugate_cc.xml new file mode 100644 index 00000000..0b4deb34 --- /dev/null +++ b/grc/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/blocks/gr_constellation_decoder_cb.xml b/grc/blocks/gr_constellation_decoder_cb.xml new file mode 100644 index 00000000..99d897a3 --- /dev/null +++ b/grc/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/blocks/gr_correlate_access_code_bb.xml b/grc/blocks/gr_correlate_access_code_bb.xml new file mode 100644 index 00000000..e13d2d07 --- /dev/null +++ b/grc/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/blocks/gr_costas_loop_cc.xml b/grc/blocks/gr_costas_loop_cc.xml new file mode 100644 index 00000000..e0db8bc5 --- /dev/null +++ b/grc/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/blocks/gr_cpfsk_bc.xml b/grc/blocks/gr_cpfsk_bc.xml new file mode 100644 index 00000000..d5549d93 --- /dev/null +++ b/grc/blocks/gr_cpfsk_bc.xml @@ -0,0 +1,37 @@ + + + + CPFSK + gr_cpfsk_bc + from gnuradio import gr + 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/blocks/gr_dd_mpsk_sync_cc.xml b/grc/blocks/gr_dd_mpsk_sync_cc.xml new file mode 100644 index 00000000..aed0e8d3 --- /dev/null +++ b/grc/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/blocks/gr_decode_ccsds_27_fb.xml b/grc/blocks/gr_decode_ccsds_27_fb.xml new file mode 100644 index 00000000..03b31db8 --- /dev/null +++ b/grc/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/blocks/gr_deinterleave.xml b/grc/blocks/gr_deinterleave.xml new file mode 100644 index 00000000..a7482978 --- /dev/null +++ b/grc/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/blocks/gr_delay.xml b/grc/blocks/gr_delay.xml new file mode 100644 index 00000000..64a774de --- /dev/null +++ b/grc/blocks/gr_delay.xml @@ -0,0 +1,66 @@ + + + + Delay + gr_delay + from gnuradio import gr + gr.delay($type.size*$vlen, $delay) + set_delay($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/blocks/gr_descrambler_bb.xml b/grc/blocks/gr_descrambler_bb.xml new file mode 100644 index 00000000..5cfbcc20 --- /dev/null +++ b/grc/blocks/gr_descrambler_bb.xml @@ -0,0 +1,38 @@ + + + + Descrambler + gr_descrambler_bb + from gnuradio import gr + gr.descrambler_bb($mask, $seed, $len) + + Mask + mask + 0x8A + hex + + + Seed + seed + 0x7F + hex + + + Length + len + 7 + int + + + in + byte + + + out + byte + + diff --git a/grc/blocks/gr_diff_decoder_bb.xml b/grc/blocks/gr_diff_decoder_bb.xml new file mode 100644 index 00000000..ea7cf173 --- /dev/null +++ b/grc/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/blocks/gr_diff_encoder_bb.xml b/grc/blocks/gr_diff_encoder_bb.xml new file mode 100644 index 00000000..21241eac --- /dev/null +++ b/grc/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/blocks/gr_diff_phasor_cc.xml b/grc/blocks/gr_diff_phasor_cc.xml new file mode 100644 index 00000000..2b2d7e37 --- /dev/null +++ b/grc/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/blocks/gr_divide_xx.xml b/grc/blocks/gr_divide_xx.xml new file mode 100644 index 00000000..04667bc2 --- /dev/null +++ b/grc/blocks/gr_divide_xx.xml @@ -0,0 +1,63 @@ + + + + Divide + gr_divide_xx + from gnuradio import gr + gr.divide_$(type.fcn)($vlen) + + IO Type + type + enum + + + + + + + Vec Length + vlen + 1 + int + + + Num Inputs + num_inputs + 2 + int + + $vlen > 0 + $num_inputs >= 2 + + in + $type + $vlen + $num_inputs + + + out + $type + $vlen + + diff --git a/grc/blocks/gr_dpll_bb.xml b/grc/blocks/gr_dpll_bb.xml new file mode 100644 index 00000000..044d398f --- /dev/null +++ b/grc/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/blocks/gr_encode_ccsds_27_bb.xml b/grc/blocks/gr_encode_ccsds_27_bb.xml new file mode 100644 index 00000000..f31e6b6c --- /dev/null +++ b/grc/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/blocks/gr_feedforward_agc_cc.xml b/grc/blocks/gr_feedforward_agc_cc.xml new file mode 100644 index 00000000..24e80953 --- /dev/null +++ b/grc/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/blocks/gr_fft_filter_xxx.xml b/grc/blocks/gr_fft_filter_xxx.xml new file mode 100644 index 00000000..c1633094 --- /dev/null +++ b/grc/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/blocks/gr_fft_vxx.xml b/grc/blocks/gr_fft_vxx.xml new file mode 100644 index 00000000..d398486e --- /dev/null +++ b/grc/blocks/gr_fft_vxx.xml @@ -0,0 +1,81 @@ + + + + FFT + gr_fft_vxx + from gnuradio import gr + from gnuradio import window + #if $type() == "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/blocks/gr_file_sink.xml b/grc/blocks/gr_file_sink.xml new file mode 100644 index 00000000..880dc275 --- /dev/null +++ b/grc/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/blocks/gr_file_source.xml b/grc/blocks/gr_file_source.xml new file mode 100644 index 00000000..fcc7a704 --- /dev/null +++ b/grc/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/blocks/gr_filter_delay_fc.xml b/grc/blocks/gr_filter_delay_fc.xml new file mode 100644 index 00000000..30d65bf8 --- /dev/null +++ b/grc/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/blocks/gr_fir_filter_xxx.xml b/grc/blocks/gr_fir_filter_xxx.xml new file mode 100644 index 00000000..c4de8f53 --- /dev/null +++ b/grc/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/blocks/gr_float_to_char.xml b/grc/blocks/gr_float_to_char.xml new file mode 100644 index 00000000..907de774 --- /dev/null +++ b/grc/blocks/gr_float_to_char.xml @@ -0,0 +1,20 @@ + + + + Float To Char + gr_float_to_char + from gnuradio import gr + gr.float_to_char() + + in + float + + + out + byte + + diff --git a/grc/blocks/gr_float_to_complex.xml b/grc/blocks/gr_float_to_complex.xml new file mode 100644 index 00000000..a1644efd --- /dev/null +++ b/grc/blocks/gr_float_to_complex.xml @@ -0,0 +1,36 @@ + + + + Float To Complex + gr_float_to_complex + from gnuradio import gr + gr.float_to_complex($vlen) + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + float + $vlen + + + in + float + $vlen + 1 + + + out + complex + $vlen + + diff --git a/grc/blocks/gr_float_to_short.xml b/grc/blocks/gr_float_to_short.xml new file mode 100644 index 00000000..cb2bcd4b --- /dev/null +++ b/grc/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/blocks/gr_float_to_uchar.xml b/grc/blocks/gr_float_to_uchar.xml new file mode 100644 index 00000000..aa804d7d --- /dev/null +++ b/grc/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/blocks/gr_fractional_interpolator_xx.xml b/grc/blocks/gr_fractional_interpolator_xx.xml new file mode 100644 index 00000000..8d65ff8b --- /dev/null +++ b/grc/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/blocks/gr_freq_xlating_fir_filter_xxx.xml b/grc/blocks/gr_freq_xlating_fir_filter_xxx.xml new file mode 100644 index 00000000..e3ee6697 --- /dev/null +++ b/grc/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/blocks/gr_frequency_modulator_fc.xml b/grc/blocks/gr_frequency_modulator_fc.xml new file mode 100644 index 00000000..f18d9f1e --- /dev/null +++ b/grc/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/blocks/gr_glfsr_source_x.xml b/grc/blocks/gr_glfsr_source_x.xml new file mode 100644 index 00000000..88fb6679 --- /dev/null +++ b/grc/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/blocks/gr_goertzel_fc.xml b/grc/blocks/gr_goertzel_fc.xml new file mode 100644 index 00000000..2105445d --- /dev/null +++ b/grc/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/blocks/gr_head.xml b/grc/blocks/gr_head.xml new file mode 100644 index 00000000..e5ff7f6a --- /dev/null +++ b/grc/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/blocks/gr_hilbert_fc.xml b/grc/blocks/gr_hilbert_fc.xml new file mode 100644 index 00000000..165e8da2 --- /dev/null +++ b/grc/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/blocks/gr_iir_filter_ffd.xml b/grc/blocks/gr_iir_filter_ffd.xml new file mode 100644 index 00000000..9799150e --- /dev/null +++ b/grc/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/blocks/gr_integrate_xx.xml b/grc/blocks/gr_integrate_xx.xml new file mode 100644 index 00000000..d0ebd42e --- /dev/null +++ b/grc/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/blocks/gr_interleave.xml b/grc/blocks/gr_interleave.xml new file mode 100644 index 00000000..3db16ab5 --- /dev/null +++ b/grc/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/blocks/gr_interleaved_short_to_complex.xml b/grc/blocks/gr_interleaved_short_to_complex.xml new file mode 100644 index 00000000..e3023e49 --- /dev/null +++ b/grc/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/blocks/gr_interp_fir_filter_xxx.xml b/grc/blocks/gr_interp_fir_filter_xxx.xml new file mode 100644 index 00000000..55375ae0 --- /dev/null +++ b/grc/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/blocks/gr_iqcomp_cc.xml b/grc/blocks/gr_iqcomp_cc.xml new file mode 100644 index 00000000..1603bdc4 --- /dev/null +++ b/grc/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/blocks/gr_keep_one_in_n.xml b/grc/blocks/gr_keep_one_in_n.xml new file mode 100644 index 00000000..21595b75 --- /dev/null +++ b/grc/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/blocks/gr_kludge_copy.xml b/grc/blocks/gr_kludge_copy.xml new file mode 100644 index 00000000..3c817c57 --- /dev/null +++ b/grc/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/blocks/gr_map_bb.xml b/grc/blocks/gr_map_bb.xml new file mode 100644 index 00000000..20d6bd2b --- /dev/null +++ b/grc/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/blocks/gr_max_xx.xml b/grc/blocks/gr_max_xx.xml new file mode 100644 index 00000000..9dbbe60e --- /dev/null +++ b/grc/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/blocks/gr_moving_average_xx.xml b/grc/blocks/gr_moving_average_xx.xml new file mode 100644 index 00000000..b70943c7 --- /dev/null +++ b/grc/blocks/gr_moving_average_xx.xml @@ -0,0 +1,68 @@ + + + + Moving Average + gr_moving_average_xx + from gnuradio import gr + gr.moving_average_$(type.fcn)($length, $scale, $max_iter) + set_length_and_scale($length, $scale) + + 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/blocks/gr_mpsk_receiver_cc.xml b/grc/blocks/gr_mpsk_receiver_cc.xml new file mode 100644 index 00000000..843c3a4c --- /dev/null +++ b/grc/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/blocks/gr_mpsk_sync_cc.xml b/grc/blocks/gr_mpsk_sync_cc.xml new file mode 100644 index 00000000..fd08f834 --- /dev/null +++ b/grc/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/blocks/gr_multiply_const_vxx.xml b/grc/blocks/gr_multiply_const_vxx.xml new file mode 100644 index 00000000..1309d75c --- /dev/null +++ b/grc/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/blocks/gr_multiply_xx.xml b/grc/blocks/gr_multiply_xx.xml new file mode 100644 index 00000000..60f65c27 --- /dev/null +++ b/grc/blocks/gr_multiply_xx.xml @@ -0,0 +1,63 @@ + + + + Multiply + gr_multiply_xx + 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/blocks/gr_mute_xx.xml b/grc/blocks/gr_mute_xx.xml new file mode 100644 index 00000000..a9a857c6 --- /dev/null +++ b/grc/blocks/gr_mute_xx.xml @@ -0,0 +1,61 @@ + + + + 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/blocks/gr_nlog10_ff.xml b/grc/blocks/gr_nlog10_ff.xml new file mode 100644 index 00000000..93507823 --- /dev/null +++ b/grc/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/blocks/gr_noise_source_x.xml b/grc/blocks/gr_noise_source_x.xml new file mode 100644 index 00000000..4fcef514 --- /dev/null +++ b/grc/blocks/gr_noise_source_x.xml @@ -0,0 +1,77 @@ + + + + Noise Source + gr_noise_source_x + from gnuradio import gr + gr.noise_source_$(type.fcn)($noise_type, $amp, $seed) + set_type($noise_type) + set_amplitude($amp) + + Output Type + type + enum + + + + + + + Noise Type + noise_type + gr.GR_GAUSSIAN + raw + + + + + + + Amplitude + amp + 1 + real + + + Seed + seed + 42 + int + + + out + $type + + diff --git a/grc/blocks/gr_nop.xml b/grc/blocks/gr_nop.xml new file mode 100644 index 00000000..127a78a5 --- /dev/null +++ b/grc/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/blocks/gr_not_xx.xml b/grc/blocks/gr_not_xx.xml new file mode 100644 index 00000000..7af7e4b6 --- /dev/null +++ b/grc/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/blocks/gr_null_sink.xml b/grc/blocks/gr_null_sink.xml new file mode 100644 index 00000000..ed106b49 --- /dev/null +++ b/grc/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/blocks/gr_null_source.xml b/grc/blocks/gr_null_source.xml new file mode 100644 index 00000000..6132eae3 --- /dev/null +++ b/grc/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/blocks/gr_or_xx.xml b/grc/blocks/gr_or_xx.xml new file mode 100644 index 00000000..b374aa22 --- /dev/null +++ b/grc/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/blocks/gr_packed_to_unpacked_xx.xml b/grc/blocks/gr_packed_to_unpacked_xx.xml new file mode 100644 index 00000000..5fd9729a --- /dev/null +++ b/grc/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/blocks/gr_peak_detector2_fb.xml b/grc/blocks/gr_peak_detector2_fb.xml new file mode 100644 index 00000000..128c6244 --- /dev/null +++ b/grc/blocks/gr_peak_detector2_fb.xml @@ -0,0 +1,38 @@ + + + + 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) + + TH Factor Rise + threshold_factor_rise + real + + + Look Ahead + look_ahead + int + + + Alpha + alpha + real + + + in + float + + + out + byte + + diff --git a/grc/blocks/gr_peak_detector_xb.xml b/grc/blocks/gr_peak_detector_xb.xml new file mode 100644 index 00000000..394b0697 --- /dev/null +++ b/grc/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/blocks/gr_phase_modulator_fc.xml b/grc/blocks/gr_phase_modulator_fc.xml new file mode 100644 index 00000000..758c5086 --- /dev/null +++ b/grc/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/blocks/gr_pll_carriertracking_cc.xml b/grc/blocks/gr_pll_carriertracking_cc.xml new file mode 100644 index 00000000..5b876b25 --- /dev/null +++ b/grc/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/blocks/gr_pll_freqdet_cf.xml b/grc/blocks/gr_pll_freqdet_cf.xml new file mode 100644 index 00000000..8ec1fb3b --- /dev/null +++ b/grc/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/blocks/gr_pll_refout_cc.xml b/grc/blocks/gr_pll_refout_cc.xml new file mode 100644 index 00000000..64cf2bfb --- /dev/null +++ b/grc/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/blocks/gr_pn_correlator_cc.xml b/grc/blocks/gr_pn_correlator_cc.xml new file mode 100644 index 00000000..094f46cd --- /dev/null +++ b/grc/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/blocks/gr_probe_avg_mag_sqrd_x.xml b/grc/blocks/gr_probe_avg_mag_sqrd_x.xml new file mode 100644 index 00000000..eb855956 --- /dev/null +++ b/grc/blocks/gr_probe_avg_mag_sqrd_x.xml @@ -0,0 +1,60 @@ + + + + Probe Avg Mag^2 + gr_probe_avg_mag_sqrd_x + from grc_gnuradio import blks2 as grc_blks2 + grc_blks2.probe_avg_mag_sqrd_$(type)( + threshold=$threshold, + alpha=$alpha, + probe_rate=$probe_rate, +) + set_alpha($alpha) + set_threshold($threshold) + set_probe_rate($probe_rate) + + Type + type + enum + + + + + Threshold (dB) + threshold + 0 + real + + + Alpha + alpha + 1 + real + + + Probe Rate + probe_rate + 10 + real + + + in + $type.input + + + out + float + + diff --git a/grc/blocks/gr_probe_density_b.xml b/grc/blocks/gr_probe_density_b.xml new file mode 100644 index 00000000..74d3b0a2 --- /dev/null +++ b/grc/blocks/gr_probe_density_b.xml @@ -0,0 +1,37 @@ + + + + Probe Density + gr_probe_density_b + from grc_gnuradio import blks2 as grc_blks2 + grc_blks2.probe_density_b( + alpha=$alpha, + probe_rate=$probe_rate, +) + set_alpha($alpha) + set_probe_rate($probe_rate) + + Alpha + alpha + 1 + real + + + Probe Rate + probe_rate + 10 + real + + + in + byte + + + out + float + + diff --git a/grc/blocks/gr_probe_mpsk_snr_c.xml b/grc/blocks/gr_probe_mpsk_snr_c.xml new file mode 100644 index 00000000..7f562d2f --- /dev/null +++ b/grc/blocks/gr_probe_mpsk_snr_c.xml @@ -0,0 +1,55 @@ + + + + Probe MPSK SNR + gr_probe_mpsk_snr_c + from grc_gnuradio import blks2 as grc_blks2 + grc_blks2.probe_mpsk_snr_c( + type='$type', + alpha=$alpha, + probe_rate=$probe_rate, +) + set_alpha($alpha) + set_probe_rate($probe_rate) + + Type + type + enum + + + + + + Alpha + alpha + 1 + real + + + Probe Rate + probe_rate + 10 + real + + + in + complex + + + out + float + + diff --git a/grc/blocks/gr_pwr_squelch_xx.xml b/grc/blocks/gr_pwr_squelch_xx.xml new file mode 100644 index 00000000..08d62117 --- /dev/null +++ b/grc/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/blocks/gr_quadrature_demod_cf.xml b/grc/blocks/gr_quadrature_demod_cf.xml new file mode 100644 index 00000000..a0e630c7 --- /dev/null +++ b/grc/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/blocks/gr_rational_resampler_base_xxx.xml b/grc/blocks/gr_rational_resampler_base_xxx.xml new file mode 100644 index 00000000..4b772017 --- /dev/null +++ b/grc/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/blocks/gr_repeat.xml b/grc/blocks/gr_repeat.xml new file mode 100644 index 00000000..ba652a4d --- /dev/null +++ b/grc/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/blocks/gr_rms_xx.xml b/grc/blocks/gr_rms_xx.xml new file mode 100644 index 00000000..1e094719 --- /dev/null +++ b/grc/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/blocks/gr_sample_and_hold_xx.xml b/grc/blocks/gr_sample_and_hold_xx.xml new file mode 100644 index 00000000..bfe66bb0 --- /dev/null +++ b/grc/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/blocks/gr_scrambler_bb.xml b/grc/blocks/gr_scrambler_bb.xml new file mode 100644 index 00000000..d079c401 --- /dev/null +++ b/grc/blocks/gr_scrambler_bb.xml @@ -0,0 +1,38 @@ + + + + Scrambler + gr_scrambler_bb + from gnuradio import gr + gr.scrambler_bb($mask, $seed, $len) + + Mask + mask + 0x8A + hex + + + Seed + seed + 0x7F + hex + + + Length + len + 7 + int + + + in + byte + + + out + byte + + diff --git a/grc/blocks/gr_short_to_float.xml b/grc/blocks/gr_short_to_float.xml new file mode 100644 index 00000000..8dac97c0 --- /dev/null +++ b/grc/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/blocks/gr_sig_source_x.xml b/grc/blocks/gr_sig_source_x.xml new file mode 100644 index 00000000..c329dba6 --- /dev/null +++ b/grc/blocks/gr_sig_source_x.xml @@ -0,0 +1,104 @@ + + + + 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_waveform($waveform) + 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 + raw + + + + + + + + + Frequency + freq + 1000 + real + + + Amplitude + amp + 1 + real + + + Offset + offset + 0 + $type.offset_type + + + out + $type + + diff --git a/grc/blocks/gr_simple_correlator.xml b/grc/blocks/gr_simple_correlator.xml new file mode 100644 index 00000000..820523a6 --- /dev/null +++ b/grc/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/blocks/gr_simple_framer.xml b/grc/blocks/gr_simple_framer.xml new file mode 100644 index 00000000..2a0295c4 --- /dev/null +++ b/grc/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/blocks/gr_simple_squelch_cc.xml b/grc/blocks/gr_simple_squelch_cc.xml new file mode 100644 index 00000000..5c0727f5 --- /dev/null +++ b/grc/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/blocks/gr_single_pole_iir_filter_xx.xml b/grc/blocks/gr_single_pole_iir_filter_xx.xml new file mode 100644 index 00000000..50cf4a82 --- /dev/null +++ b/grc/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/blocks/gr_skiphead.xml b/grc/blocks/gr_skiphead.xml new file mode 100644 index 00000000..0849ad29 --- /dev/null +++ b/grc/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/blocks/gr_stream_to_streams.xml b/grc/blocks/gr_stream_to_streams.xml new file mode 100644 index 00000000..82542b8d --- /dev/null +++ b/grc/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/blocks/gr_stream_to_vector.xml b/grc/blocks/gr_stream_to_vector.xml new file mode 100644 index 00000000..296d786f --- /dev/null +++ b/grc/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/blocks/gr_streams_to_stream.xml b/grc/blocks/gr_streams_to_stream.xml new file mode 100644 index 00000000..7aadd7ee --- /dev/null +++ b/grc/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/blocks/gr_streams_to_vector.xml b/grc/blocks/gr_streams_to_vector.xml new file mode 100644 index 00000000..4ecdcb2d --- /dev/null +++ b/grc/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/blocks/gr_sub_xx.xml b/grc/blocks/gr_sub_xx.xml new file mode 100644 index 00000000..f1f4797e --- /dev/null +++ b/grc/blocks/gr_sub_xx.xml @@ -0,0 +1,63 @@ + + + + Subtract + gr_sub_xx + from gnuradio import gr + gr.sub_$(type.fcn)($vlen) + + IO Type + type + enum + + + + + + + Vec Length + vlen + 1 + int + + + Num Inputs + num_inputs + 2 + int + + $vlen > 0 + $num_inputs >= 2 + + in + $type + $vlen + $num_inputs + + + out + $type + $vlen + + diff --git a/grc/blocks/gr_threshold_ff.xml b/grc/blocks/gr_threshold_ff.xml new file mode 100644 index 00000000..740ce579 --- /dev/null +++ b/grc/blocks/gr_threshold_ff.xml @@ -0,0 +1,40 @@ + + + + Threshold + gr_threshold_ff + from gnuradio import gr + gr.threshold_ff($low, $high, $init) + set_hi($high) + set_lo($low) + + Low + low + -100 + real + + + High + high + 100 + real + + + Initial State + init + 0 + real + + + in + float + + + out + float + + diff --git a/grc/blocks/gr_throttle.xml b/grc/blocks/gr_throttle.xml new file mode 100644 index 00000000..ab8506f5 --- /dev/null +++ b/grc/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/blocks/gr_uchar_to_float.xml b/grc/blocks/gr_uchar_to_float.xml new file mode 100644 index 00000000..0a5f7f96 --- /dev/null +++ b/grc/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/blocks/gr_udp_sink.xml b/grc/blocks/gr_udp_sink.xml new file mode 100644 index 00000000..e9f6c2be --- /dev/null +++ b/grc/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/blocks/gr_udp_source.xml b/grc/blocks/gr_udp_source.xml new file mode 100644 index 00000000..f03adf80 --- /dev/null +++ b/grc/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/blocks/gr_unpack_k_bits_bb.xml b/grc/blocks/gr_unpack_k_bits_bb.xml new file mode 100644 index 00000000..9917644a --- /dev/null +++ b/grc/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/blocks/gr_unpacked_to_packed_xx.xml b/grc/blocks/gr_unpacked_to_packed_xx.xml new file mode 100644 index 00000000..f7457eb5 --- /dev/null +++ b/grc/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/blocks/gr_vco_f.xml b/grc/blocks/gr_vco_f.xml new file mode 100644 index 00000000..e49c5396 --- /dev/null +++ b/grc/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/blocks/gr_vector_sink_x.xml b/grc/blocks/gr_vector_sink_x.xml new file mode 100644 index 00000000..3bd99869 --- /dev/null +++ b/grc/blocks/gr_vector_sink_x.xml @@ -0,0 +1,54 @@ + + + + Vector Sink + gr_vector_sink_x + from gnuradio import gr + gr.vector_sink_$(type.fcn)($vlen) + + Input Type + type + enum + + + + + + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + diff --git a/grc/blocks/gr_vector_source_x.xml b/grc/blocks/gr_vector_source_x.xml new file mode 100644 index 00000000..7a6a3aef --- /dev/null +++ b/grc/blocks/gr_vector_source_x.xml @@ -0,0 +1,79 @@ + + + + Vector Source + gr_vector_source_x + from gnuradio import gr + gr.vector_source_$(type.fcn)($vector, $repeat, $vlen) + + Output Type + type + enum + + + + + + + + Vector + vector + 0, 0, 0 + $type.vec_type + + + Repeat + repeat + True + enum + + + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + out + $type + $vlen + + diff --git a/grc/blocks/gr_vector_to_stream.xml b/grc/blocks/gr_vector_to_stream.xml new file mode 100644 index 00000000..d56d3406 --- /dev/null +++ b/grc/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/blocks/gr_vector_to_streams.xml b/grc/blocks/gr_vector_to_streams.xml new file mode 100644 index 00000000..86cb5681 --- /dev/null +++ b/grc/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/blocks/gr_wavfile_sink.xml b/grc/blocks/gr_wavfile_sink.xml new file mode 100644 index 00000000..f2c8a009 --- /dev/null +++ b/grc/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/blocks/gr_wavfile_source.xml b/grc/blocks/gr_wavfile_source.xml new file mode 100644 index 00000000..433bb0af --- /dev/null +++ b/grc/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/blocks/gr_xor_xx.xml b/grc/blocks/gr_xor_xx.xml new file mode 100644 index 00000000..c014cbe5 --- /dev/null +++ b/grc/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/blocks/high_pass_filter.xml b/grc/blocks/high_pass_filter.xml new file mode 100644 index 00000000..5be916fa --- /dev/null +++ b/grc/blocks/high_pass_filter.xml @@ -0,0 +1,126 @@ + + + + High Pass Filter + high_pass_filter + from gnuradio import gr + from gnuradio.gr import firdes + gr.$(type)(#if str($type).startswith('interp') then $interp else $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 + #if str($type).startswith('interp') then 'all' else 'none'# + + + Interpolation + interp + 1 + int + #if str($type).startswith('interp') then 'none' else 'all'# + + + 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. + +Sample rate, cutoff frequency, and transition width are in Hertz. + +The beta paramater only applies to the Kaiser window. + + diff --git a/grc/blocks/import.xml b/grc/blocks/import.xml new file mode 100644 index 00000000..feea052d --- /dev/null +++ b/grc/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/blocks/low_pass_filter.xml b/grc/blocks/low_pass_filter.xml new file mode 100644 index 00000000..27120c04 --- /dev/null +++ b/grc/blocks/low_pass_filter.xml @@ -0,0 +1,126 @@ + + + + Low Pass Filter + low_pass_filter + from gnuradio import gr + from gnuradio.gr import firdes + gr.$(type)(#if str($type).startswith('interp') then $interp else $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 + #if str($type).startswith('interp') then 'all' else 'none'# + + + Interpolation + interp + 1 + int + #if str($type).startswith('interp') then 'none' else 'all'# + + + 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. + +Sample rate, cutoff frequency, and transition width are in Hertz. + +The beta paramater only applies to the Kaiser window. + + diff --git a/grc/blocks/note.xml b/grc/blocks/note.xml new file mode 100644 index 00000000..db6687c0 --- /dev/null +++ b/grc/blocks/note.xml @@ -0,0 +1,17 @@ + + + + Note + note + + + Note + note + + string + + diff --git a/grc/blocks/options.xml b/grc/blocks/options.xml new file mode 100644 index 00000000..06ede76f --- /dev/null +++ b/grc/blocks/options.xml @@ -0,0 +1,147 @@ + + + + Options + options + from gnuradio import gr +#if $generate_options() == 'wx_gui' +from grc_gnuradio import wxgui as grc_wxgui +import wx +#end if +#if $generate_options() != 'hb' +from optparse import OptionParser +from gnuradio.eng_option import eng_option +#end if + + + self.start($autostart) + + Title + title + + string + #if $title() then 'none' else 'part'# + + + Author + author + + string + #if $author() then 'none' else 'part'# + + + Description + description + + string + #if $description() then 'none' else 'part'# + + + Window Size + window_size + 1280, 1024 + int_vector + part + + + Generate Options + generate_options + wx_gui + enum + #if $generate_options() == 'wx_gui' then 'part' else 'none'# + + + + + + Category + category + Custom + string + #if $generate_options() == 'hb' then 'none' else 'all'# + + + Autostart + autostart + True + bool + #if $generate_options() == 'wx_gui' + #if str($autostart) == 'True' +part#slurp + #else +none#slurp + #end if +#else +all#slurp +#end if + + + + + Realtime Scheduling + realtime_scheduling + + enum + #if $generate_options() == 'hb' +all#slurp +#elif $realtime_scheduling() +none#slurp +#else +part#slurp +#end if + + + + len($window_size) == 2 + 300 <= $(window_size)[0] <= 4096 + 300 <= $(window_size)[1] <= 4096 + +The options block sets special parameters for the flow graph. \ +Only one option block is allowed per flow graph. + +Title, author, and description parameters are for identification purposes. + +The window size controls the dimensions of the flow graph editor. \ +The window size (width, height) must be between (300, 300) and (4096, 4096). + +The generate options controls the type of code generated. \ +Non-graphical flow graphs should avoid using graphical sinks or graphical variable controls. + +In a graphical application, \ +autostart can be controlled by a variable to start and stop the flowgraph at runtime. + +The id of this block determines the name of the generated file and the name of the class. \ +For example, an id of my_block will generate the file my_block.py and class my_block(gr.... + +The category parameter determines the placement of the block in the block selection window. \ +The category only applies when creating hier blocks. \ +To put hier blocks into the root category, enter / for the category. + + diff --git a/grc/blocks/pad_sink.xml b/grc/blocks/pad_sink.xml new file mode 100644 index 00000000..477f2ad1 --- /dev/null +++ b/grc/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/blocks/pad_source.xml b/grc/blocks/pad_source.xml new file mode 100644 index 00000000..b6ef2c55 --- /dev/null +++ b/grc/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/blocks/parameter.xml b/grc/blocks/parameter.xml new file mode 100644 index 00000000..d3bab94c --- /dev/null +++ b/grc/blocks/parameter.xml @@ -0,0 +1,80 @@ + + + + Parameter + parameter + self.$(id) = $(id) + $value + + Label + label + + string + #if $label() then 'none' else 'part'# + + + Value + value + 0 + $type.type + + + Type + type + + enum + $type.hide + + + + + + + + +This block represents a parameter to the flow graph. \ +A parameter can be used to pass command line arguments into a top block. \ +Or, parameters can pass arguments into an instantiated hierarchical block. + +The paramater value cannot depend on any variables. + +Leave the label blank to use the parameter id as the label. \ +The label only applies when this flow graph is instantiated as a hierarchical block. + +When type is not None, this parameter also becomes a command line option of the form --[id] [value]. + + diff --git a/grc/blocks/probe_function.xml b/grc/blocks/probe_function.xml new file mode 100644 index 00000000..ac0b3dcd --- /dev/null +++ b/grc/blocks/probe_function.xml @@ -0,0 +1,44 @@ + + + + Probe Function + probe_function + from grc_gnuradio import blks2 as grc_blks2 + grc_blks2.probe_function( + probe_callback=self.$(block_id()).$(function_name()), + probe_rate=$probe_rate, +) + set_probe_rate($probe_rate) + + Block ID + block_id + my_block_0 + string + + + Function Name + function_name + get_number + string + + + Probe Rate + probe_rate + 10 + real + + + out + float + + +Polls a function of an arbitrary block and writes the value to the output port. \ +The block id is the id of another block in the flow graph. \ +The function name is the name of a function in the said block. \ +The function should take no arguments and return a floating point or integer number. + + diff --git a/grc/blocks/random_source_x.xml b/grc/blocks/random_source_x.xml new file mode 100644 index 00000000..800bae71 --- /dev/null +++ b/grc/blocks/random_source_x.xml @@ -0,0 +1,75 @@ + + + + Random Source + random_source_x + from gnuradio import gr + import numpy + gr.vector_source_$(type.fcn)(map(int, numpy.random.randint($min, $max, $num_samps)), $repeat) + + Output Type + type + enum + + + + + + Minimum + min + 0 + int + + + Maximum + max + 2 + 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. + +Ex: With min=0 and max=2, the sequence 01110101... will be generated. + + diff --git a/grc/blocks/root_raised_cosine_filter.xml b/grc/blocks/root_raised_cosine_filter.xml new file mode 100644 index 00000000..81688d29 --- /dev/null +++ b/grc/blocks/root_raised_cosine_filter.xml @@ -0,0 +1,101 @@ + + + + Root Raised Cosine Filter + root_raised_cosine_filter + from gnuradio import gr + from gnuradio.gr import firdes + gr.$(type)(#if str($type).startswith('interp') then $interp else $decim#, firdes.root_raised_cosine( + $gain, $samp_rate, $sym_rate, $alpha, $ntaps)) + set_taps(firdes.root_raised_cosine($gain, $samp_rate, $sym_rate, $alpha, $ntaps)) + + FIR Type + type + enum + + + + + + + Decimation + decim + 1 + int + #if str($type).startswith('interp') then 'all' else 'none'# + + + Interpolation + interp + 1 + int + #if str($type).startswith('interp') then 'none' else 'all'# + + + Gain + gain + 1 + real + + + Sample Rate + samp_rate + samp_rate + real + + + Symbol Rate + sym_rate + 1.0 + real + + + Alpha + alpha + 0.35 + real + + + Num Taps + ntaps + 11*samp_rate + int + + + in + $type.input + + + out + $type.output + + +This filter is a convenience wrapper for an fir filter and a firdes taps generating function. + +Sample rate in Hertz. + + diff --git a/grc/blocks/trellis_encoder_xx.xml b/grc/blocks/trellis_encoder_xx.xml new file mode 100644 index 00000000..74a8cc34 --- /dev/null +++ b/grc/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/blocks/trellis_metrics_x.xml b/grc/blocks/trellis_metrics_x.xml new file mode 100644 index 00000000..2016a34c --- /dev/null +++ b/grc/blocks/trellis_metrics_x.xml @@ -0,0 +1,85 @@ + + + + Trellis Metrics + trellis_metrics_x + from gnuradio import trellis + trellis.metrics_$(type)($card, $dim, $table, $metric_type) + set_TABLE($table) + + Type + type + enum + + + + + + + Output Cardinality + card + int + + + Dimensionality + dim + int + + + Constellation + table + $type.table + + + Metric Type + metric_type + enum + + + + + + in + $type.io + + + out + float + + +Generate metrics required for Viterbi or SISO algorithms. + + diff --git a/grc/blocks/trellis_permutation.xml b/grc/blocks/trellis_permutation.xml new file mode 100644 index 00000000..7721cc71 --- /dev/null +++ b/grc/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/blocks/trellis_siso_combined_f.xml b/grc/blocks/trellis_siso_combined_f.xml new file mode 100644 index 00000000..98874d7f --- /dev/null +++ b/grc/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/blocks/trellis_siso_f.xml b/grc/blocks/trellis_siso_f.xml new file mode 100644 index 00000000..2b9cfe5f --- /dev/null +++ b/grc/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/blocks/trellis_viterbi_combined_xx.xml b/grc/blocks/trellis_viterbi_combined_xx.xml new file mode 100644 index 00000000..33dcaaf7 --- /dev/null +++ b/grc/blocks/trellis_viterbi_combined_xx.xml @@ -0,0 +1,123 @@ + + + + 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) + set_TABLE($table) + + 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/blocks/trellis_viterbi_x.xml b/grc/blocks/trellis_viterbi_x.xml new file mode 100644 index 00000000..84b39677 --- /dev/null +++ b/grc/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 + float + + + out + $type.io + + +Viterbi Decoder. \ +The fsm arguments are passed directly to the trellis.fsm() constructor. + + diff --git a/grc/blocks/usrp2_probe.xml b/grc/blocks/usrp2_probe.xml new file mode 100644 index 00000000..cc3f9c2f --- /dev/null +++ b/grc/blocks/usrp2_probe.xml @@ -0,0 +1,33 @@ + + + + USRP2 Probe + usrp2_probe + + + Interface + interface + + string + + + Type + type + rx + enum + + + + Press "Probe" to retrieve USRP2 information... + diff --git a/grc/blocks/usrp2_sink_xxxx.xml b/grc/blocks/usrp2_sink_xxxx.xml new file mode 100644 index 00000000..639f96cf --- /dev/null +++ b/grc/blocks/usrp2_sink_xxxx.xml @@ -0,0 +1,95 @@ + + + + USRP2 Sink + usrp2_sink_xxxx + from gnuradio import usrp2 + #if not $interface() and not $mac_addr() +usrp2.sink_$(type.fcn)() +#elif not $mac_addr() +usrp2.sink_$(type.fcn)($interface) +#else +usrp2.sink_$(type.fcn)($interface, $mac_addr) +#end if +self.$(id).set_interp($interpolation) +self.$(id).set_center_freq($frequency) +self.$(id).set_gain($gain) +#if $lo_offset() != float('inf') +self.$(id).set_lo_offset($lo_offset) +#end if + set_lo_offset($lo_offset) + set_interp($interpolation) + set_center_freq($frequency) + set_gain($gain) + + Output Type + type + enum + + + + + Interface + interface + + string + + + MAC Addr + mac_addr + + string + + + Interpolation + interpolation + int + + + Frequency (Hz) + frequency + real + + + LO Offset (Hz) + lo_offset + float('inf') + real + #if $lo_offset() == float('inf') then 'part' else 'none'# + + + + Gain (dB) + gain + 0 + real + + + in + $type + + +The USRP2 sink inputs 100 Megasamples per second / interpolation. + +Input amplitude should be between 0.0 and 1.0. + +To use the default ethernet device, leave interface blank. \ +For systems with only 1 USRP2, you may leave the mac address blank. \ +For multi-USRP2 systems, specify the mac address in the form 00:50:C2:85:3x:xx. + + diff --git a/grc/blocks/usrp2_source_xxxx.xml b/grc/blocks/usrp2_source_xxxx.xml new file mode 100644 index 00000000..6c776d0a --- /dev/null +++ b/grc/blocks/usrp2_source_xxxx.xml @@ -0,0 +1,93 @@ + + + + USRP2 Source + usrp2_source_xxxx + from gnuradio import usrp2 + #if not $interface() and not $mac_addr() +usrp2.source_$(type.fcn)() +#elif not $mac_addr() +usrp2.source_$(type.fcn)($interface) +#else +usrp2.source_$(type.fcn)($interface, $mac_addr) +#end if +self.$(id).set_decim($decimation) +self.$(id).set_center_freq($frequency) +self.$(id).set_gain($gain) +#if $lo_offset() != float('inf') +self.$(id).set_lo_offset($lo_offset) +#end if + set_lo_offset($lo_offset) + set_decim($decimation) + set_center_freq($frequency) + set_gain($gain) + + Output Type + type + enum + + + + + Interface + interface + + string + + + MAC Addr + mac_addr + + string + + + Decimation + decimation + int + + + Frequency (Hz) + frequency + real + + + LO Offset (Hz) + lo_offset + float('inf') + real + #if $lo_offset() == float('inf') then 'part' else 'none'# + + + + Gain (dB) + gain + 0 + real + + + out + $type + + +The USRP2 source outputs 100 Megasamples per second / decimation. + +To use the default ethernet device, leave interface blank. \ +For systems with only 1 USRP2, you may leave the mac address blank. \ +For multi-USRP2 systems, specify the mac address in the form 00:50:C2:85:3x:xx. + + diff --git a/grc/blocks/usrp_dual_sink_x.xml b/grc/blocks/usrp_dual_sink_x.xml new file mode 100644 index 00000000..8f418bec --- /dev/null +++ b/grc/blocks/usrp_dual_sink_x.xml @@ -0,0 +1,193 @@ + + + + USRP Dual Sink + usrp_dual_sink_x + from grc_gnuradio import usrp as grc_usrp + grc_usrp.dual_sink_$(type.fcn)(which=$which) +self.$(id).set_interp_rate($interpolation) +self.$(id).set_frequency_a($frequency_a, verbose=True) +self.$(id).set_frequency_b($frequency_b, verbose=True) +self.$(id).set_gain_a($gain_a) +self.$(id).set_gain_b($gain_b) +#if $lo_offset_a() != float('inf') +self.$(id).set_lo_offset_a($lo_offset_a) +#end if +#if $lo_offset_b() != float('inf') +self.$(id).set_lo_offset_b($lo_offset_b) +#end if +################################################## +## Flex RF A +################################################## +#if $transmit_a.tx_enb +self.$(id).set_enable_a(True) +#end if +#if $transmit_a.auto_tr +self.$(id).set_auto_tr_a(True) +#end if +################################################## +## Flex RF B +################################################## +#if $transmit_b.tx_enb +self.$(id).set_enable_b(True) +#end if +#if $transmit_b.auto_tr +self.$(id).set_auto_tr_b(True) +#end if + set_interp_rate($interpolation) + set_frequency_a($frequency_a) + set_frequency_b($frequency_b) + set_gain_a($gain_a) + set_gain_b($gain_b) + + Input Type + type + enum + + + + + Unit Number + which + 0 + int + + + Interpolation + interpolation + int + + + Frequency A (Hz) + frequency_a + real + + + Frequency B (Hz) + frequency_b + real + + + LO Offset A (Hz) + lo_offset_a + float('inf') + real + #if $lo_offset_a() == float('inf') then 'part' else 'none'# + + + + LO Offset B (Hz) + lo_offset_b + float('inf') + real + #if $lo_offset_b() == float('inf') then 'part' else 'none'# + + + + Gain A (dB) + gain_a + 0 + real + + + Gain B (dB) + gain_b + 0 + real + + + + Transmit A + transmit_a + + enum + #if $transmit_a.tx_enb then 'none' else 'part'# + + + + + + + Transmit B + transmit_b + + enum + #if $transmit_b.tx_enb then 'none' else 'part'# + + + + + + Ain + $type + + + Bin + $type + + +The USRP sink inputs 128 Megasamples per second / interpolation. + +Input amplitude should be between 0 and 32767. + +Flex RF boards only: The "Transmit Setting" must be configured. \ +When set to "Enable" the transmitter is always on. \ +When set to "Auto Transmit/Receive", the transmitter is disabled while receiving. + + diff --git a/grc/blocks/usrp_dual_source_x.xml b/grc/blocks/usrp_dual_source_x.xml new file mode 100644 index 00000000..740895d4 --- /dev/null +++ b/grc/blocks/usrp_dual_source_x.xml @@ -0,0 +1,198 @@ + + + + USRP Dual Source + usrp_dual_source_x + from grc_gnuradio import usrp as grc_usrp + grc_usrp.dual_source_$(type.fcn)(which=$which, rx_ant_a=$rx_ant_a, rx_ant_b=$rx_ant_b) +#if $format() +self.$(id).set_format(width=$format.width, shift=$format.shift) +#end if +self.$(id).set_decim_rate($decimation) +self.$(id).set_frequency_a($frequency_a, verbose=True) +self.$(id).set_frequency_b($frequency_b, verbose=True) +self.$(id).set_gain_a($gain_a) +self.$(id).set_gain_b($gain_b) +#if $lo_offset_a() != float('inf') +self.$(id).set_lo_offset_a($lo_offset_a) +#end if +#if $lo_offset_b() != float('inf') +self.$(id).set_lo_offset_b($lo_offset_b) +#end if + set_decim_rate($decimation) + set_frequency_a($frequency_a) + set_frequency_b($frequency_b) + set_gain_a($gain_a) + set_gain_b($gain_b) + + Output Type + type + enum + + + + + Format + format + + enum + #if $format() then '' else 'part'# + + + + + Unit Number + which + 0 + int + + + Decimation + decimation + int + + + Frequency A (Hz) + frequency_a + real + + + Frequency B (Hz) + frequency_b + real + + + LO Offset A (Hz) + lo_offset_a + float('inf') + real + #if $lo_offset_a() == float('inf') then 'part' else 'none'# + + + + LO Offset B (Hz) + lo_offset_b + float('inf') + real + #if $lo_offset_b() == float('inf') then 'part' else 'none'# + + + + Gain A (dB) + gain_a + 0 + real + + + Gain B (dB) + gain_b + 0 + real + + + + RX Antenna A + rx_ant_a + RXA + string + + + + + + + + + RX Antenna B + rx_ant_b + RXA + string + + + + + + + + Aout + $type + + + Bout + $type + + +The USRP source outputs 64 Megasamples per second / decimation. + +The "Receive Antenna Setting" selects one of the SMA connectors as the data source. \ +Flex RF boards use the "TX/RX" and "RX2" settings. \ +Basic RX and LFRX use the "RXA", "RXB", and "RXAB" settings. \ +All other boards use the "RXA" setting. + + diff --git a/grc/blocks/usrp_probe.xml b/grc/blocks/usrp_probe.xml new file mode 100644 index 00000000..ee207c28 --- /dev/null +++ b/grc/blocks/usrp_probe.xml @@ -0,0 +1,40 @@ + + + + USRP Probe + usrp_probe + + + Unit Number + which + 0 + int + + + Daughter Board + dboard + enum + + + + + + Press "Probe" to retrieve USRP information... + diff --git a/grc/blocks/usrp_simple_sink_x.xml b/grc/blocks/usrp_simple_sink_x.xml new file mode 100644 index 00000000..f3ccf126 --- /dev/null +++ b/grc/blocks/usrp_simple_sink_x.xml @@ -0,0 +1,128 @@ + + + + USRP Sink + usrp_simple_sink_x + from grc_gnuradio import usrp as grc_usrp + grc_usrp.simple_sink_$(type.fcn)(which=$which, side=$side) +self.$(id).set_interp_rate($interpolation) +self.$(id).set_frequency($frequency, verbose=True) +self.$(id).set_gain($gain) +#if $transmit.tx_enb +self.$(id).set_enable(True) +#end if +#if $transmit.auto_tr +self.$(id).set_auto_tr(True) +#end if +#if $lo_offset() != float('inf') +self.$(id).set_lo_offset($lo_offset) +#end if + set_lo_offset($lo_offset) + set_interp_rate($interpolation) + set_frequency($frequency) + set_gain($gain) + + Input Type + type + enum + + + + + Unit Number + which + 0 + int + + + Interpolation + interpolation + int + + + Frequency (Hz) + frequency + real + + + LO Offset (Hz) + lo_offset + float('inf') + real + #if $lo_offset() == float('inf') then 'part' else 'none'# + + + + Gain (dB) + gain + 0 + real + + + Side + side + A + string + + + + + Transmit + transmit + + enum + #if $transmit.tx_enb then 'none' else 'part'# + + + + + + in + $type + + +The USRP sink inputs 128 Megasamples per second / interpolation. + +Input amplitude should be between 0 and 32767. + +Flex RF boards only: The "Transmit Setting" must be configured. \ +When set to "Enable" the transmitter is always on. \ +When set to "Auto Transmit/Receive", the transmitter is disabled while receiving. + + diff --git a/grc/blocks/usrp_simple_source_x.xml b/grc/blocks/usrp_simple_source_x.xml new file mode 100644 index 00000000..1a777bd6 --- /dev/null +++ b/grc/blocks/usrp_simple_source_x.xml @@ -0,0 +1,163 @@ + + + + USRP Source + usrp_simple_source_x + from grc_gnuradio import usrp as grc_usrp + grc_usrp.simple_source_$(type.fcn)(which=$which, side=$side, rx_ant=$rx_ant#if $hb_filters() then ', no_hb=True' else ''#) +#if $format() +self.$(id).set_format(width=$format.width, shift=$format.shift) +#end if +self.$(id).set_decim_rate($decimation) +self.$(id).set_frequency($frequency, verbose=True) +self.$(id).set_gain($gain) +#if $lo_offset() != float('inf') +self.$(id).set_lo_offset($lo_offset) +#end if + set_lo_offset($lo_offset) + set_decim_rate($decimation) + set_frequency($frequency) + set_gain($gain) + + Output Type + type + enum + + + + + Format + format + + enum + #if $format() then '' else 'part'# + + + + + Unit Number + which + 0 + int + + + Decimation + decimation + int + + + Frequency (Hz) + frequency + real + + + LO Offset (Hz) + lo_offset + float('inf') + real + #if $lo_offset() == float('inf') then 'part' else 'none'# + + + + Gain (dB) + gain + 0 + real + + + Side + side + A + string + + + + + RX Antenna + rx_ant + RXA + string + + + + + + + + Halfband Filters + hb_filters + + enum + #if $hb_filters() then 'none' else 'part'# + + + + + out + $type + + +The USRP source outputs 64 Megasamples per second / decimation. + +The "Receive Antenna Setting" selects one of the SMA connectors as the data source. \ +Flex RF boards use the "TX/RX" and "RX2" settings. \ +Basic RX and LFRX use the "RXA", "RXB", and "RXAB" settings. \ +All other boards use the "RXA" setting. + +With the format set to 8 bits and the halfband filters disabled, the USRP can acheive a decimation rate of 4. \ +Disabling the halfband filters requires a special USRP firmware without halfband filters or TX paths. \ +For this reason, the USRP cannot transmit with the halfband filters disabled. + + diff --git a/grc/blocks/variable.xml b/grc/blocks/variable.xml new file mode 100644 index 00000000..afee0f5d --- /dev/null +++ b/grc/blocks/variable.xml @@ -0,0 +1,23 @@ + + + + Variable + variable + self.$(id) = $(id) = $value + + self.set_$(id)($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/blocks/variable_check_box.xml b/grc/blocks/variable_check_box.xml new file mode 100644 index 00000000..59ace503 --- /dev/null +++ b/grc/blocks/variable_check_box.xml @@ -0,0 +1,75 @@ + + + + Variable Check Box + variable_check_box + from gnuradio.wxgui import forms + self.$(id) = $(id) = $value + self.$(id)_check_box = forms.check_box( + parent=self.GetWin(), + value=self.$id, + callback=self.set_$(id), + #if $label() + label=$label, + #else + label='$id', + #end if + true=$true, + false=$false, +) +#set $grid_pos = $grid_pos() +#if not grid_pos +self.Add(self.$(id)_check_box) +#else +self.GridAdd(self.$(id)_check_box, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) +#end if + self.set_$(id)($value) + self.$(id)_check_box.set_value($id) + + Label + label + + string + #if $label() then 'none' else 'part'# + + + Default Value + value + True + raw + + + True + true + True + raw + + + False + false + False + raw + + + Grid Position + grid_pos + + grid_pos + + $value in ($true, $false) + +This block creates a variable with a check box form. \ +Leave the label blank to use the variable id as the label. + +A check box form can switch between two states; \ +the default being True and False. \ +Override True and False to use alternative states. + +Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. + + diff --git a/grc/blocks/variable_chooser.xml b/grc/blocks/variable_chooser.xml new file mode 100644 index 00000000..2f0e9bbf --- /dev/null +++ b/grc/blocks/variable_chooser.xml @@ -0,0 +1,113 @@ + + + + Variable Chooser + variable_chooser + from gnuradio.wxgui import forms + self.$(id) = $(id) = $value + self.$(id)_chooser = forms.$(type)( + parent=self.GetWin(), + value=self.$id, + callback=self.set_$(id), + #if $label() + label=$label, + #else + label='$id', + #end if + choices=$choices, + labels=$labels, +#if $type() == 'radio_buttons' + style=$style, +#end if +) +#set $grid_pos = $grid_pos() +#if not grid_pos +self.Add(self.$(id)_chooser) +#else +self.GridAdd(self.$(id)_chooser, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) +#end if + self.set_$(id)($value) + self.$(id)_chooser.set_value($id) + + Label + label + + string + #if $label() then 'none' else 'part'# + + + Default Value + value + 1 + raw + + + Choices + choices + [1, 2, 3] + raw + + + Labels + labels + [] + raw + + + Type + type + drop_down + enum + + + + + + Style + style + wx.RA_HORIZONTAL + enum + #if $type() == 'radio_buttons' then 'part' else 'all'# + + + + + Grid Position + grid_pos + + grid_pos + + $value in $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/blocks/variable_config.xml b/grc/blocks/variable_config.xml new file mode 100644 index 00000000..f62a3def --- /dev/null +++ b/grc/blocks/variable_config.xml @@ -0,0 +1,86 @@ + + + + Variable Config + variable_config + import ConfigParser + self._$(id)_config = ConfigParser.ConfigParser() +self._$(id)_config.read($config_file) +if not self._$(id)_config.has_section($section): + self._$(id)_config.add_section($section) +try: $(id) = self._$(id)_config.$(type.get)($section, $option) +except: $(id) = $value +self.$(id) = $(id) + + self.set_$(id)($value) + self._$(id)_config.set($section, $option, str($writeback)) +self._$(id)_config.write(open($config_file, 'w')) + + Default Value + value + 0 + $type + + + Type + type + real + enum + + + + + + + Config File + config_file + default + file_open + + + Section + section + main + string + + + Option + option + key + string + + + WriteBack + writeback + None + raw + + +This block represents a variable that can be read from a config file. + +To save the value back into the config file: \ +enter the name of another variable into the writeback param. \ +When the other variable is changed at runtime, the config file will be re-written. + + diff --git a/grc/blocks/variable_slider.xml b/grc/blocks/variable_slider.xml new file mode 100644 index 00000000..6a7c400e --- /dev/null +++ b/grc/blocks/variable_slider.xml @@ -0,0 +1,129 @@ + + + + Variable Slider + variable_slider + from gnuradio.wxgui import forms + self.$(id) = $(id) = $value + _$(id)_sizer = wx.BoxSizer(wx.VERTICAL) +self.$(id)_text_box = forms.text_box( + parent=self.GetWin(), + sizer=_$(id)_sizer, + value=self.$id, + callback=self.set_$(id), + #if $label() + label=$label, + #else + label='$id', + #end if + converter=forms.$(converver)(), + proportion=0, +) +self.$(id)_slider = forms.slider( + parent=self.GetWin(), + sizer=_$(id)_sizer, + value=self.$id, + callback=self.set_$(id), + minimum=$min, + maximum=$max, + num_steps=$num_steps, + style=$style, + cast=$(converver.slider_cast), + proportion=1, +) +#set $grid_pos = $grid_pos() +#if not grid_pos +self.Add(_$(id)_sizer) +#else +self.GridAdd(_$(id)_sizer, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) +#end if + self.set_$(id)($value) + self.$(id)_slider.set_value($id) + self.$(id)_text_box.set_value($id) + + Label + label + + string + #if $label() then 'none' else 'part'# + + + Default Value + value + 50 + real + + + Minimum + min + 0 + real + + + Maximum + max + 100 + real + + + Num Steps + num_steps + 100 + int + part + + + Style + style + wx.SL_HORIZONTAL + enum + part + + + + + Converter + converver + float_converter + 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/blocks/variable_static_text.xml b/grc/blocks/variable_static_text.xml new file mode 100644 index 00000000..0179eb6e --- /dev/null +++ b/grc/blocks/variable_static_text.xml @@ -0,0 +1,88 @@ + + + + Variable Static Text + variable_static_text + from gnuradio.wxgui import forms + self.$(id) = $(id) = $value + self.$(id)_static_text = forms.static_text( + parent=self.GetWin(), + value=self.$id, + callback=self.set_$(id), + #if $label() + label=$label, + #else + label='$id', + #end if + #if $formatter() + converter=forms.$(converver)(formatter=$formatter), + #else + converter=forms.$(converver)(), + #end if +) +#set $grid_pos = $grid_pos() +#if not grid_pos +self.Add(self.$(id)_static_text) +#else +self.GridAdd(self.$(id)_static_text, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) +#end if + self.set_$(id)($value) + self.$(id)_static_text.set_value($id) + + Label + label + + string + #if $label() then 'none' else 'part'# + + + Default Value + value + 0 + raw + + + Converter + converver + float_converter + enum + + + + + + Formatter + formatter + None + raw + part + + + Grid Position + grid_pos + + grid_pos + + +This block creates a variable with a static text form. \ +Leave the label blank to use the variable id as the label. + +Format should be a function/lambda that converts a value into a string or None for the default formatter. + +Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. + + diff --git a/grc/blocks/variable_text_box.xml b/grc/blocks/variable_text_box.xml new file mode 100644 index 00000000..2bcb680f --- /dev/null +++ b/grc/blocks/variable_text_box.xml @@ -0,0 +1,92 @@ + + + + Variable Text Box + variable_text_box + from gnuradio.wxgui import forms + self.$(id) = $(id) = $value + self.$(id)_text_box = forms.text_box( + parent=self.GetWin(), + value=self.$id, + callback=self.set_$(id), + #if $label() + label=$label, + #else + label='$id', + #end if + #if $formatter() + converter=forms.$(converver)(formatter=$formatter), + #else + converter=forms.$(converver)(), + #end if +) +#set $grid_pos = $grid_pos() +#if not grid_pos +self.Add(self.$(id)_text_box) +#else +self.GridAdd(self.$(id)_text_box, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) +#end if + self.set_$(id)($value) + self.$(id)_text_box.set_value($id) + + Label + label + + string + #if $label() then 'none' else 'part'# + + + Default Value + value + 0 + raw + + + Converter + converver + float_converter + enum + + + + + + + Formatter + formatter + None + raw + part + + + 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. + +Format should be a function/lambda that converts a value into a string or None for the default formatter. + +Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. + + diff --git a/grc/blocks/wxgui_constellationsink2.xml b/grc/blocks/wxgui_constellationsink2.xml new file mode 100644 index 00000000..471c9f4a --- /dev/null +++ b/grc/blocks/wxgui_constellationsink2.xml @@ -0,0 +1,118 @@ + + + + Constellation Sink + wxgui_constellationsink2 + from gnuradio.wxgui import constsink_gl + constsink_gl.const_sink_c( + self.GetWin(), + title=$title, + sample_rate=$samp_rate, + frame_rate=$frame_rate, + const_size=$const_size, + M=$M, + theta=$theta, + alpha=$alpha, + fmax=$fmax, + mu=$mu, + gain_mu=$gain_mu, + symbol_rate=$symbol_rate, + omega_limit=$omega_limit, +) +#set $grid_pos = $grid_pos() +#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 Rate + frame_rate + 5 + real + + + Constellation Size + const_size + 2048 + real + + + M + M + 4 + int + + + Theta + theta + 0 + real + + + Alpha + alpha + 0.005 + real + + + Max Freq + fmax + 0.06 + real + + + Mu + mu + 0.5 + real + + + Gain Mu + gain_mu + 0.005 + real + + + Symbol Rate + symbol_rate + samp_rate/4. + real + + + Omega Limit + omega_limit + 0.005 + real + + + 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/blocks/wxgui_fftsink2.xml b/grc/blocks/wxgui_fftsink2.xml new file mode 100644 index 00000000..d7763cb2 --- /dev/null +++ b/grc/blocks/wxgui_fftsink2.xml @@ -0,0 +1,169 @@ + + + + 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, + avg_alpha=#if $avg_alpha() then $avg_alpha else 'None'#, + title=$title, + peak_hold=$peak_hold, +) +#set $grid_pos = $grid_pos() +#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_baseband_freq($baseband_freq) + set_sample_rate($samp_rate) + + 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 + enum + + + + + + + + Y Divs + y_divs + 10 + int + + + Ref Level (dB) + ref_level + 50 + real + + + FFT Size + fft_size + 1024 + int + + + Refresh Rate + fft_rate + 30 + int + + + Peak Hold + peak_hold + False + enum + #if $peak_hold() == 'True' then 'none' else 'part'# + + + + + Average + average + False + enum + #if $average() == 'True' then 'none' else 'part'# + + + + + Average Alpha + avg_alpha + 0 + real + #if $average() == 'True' then 'none' else 'all'# + + + 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/blocks/wxgui_histosink2.xml b/grc/blocks/wxgui_histosink2.xml new file mode 100644 index 00000000..4de57b1c --- /dev/null +++ b/grc/blocks/wxgui_histosink2.xml @@ -0,0 +1,56 @@ + + + + Histo Sink + wxgui_histosink2 + from gnuradio.wxgui import histosink_gl + histosink_gl.histo_sink_f( + self.GetWin(), + title=$title, + num_bins=$num_bins, + frame_size=$frame_size, +) +#set $grid_pos = $grid_pos() +#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_num_bins($num_bins) + set_frame_size($frame_size) + + Title + title + Histogram Plot + string + + + Num Bins + num_bins + 27 + int + + + Frame Size + frame_size + 1000 + int + + + Grid Position + grid_pos + + grid_pos + + + in + float + + +Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. + + diff --git a/grc/blocks/wxgui_numbersink2.xml b/grc/blocks/wxgui_numbersink2.xml new file mode 100644 index 00000000..7cc90b69 --- /dev/null +++ b/grc/blocks/wxgui_numbersink2.xml @@ -0,0 +1,171 @@ + + + + Number Sink + wxgui_numbersink2 + from gnuradio.wxgui import numbersink2 + numbersink2.$(type.fcn)( + self.GetWin(), + unit=$units, + 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=$average, + avg_alpha=#if $avg_alpha() then $avg_alpha else 'None'#, + label=$title, + peak_hold=$peak_hold, + show_gauge=$show_gauge, +) +#set $grid_pos = $grid_pos() +#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 + + + 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 + 0 + real + + + Number Rate + number_rate + 15 + int + + + Peak Hold + peak_hold + False + enum + #if $peak_hold() == 'True' then 'none' else 'part'# + + + + + Average + average + False + enum + #if $average() == 'True' then 'none' else 'part'# + + + + + Average Alpha + avg_alpha + 0 + real + #if $average() == 'True' then 'none' else 'all'# + + + 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. + +Incoming numbers are multiplied by the factor, and then added-to by the reference level. + + diff --git a/grc/blocks/wxgui_scopesink2.xml b/grc/blocks/wxgui_scopesink2.xml new file mode 100644 index 00000000..78c39f80 --- /dev/null +++ b/grc/blocks/wxgui_scopesink2.xml @@ -0,0 +1,126 @@ + + + + Scope Sink + wxgui_scopesink2 + from gnuradio.wxgui import scopesink2 + from gnuradio import gr + scopesink2.$(type.fcn)( + self.GetWin(), + title=$title, + sample_rate=$samp_rate, + v_scale=$v_scale, + t_scale=$t_scale, + ac_couple=$ac_couple, + xy_mode=$xy_mode, + num_inputs=$num_inputs, +) +#set $grid_pos = $grid_pos() +#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 + + + V Scale + v_scale + 0 + real + + + T Scale + t_scale + 0 + real + + + AC Couple + ac_couple + False + enum + #if $ac_couple() == 'True' then 'none' else 'part'# + + + + + XY Mode + xy_mode + False + enum + #if $xy_mode() == 'True' then 'none' else 'part'# + + + + + Num Inputs + num_inputs + 1 + int + + + Grid Position + grid_pos + + grid_pos + + not $xy_mode or '$type' == 'complex' or $num_inputs != 1 + + in + $type + $num_inputs + + +Set the V Scale to 0 for the scope to auto-scale. + +Set the T Scale to 0 for automatic setting. + +XY Mode allows the scope to initialize as an XY plotter. + +Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. + + diff --git a/grc/blocks/wxgui_waterfallsink2.xml b/grc/blocks/wxgui_waterfallsink2.xml new file mode 100644 index 00000000..6d76ee86 --- /dev/null +++ b/grc/blocks/wxgui_waterfallsink2.xml @@ -0,0 +1,126 @@ + + + + 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, + avg_alpha=#if $avg_alpha() then $avg_alpha else 'None'#, + title=$title, +) +#set $grid_pos = $grid_pos() +#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_baseband_freq($baseband_freq) + set_sample_rate($samp_rate) + + 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/blocks/xmlrpc_client.xml b/grc/blocks/xmlrpc_client.xml new file mode 100644 index 00000000..dc4d154d --- /dev/null +++ b/grc/blocks/xmlrpc_client.xml @@ -0,0 +1,42 @@ + + + + XMLRPC Client + xmlrpc_client + import xmlrpclib + xmlrpclib.Server('http://$(addr()):$(port)') + $(callback())($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/blocks/xmlrpc_server.xml b/grc/blocks/xmlrpc_server.xml new file mode 100644 index 00000000..6c31bd1a --- /dev/null +++ b/grc/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/cpp/README b/grc/cpp/README new file mode 100644 index 00000000..3eccc5db --- /dev/null +++ b/grc/cpp/README @@ -0,0 +1,5 @@ +GRC could be used to generate c++ based flowgraphs: + +* A few base and gui classes would be overridden. +* Block info could be extracted from the doxygen xml. +* New flowgraph templates would be designed. diff --git a/grc/data/Makefile.am b/grc/data/Makefile.am deleted file mode 100644 index 961c183f..00000000 --- a/grc/data/Makefile.am +++ /dev/null @@ -1,24 +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 = platforms diff --git a/grc/data/platforms/Makefile.am b/grc/data/platforms/Makefile.am deleted file mode 100644 index d26abd9b..00000000 --- a/grc/data/platforms/Makefile.am +++ /dev/null @@ -1,24 +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 = base python diff --git a/grc/data/platforms/base/Makefile.am b/grc/data/platforms/base/Makefile.am deleted file mode 100644 index d323a144..00000000 --- a/grc/data/platforms/base/Makefile.am +++ /dev/null @@ -1,28 +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 = $(pkgdatadir)/$(grc_base_data_reldir) - -dist_ourdata_DATA = \ - block_tree.dtd \ - flow_graph.dtd diff --git a/grc/data/platforms/base/block_tree.dtd b/grc/data/platforms/base/block_tree.dtd deleted file mode 100644 index be1524a3..00000000 --- a/grc/data/platforms/base/block_tree.dtd +++ /dev/null @@ -1,26 +0,0 @@ - - - - - diff --git a/grc/data/platforms/base/flow_graph.dtd b/grc/data/platforms/base/flow_graph.dtd deleted file mode 100644 index 904147b3..00000000 --- a/grc/data/platforms/base/flow_graph.dtd +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/grc/data/platforms/python/Makefile.am b/grc/data/platforms/python/Makefile.am deleted file mode 100644 index 3b056b3f..00000000 --- a/grc/data/platforms/python/Makefile.am +++ /dev/null @@ -1,32 +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 = $(pkgdatadir)/$(grc_python_data_reldir) - -dist_ourdata_DATA = \ - block.dtd \ - block_tree.xml \ - default_flow_graph.grc \ - flow_graph.tmpl diff --git a/grc/data/platforms/python/block.dtd b/grc/data/platforms/python/block.dtd deleted file mode 100644 index d892b128..00000000 --- a/grc/data/platforms/python/block.dtd +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/grc/data/platforms/python/block_tree.xml b/grc/data/platforms/python/block_tree.xml deleted file mode 100644 index 074b7976..00000000 --- a/grc/data/platforms/python/block_tree.xml +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - Sources - const_source_x - 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 - blks2_tcp_source - gr_udp_source - audio_source - gr_wavfile_source - pad_source - - - Sinks - blks2_variable_sink_x - gr_vector_sink_x - gr_null_sink - gr_file_sink - blks2_tcp_sink - gr_udp_sink - audio_sink - gr_wavfile_sink - pad_sink - - - Graphical Sinks - wxgui_numbersink2 - wxgui_scopesink2 - wxgui_fftsink2 - wxgui_constellationsink2 - wxgui_waterfallsink2 - wxgui_histosink2 - - - Operators - gr_add_xx - gr_sub_xx - gr_multiply_xx - 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 - - blks2_packet_decoder - blks2_packet_encoder - - - 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 - gr_channel_model - - blks2_synthesis_filterbank - blks2_analysis_filterbank - - 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_ofdm_mod - blks2_ofdm_demod - - - Error Correction - - Trellis - trellis_encoder_xx - trellis_metrics_x - trellis_permutation - trellis_siso_combined_f - trellis_siso_f - trellis_viterbi_combined_xx - trellis_viterbi_x - - - gr_encode_ccsds_27_bb - gr_decode_ccsds_27_fb - - - Line Coding - gr_scrambler_bb - gr_descrambler_bb - - - Probes - gr_probe_avg_mag_sqrd_x - gr_probe_density_b - gr_probe_mpsk_snr_c - probe_function - - - USRP - usrp_simple_source_x - usrp_simple_sink_x - usrp_dual_source_x - usrp_dual_sink_x - usrp2_source_xxxx - usrp2_sink_xxxx - - - Variables - variable - variable_slider - variable_chooser - variable_text_box - 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 deleted file mode 100644 index d3b3564c..00000000 --- a/grc/data/platforms/python/blocks/Makefile.am +++ /dev/null @@ -1,220 +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 = $(pkgdatadir)/$(grc_blocks_data_reldir) - -dist_ourdata_DATA = \ - audio_sink.xml \ - audio_source.xml \ - band_pass_filter.xml \ - band_reject_filter.xml \ - blks2_am_demod_cf.xml \ - blks2_analysis_filterbank.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_ofdm_demod.xml \ - blks2_ofdm_mod.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_tcp_sink.xml \ - blks2_tcp_source.xml \ - blks2_valve.xml \ - blks2_variable_sink_x.xml \ - blks2_wfm_rcv.xml \ - blks2_wfm_rcv_pll.xml \ - blks2_wfm_tx.xml \ - const_source_x.xml \ - gr_add_const_vxx.xml \ - gr_add_xx.xml \ - gr_agc2_xx.xml \ - gr_agc_xx.xml \ - gr_and_xx.xml \ - gr_argmax_xx.xml \ - gr_binary_slicer_fb.xml \ - gr_channel_model.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_descrambler_bb.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_xx.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_probe_avg_mag_sqrd_x.xml \ - gr_probe_density_b.xml \ - gr_probe_mpsk_snr_c.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_scrambler_bb.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 \ - probe_function.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 \ - usrp2_probe.xml \ - usrp2_sink_xxxx.xml \ - usrp2_source_xxxx.xml \ - usrp_dual_sink_x.xml \ - usrp_dual_source_x.xml \ - usrp_probe.xml \ - usrp_simple_sink_x.xml \ - usrp_simple_source_x.xml \ - variable.xml \ - variable_chooser.xml \ - variable_slider.xml \ - variable_text_box.xml \ - wxgui_constellationsink2.xml \ - wxgui_fftsink2.xml \ - wxgui_histosink2.xml \ - wxgui_numbersink2.xml \ - wxgui_scopesink2.xml \ - wxgui_waterfallsink2.xml \ - xmlrpc_client.xml \ - xmlrpc_server.xml diff --git a/grc/data/platforms/python/blocks/audio_sink.xml b/grc/data/platforms/python/blocks/audio_sink.xml deleted file mode 100644 index 75d58347..00000000 --- a/grc/data/platforms/python/blocks/audio_sink.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - Audio Sink - audio_sink - from gnuradio import audio - audio.sink($samp_rate, $device_name, $ok_to_block) - - Sample Rate - samp_rate - 32000 - int - - - - - - - - - Device Name - device_name - - string - #if $device_name() then 'none' else 'part'# - - - OK to Block - ok_to_block - True - enum - part - - - - - 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. \ -ALSA users with audio trouble may try setting the device name to plughw: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 deleted file mode 100644 index 1f5d1033..00000000 --- a/grc/data/platforms/python/blocks/audio_source.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - Audio Source - audio_source - from gnuradio import audio - audio.source($samp_rate, $device_name, $ok_to_block) - - Sample Rate - samp_rate - 32000 - int - - - - - - - - - Device Name - device_name - - string - #if $device_name() then 'none' else 'part'# - - - OK to Block - ok_to_block - True - enum - part - - - - - 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. \ -ALSA users with audio trouble may try setting the device name to plughw: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 deleted file mode 100644 index 2dac2960..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/band_reject_filter.xml b/grc/data/platforms/python/blocks/band_reject_filter.xml deleted file mode 100644 index ed6a5fa8..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_am_demod_cf.xml b/grc/data/platforms/python/blocks/blks2_am_demod_cf.xml deleted file mode 100644 index 898c613b..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_analysis_filterbank.xml b/grc/data/platforms/python/blocks/blks2_analysis_filterbank.xml deleted file mode 100644 index 93cfa30a..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_dxpsk_demod.xml b/grc/data/platforms/python/blocks/blks2_dxpsk_demod.xml deleted file mode 100644 index 20c7bd7f..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_dxpsk_mod.xml b/grc/data/platforms/python/blocks/blks2_dxpsk_mod.xml deleted file mode 100644 index e165fe9b..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_error_rate.xml b/grc/data/platforms/python/blocks/blks2_error_rate.xml deleted file mode 100644 index 91a30320..00000000 --- a/grc/data/platforms/python/blocks/blks2_error_rate.xml +++ /dev/null @@ -1,69 +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 - $type.hide_bps - - - 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 deleted file mode 100644 index 6f38dab6..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_fm_demod_cf.xml b/grc/data/platforms/python/blocks/blks2_fm_demod_cf.xml deleted file mode 100644 index 2ce1fb97..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_fm_preemph.xml b/grc/data/platforms/python/blocks/blks2_fm_preemph.xml deleted file mode 100644 index 672a7a7b..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_gmsk_demod.xml b/grc/data/platforms/python/blocks/blks2_gmsk_demod.xml deleted file mode 100644 index c8103981..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_gmsk_mod.xml b/grc/data/platforms/python/blocks/blks2_gmsk_mod.xml deleted file mode 100644 index ab57357e..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_logpwrfft_x.xml b/grc/data/platforms/python/blocks/blks2_logpwrfft_x.xml deleted file mode 100644 index ef49c443..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_nbfm_rx.xml b/grc/data/platforms/python/blocks/blks2_nbfm_rx.xml deleted file mode 100644 index d332b9a6..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_nbfm_tx.xml b/grc/data/platforms/python/blocks/blks2_nbfm_tx.xml deleted file mode 100644 index 3aa7ede0..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_ofdm_demod.xml b/grc/data/platforms/python/blocks/blks2_ofdm_demod.xml deleted file mode 100644 index ac5ee479..00000000 --- a/grc/data/platforms/python/blocks/blks2_ofdm_demod.xml +++ /dev/null @@ -1,122 +0,0 @@ - - - - OFDM Demod - blks2_ofdm_demod - from grc_gnuradio import blks2 as grc_blks2 - from gnuradio import blks2 - grc_blks2.packet_demod_$(type.fcn)(blks2.ofdm_demod( - options=grc_blks2.options( - modulation="$modulation", - fft_length=$fft_length, - occupied_tones=$occupied_tones, - cp_length=$cp_length, - snr=$snr, - log=None, - verbose=None, - ), - callback=lambda ok, payload: self.$(id).recv_pkt(ok, payload), - ), -) - - Output Type - type - float - enum - - - - - - - - Modulation - modulation - enum - - - - - - - - - - FFT Length - fft_length - 512 - int - - - Occupied Tones - occupied_tones - 200 - int - - - Cyclic Prefix Length - cp_length - 128 - int - - - SNR - snr - 10 - real - - - in - complex - - - out - $type - - Payload Length: 0 for automatic. - diff --git a/grc/data/platforms/python/blocks/blks2_ofdm_mod.xml b/grc/data/platforms/python/blocks/blks2_ofdm_mod.xml deleted file mode 100644 index 2c54d10f..00000000 --- a/grc/data/platforms/python/blocks/blks2_ofdm_mod.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - - OFDM Mod - blks2_ofdm_mod - from grc_gnuradio import blks2 as grc_blks2 - from gnuradio import blks2 - grc_blks2.packet_mod_$(type.fcn)(blks2.ofdm_mod( - options=grc_blks2.options( - modulation="$modulation", - fft_length=$fft_length, - occupied_tones=$occupied_tones, - cp_length=$cp_length, - pad_for_usrp=$pad_for_usrp, - log=None, - verbose=None, - ), - ), - payload_length=$payload_length, -) - - Input Type - type - float - enum - - - - - - - - Modulation - modulation - enum - - - - - - - - - - FFT Length - fft_length - 512 - int - - - Occupied Tones - occupied_tones - 200 - int - - - Cyclic Prefix Length - cp_length - 128 - int - - - Pad for USRP - pad_for_usrp - enum - - - - - Payload Length - payload_length - 0 - int - - - in - $type - - - out - complex - - Payload Length: 0 for automatic. - diff --git a/grc/data/platforms/python/blocks/blks2_packet_decoder.xml b/grc/data/platforms/python/blocks/blks2_packet_decoder.xml deleted file mode 100644 index 07b0d1f2..00000000 --- a/grc/data/platforms/python/blocks/blks2_packet_decoder.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - Packet Decoder - blks2_packet_decoder - from grc_gnuradio import blks2 as grc_blks2 - grc_blks2.packet_demod_$(type.fcn)(grc_blks2.packet_decoder( - access_code=$access_code, - threshold=$threshold, - callback=lambda ok, payload: self.$(id).recv_pkt(ok, payload), - ), -) - - Output Type - type - float - enum - - - - - - - - Access Code - access_code - - string - - - Threshold - threshold - -1 - int - - - in - byte - - - out - $type - - -Packet decoder block, for use with the gnuradio demodulator blocks: gmsk, psk, qam. - -Access Code: string of 1's and 0's, leave blank for automatic. - -Threshold: -1 for automatic. - - diff --git a/grc/data/platforms/python/blocks/blks2_packet_encoder.xml b/grc/data/platforms/python/blocks/blks2_packet_encoder.xml deleted file mode 100644 index b184ebd3..00000000 --- a/grc/data/platforms/python/blocks/blks2_packet_encoder.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - - Packet Encoder - blks2_packet_encoder - from grc_gnuradio import blks2 as grc_blks2 - grc_blks2.packet_mod_$(type.fcn)(grc_blks2.packet_encoder( - samples_per_symbol=$samples_per_symbol, - bits_per_symbol=$bits_per_symbol, - access_code=$access_code, - pad_for_usrp=$pad_for_usrp, - ), - payload_length=$payload_length, -) - - 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 - 0 - int - - - in - $type - - - out - byte - - -Packet encoder block, for use with the gnuradio modulator blocks: gmsk, dpsk, qam. - -Access Code: string of 1's and 0's, leave blank for automatic. - -Payload Length: 0 for automatic. - -Bits/Symbol should be set accordingly: - gmsk -> 1 - dbpsk -> 1 - dqpsk -> 2 - d8psk -> 3 - qam8 -> 3 - qam16 -> 4 - qam64 -> 6 - qam256 -> 8 - - diff --git a/grc/data/platforms/python/blocks/blks2_qamx_demod.xml b/grc/data/platforms/python/blocks/blks2_qamx_demod.xml deleted file mode 100644 index 93dbe4bb..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_qamx_mod.xml b/grc/data/platforms/python/blocks/blks2_qamx_mod.xml deleted file mode 100644 index 25a9fb24..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_rational_resampler_xxx.xml b/grc/data/platforms/python/blocks/blks2_rational_resampler_xxx.xml deleted file mode 100644 index b92ec8ec..00000000 --- a/grc/data/platforms/python/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() - taps=$taps, -#else - taps=None, -#end if -#if $fractional_bw() != 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 deleted file mode 100644 index 2d89df18..00000000 --- a/grc/data/platforms/python/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(int($input_index)) - set_output_index(int($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 deleted file mode 100644 index fc60a31e..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_stream_to_vector_decimator.xml b/grc/data/platforms/python/blocks/blks2_stream_to_vector_decimator.xml deleted file mode 100644 index 25f8f7a6..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_synthesis_filterbank.xml b/grc/data/platforms/python/blocks/blks2_synthesis_filterbank.xml deleted file mode 100644 index 5979ed3f..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_tcp_sink.xml b/grc/data/platforms/python/blocks/blks2_tcp_sink.xml deleted file mode 100644 index cfe7b42d..00000000 --- a/grc/data/platforms/python/blocks/blks2_tcp_sink.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - TCP Sink - blks2_tcp_sink - from grc_gnuradio import blks2 as grc_blks2 - grc_blks2.tcp_sink( - itemsize=$type.size*$vlen, - addr=$addr, - port=$port, - server=$server, -) - - Input Type - type - enum - - - - - - - - Address - addr - 127.0.0.1 - string - - - Port - port - 0 - int - - - Mode - server - False - enum - - - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - -In client mode, we attempt to connect to a server at the given address and port. \ -In server mode, we bind a socket to the given address and port and accept the first client. - - diff --git a/grc/data/platforms/python/blocks/blks2_tcp_source.xml b/grc/data/platforms/python/blocks/blks2_tcp_source.xml deleted file mode 100644 index 6bf742aa..00000000 --- a/grc/data/platforms/python/blocks/blks2_tcp_source.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - TCP Source - blks2_tcp_source - from grc_gnuradio import blks2 as grc_blks2 - grc_blks2.tcp_source( - itemsize=$type.size*$vlen, - addr=$addr, - port=$port, - server=$server, -) - - Output Type - type - enum - - - - - - - - Address - addr - 127.0.0.1 - string - - - Port - port - 0 - int - - - Mode - server - True - enum - - - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - out - $type - $vlen - - -In client mode, we attempt to connect to a server at the given address and port. \ -In server mode, we bind a socket to the given address and port and accept the first client. - - diff --git a/grc/data/platforms/python/blocks/blks2_valve.xml b/grc/data/platforms/python/blocks/blks2_valve.xml deleted file mode 100644 index 47c55352..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_variable_sink_x.xml b/grc/data/platforms/python/blocks/blks2_variable_sink_x.xml deleted file mode 100644 index 5709c9f7..00000000 --- a/grc/data/platforms/python/blocks/blks2_variable_sink_x.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - Variable Sink - blks2_variable_sink_x - from grc_gnuradio import blks2 as grc_blks2 - grc_blks2.variable_sink_$(type.fcn)( - vlen=$vlen, - decim=$decim, - callback=self.set_$(variable()), -) - set_decim($decim) - - Type - type - enum - - - - - - - - Variable - variable - - string - - - Decimation - decim - 1 - int - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - -Read samples from the input stream and \ -write one in every decimation samples to the variable. - -The variable must be the id of an existing variable block. - - diff --git a/grc/data/platforms/python/blocks/blks2_wfm_rcv.xml b/grc/data/platforms/python/blocks/blks2_wfm_rcv.xml deleted file mode 100644 index 37fb3ba8..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/blks2_wfm_rcv_pll.xml b/grc/data/platforms/python/blocks/blks2_wfm_rcv_pll.xml deleted file mode 100644 index 2771350c..00000000 --- a/grc/data/platforms/python/blocks/blks2_wfm_rcv_pll.xml +++ /dev/null @@ -1,37 +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 - - - Lout - float - - - Rout - float - - diff --git a/grc/data/platforms/python/blocks/blks2_wfm_tx.xml b/grc/data/platforms/python/blocks/blks2_wfm_tx.xml deleted file mode 100644 index cff92d81..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/const_source_x.xml b/grc/data/platforms/python/blocks/const_source_x.xml deleted file mode 100644 index fe8e56ec..00000000 --- a/grc/data/platforms/python/blocks/const_source_x.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - Constant Source - const_source_x - from gnuradio import gr - gr.sig_source_$(type.fcn)(0, gr.GR_CONST_WAVE, 0, 0, $const) - set_offset($const) - - Output Type - type - enum - - - - - - - Constant - const - 0 - $type.const_type - - - out - $type - - diff --git a/grc/data/platforms/python/blocks/gr_add_const_vxx.xml b/grc/data/platforms/python/blocks/gr_add_const_vxx.xml deleted file mode 100644 index 9f1c545a..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_add_xx.xml b/grc/data/platforms/python/blocks/gr_add_xx.xml deleted file mode 100644 index 97ed9283..00000000 --- a/grc/data/platforms/python/blocks/gr_add_xx.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - Add - gr_add_xx - 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 deleted file mode 100644 index fb3ae570..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_agc_xx.xml b/grc/data/platforms/python/blocks/gr_agc_xx.xml deleted file mode 100644 index c87d239e..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_and_xx.xml b/grc/data/platforms/python/blocks/gr_and_xx.xml deleted file mode 100644 index 9ed00609..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_argmax_xx.xml b/grc/data/platforms/python/blocks/gr_argmax_xx.xml deleted file mode 100644 index e3e4e3ea..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_binary_slicer_fb.xml b/grc/data/platforms/python/blocks/gr_binary_slicer_fb.xml deleted file mode 100644 index 85d71e70..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_channel_model.xml b/grc/data/platforms/python/blocks/gr_channel_model.xml deleted file mode 100644 index e23062df..00000000 --- a/grc/data/platforms/python/blocks/gr_channel_model.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - Channel Model - gr_channel_model - from gnuradio import gr - from gnuradio.gr import firdes - gr.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) - set_timing_offset($epsilon) - - Noise Voltage - noise_voltage - 0.0 - real - - - Frequency Offset - freq_offset - 0.0 - real - - - Epsilon - epsilon - 1.0 - real - - - Taps - taps - 1.0 + 1.0j - complex_vector - - - Seed - seed - 42 - int - - - in - complex - - - out - complex - - diff --git a/grc/data/platforms/python/blocks/gr_char_to_float.xml b/grc/data/platforms/python/blocks/gr_char_to_float.xml deleted file mode 100644 index 9ab77805..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_chunks_to_symbols.xml b/grc/data/platforms/python/blocks/gr_chunks_to_symbols.xml deleted file mode 100644 index b54e710e..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_clock_recovery_mm_xx.xml b/grc/data/platforms/python/blocks/gr_clock_recovery_mm_xx.xml deleted file mode 100644 index 613cc23b..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_cma_equalizer_cc.xml b/grc/data/platforms/python/blocks/gr_cma_equalizer_cc.xml deleted file mode 100644 index 142fb6d8..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_complex_to_arg.xml b/grc/data/platforms/python/blocks/gr_complex_to_arg.xml deleted file mode 100644 index a7bbacd7..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_complex_to_float.xml b/grc/data/platforms/python/blocks/gr_complex_to_float.xml deleted file mode 100644 index 5b02c3d3..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_complex_to_imag.xml b/grc/data/platforms/python/blocks/gr_complex_to_imag.xml deleted file mode 100644 index 7c120eed..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_complex_to_interleaved_short.xml b/grc/data/platforms/python/blocks/gr_complex_to_interleaved_short.xml deleted file mode 100644 index 5e999599..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_complex_to_mag.xml b/grc/data/platforms/python/blocks/gr_complex_to_mag.xml deleted file mode 100644 index adc95f20..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_complex_to_mag_squared.xml b/grc/data/platforms/python/blocks/gr_complex_to_mag_squared.xml deleted file mode 100644 index cd23bfb5..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_complex_to_real.xml b/grc/data/platforms/python/blocks/gr_complex_to_real.xml deleted file mode 100644 index ae9ec7b1..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_conjugate_cc.xml b/grc/data/platforms/python/blocks/gr_conjugate_cc.xml deleted file mode 100644 index 0b4deb34..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_constellation_decoder_cb.xml b/grc/data/platforms/python/blocks/gr_constellation_decoder_cb.xml deleted file mode 100644 index 99d897a3..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_correlate_access_code_bb.xml b/grc/data/platforms/python/blocks/gr_correlate_access_code_bb.xml deleted file mode 100644 index e13d2d07..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_costas_loop_cc.xml b/grc/data/platforms/python/blocks/gr_costas_loop_cc.xml deleted file mode 100644 index e0db8bc5..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_cpfsk_bc.xml b/grc/data/platforms/python/blocks/gr_cpfsk_bc.xml deleted file mode 100644 index d5549d93..00000000 --- a/grc/data/platforms/python/blocks/gr_cpfsk_bc.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - CPFSK - gr_cpfsk_bc - from gnuradio import gr - 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 deleted file mode 100644 index aed0e8d3..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_decode_ccsds_27_fb.xml b/grc/data/platforms/python/blocks/gr_decode_ccsds_27_fb.xml deleted file mode 100644 index 03b31db8..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_deinterleave.xml b/grc/data/platforms/python/blocks/gr_deinterleave.xml deleted file mode 100644 index a7482978..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_delay.xml b/grc/data/platforms/python/blocks/gr_delay.xml deleted file mode 100644 index 64a774de..00000000 --- a/grc/data/platforms/python/blocks/gr_delay.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - Delay - gr_delay - from gnuradio import gr - gr.delay($type.size*$vlen, $delay) - set_delay($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_descrambler_bb.xml b/grc/data/platforms/python/blocks/gr_descrambler_bb.xml deleted file mode 100644 index 5cfbcc20..00000000 --- a/grc/data/platforms/python/blocks/gr_descrambler_bb.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - Descrambler - gr_descrambler_bb - from gnuradio import gr - gr.descrambler_bb($mask, $seed, $len) - - Mask - mask - 0x8A - hex - - - Seed - seed - 0x7F - hex - - - Length - len - 7 - int - - - in - byte - - - out - byte - - diff --git a/grc/data/platforms/python/blocks/gr_diff_decoder_bb.xml b/grc/data/platforms/python/blocks/gr_diff_decoder_bb.xml deleted file mode 100644 index ea7cf173..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_diff_encoder_bb.xml b/grc/data/platforms/python/blocks/gr_diff_encoder_bb.xml deleted file mode 100644 index 21241eac..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_diff_phasor_cc.xml b/grc/data/platforms/python/blocks/gr_diff_phasor_cc.xml deleted file mode 100644 index 2b2d7e37..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_divide_xx.xml b/grc/data/platforms/python/blocks/gr_divide_xx.xml deleted file mode 100644 index 04667bc2..00000000 --- a/grc/data/platforms/python/blocks/gr_divide_xx.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - Divide - gr_divide_xx - from gnuradio import gr - gr.divide_$(type.fcn)($vlen) - - IO Type - type - enum - - - - - - - Vec Length - vlen - 1 - int - - - Num Inputs - num_inputs - 2 - int - - $vlen > 0 - $num_inputs >= 2 - - in - $type - $vlen - $num_inputs - - - out - $type - $vlen - - diff --git a/grc/data/platforms/python/blocks/gr_dpll_bb.xml b/grc/data/platforms/python/blocks/gr_dpll_bb.xml deleted file mode 100644 index 044d398f..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_encode_ccsds_27_bb.xml b/grc/data/platforms/python/blocks/gr_encode_ccsds_27_bb.xml deleted file mode 100644 index f31e6b6c..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_feedforward_agc_cc.xml b/grc/data/platforms/python/blocks/gr_feedforward_agc_cc.xml deleted file mode 100644 index 24e80953..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_fft_filter_xxx.xml b/grc/data/platforms/python/blocks/gr_fft_filter_xxx.xml deleted file mode 100644 index c1633094..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_fft_vxx.xml b/grc/data/platforms/python/blocks/gr_fft_vxx.xml deleted file mode 100644 index d398486e..00000000 --- a/grc/data/platforms/python/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() == "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 deleted file mode 100644 index 880dc275..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_file_source.xml b/grc/data/platforms/python/blocks/gr_file_source.xml deleted file mode 100644 index fcc7a704..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_filter_delay_fc.xml b/grc/data/platforms/python/blocks/gr_filter_delay_fc.xml deleted file mode 100644 index 30d65bf8..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_fir_filter_xxx.xml b/grc/data/platforms/python/blocks/gr_fir_filter_xxx.xml deleted file mode 100644 index c4de8f53..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_float_to_char.xml b/grc/data/platforms/python/blocks/gr_float_to_char.xml deleted file mode 100644 index 907de774..00000000 --- a/grc/data/platforms/python/blocks/gr_float_to_char.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - Float To Char - gr_float_to_char - from gnuradio import 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 deleted file mode 100644 index a1644efd..00000000 --- a/grc/data/platforms/python/blocks/gr_float_to_complex.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - Float To Complex - gr_float_to_complex - from gnuradio import gr - gr.float_to_complex($vlen) - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - float - $vlen - - - in - float - $vlen - 1 - - - out - complex - $vlen - - diff --git a/grc/data/platforms/python/blocks/gr_float_to_short.xml b/grc/data/platforms/python/blocks/gr_float_to_short.xml deleted file mode 100644 index cb2bcd4b..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_float_to_uchar.xml b/grc/data/platforms/python/blocks/gr_float_to_uchar.xml deleted file mode 100644 index aa804d7d..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_fractional_interpolator_xx.xml b/grc/data/platforms/python/blocks/gr_fractional_interpolator_xx.xml deleted file mode 100644 index 8d65ff8b..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_freq_xlating_fir_filter_xxx.xml b/grc/data/platforms/python/blocks/gr_freq_xlating_fir_filter_xxx.xml deleted file mode 100644 index e3ee6697..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_frequency_modulator_fc.xml b/grc/data/platforms/python/blocks/gr_frequency_modulator_fc.xml deleted file mode 100644 index f18d9f1e..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_glfsr_source_x.xml b/grc/data/platforms/python/blocks/gr_glfsr_source_x.xml deleted file mode 100644 index 88fb6679..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_goertzel_fc.xml b/grc/data/platforms/python/blocks/gr_goertzel_fc.xml deleted file mode 100644 index 2105445d..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_head.xml b/grc/data/platforms/python/blocks/gr_head.xml deleted file mode 100644 index e5ff7f6a..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_hilbert_fc.xml b/grc/data/platforms/python/blocks/gr_hilbert_fc.xml deleted file mode 100644 index 165e8da2..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_iir_filter_ffd.xml b/grc/data/platforms/python/blocks/gr_iir_filter_ffd.xml deleted file mode 100644 index 9799150e..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_integrate_xx.xml b/grc/data/platforms/python/blocks/gr_integrate_xx.xml deleted file mode 100644 index d0ebd42e..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_interleave.xml b/grc/data/platforms/python/blocks/gr_interleave.xml deleted file mode 100644 index 3db16ab5..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_interleaved_short_to_complex.xml b/grc/data/platforms/python/blocks/gr_interleaved_short_to_complex.xml deleted file mode 100644 index e3023e49..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_interp_fir_filter_xxx.xml b/grc/data/platforms/python/blocks/gr_interp_fir_filter_xxx.xml deleted file mode 100644 index 55375ae0..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_iqcomp_cc.xml b/grc/data/platforms/python/blocks/gr_iqcomp_cc.xml deleted file mode 100644 index 1603bdc4..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_keep_one_in_n.xml b/grc/data/platforms/python/blocks/gr_keep_one_in_n.xml deleted file mode 100644 index 21595b75..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_kludge_copy.xml b/grc/data/platforms/python/blocks/gr_kludge_copy.xml deleted file mode 100644 index 3c817c57..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_map_bb.xml b/grc/data/platforms/python/blocks/gr_map_bb.xml deleted file mode 100644 index 20d6bd2b..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_max_xx.xml b/grc/data/platforms/python/blocks/gr_max_xx.xml deleted file mode 100644 index 9dbbe60e..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_moving_average_xx.xml b/grc/data/platforms/python/blocks/gr_moving_average_xx.xml deleted file mode 100644 index b70943c7..00000000 --- a/grc/data/platforms/python/blocks/gr_moving_average_xx.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - Moving Average - gr_moving_average_xx - from gnuradio import gr - gr.moving_average_$(type.fcn)($length, $scale, $max_iter) - set_length_and_scale($length, $scale) - - 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 deleted file mode 100644 index 843c3a4c..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_mpsk_sync_cc.xml b/grc/data/platforms/python/blocks/gr_mpsk_sync_cc.xml deleted file mode 100644 index fd08f834..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_multiply_const_vxx.xml b/grc/data/platforms/python/blocks/gr_multiply_const_vxx.xml deleted file mode 100644 index 1309d75c..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_multiply_xx.xml b/grc/data/platforms/python/blocks/gr_multiply_xx.xml deleted file mode 100644 index 60f65c27..00000000 --- a/grc/data/platforms/python/blocks/gr_multiply_xx.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - Multiply - gr_multiply_xx - 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 deleted file mode 100644 index a9a857c6..00000000 --- a/grc/data/platforms/python/blocks/gr_mute_xx.xml +++ /dev/null @@ -1,61 +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/platforms/python/blocks/gr_nlog10_ff.xml b/grc/data/platforms/python/blocks/gr_nlog10_ff.xml deleted file mode 100644 index 93507823..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_noise_source_x.xml b/grc/data/platforms/python/blocks/gr_noise_source_x.xml deleted file mode 100644 index 4fcef514..00000000 --- a/grc/data/platforms/python/blocks/gr_noise_source_x.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - Noise Source - gr_noise_source_x - from gnuradio import gr - gr.noise_source_$(type.fcn)($noise_type, $amp, $seed) - set_type($noise_type) - set_amplitude($amp) - - Output Type - type - enum - - - - - - - Noise Type - noise_type - gr.GR_GAUSSIAN - raw - - - - - - - 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 deleted file mode 100644 index 127a78a5..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_not_xx.xml b/grc/data/platforms/python/blocks/gr_not_xx.xml deleted file mode 100644 index 7af7e4b6..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_null_sink.xml b/grc/data/platforms/python/blocks/gr_null_sink.xml deleted file mode 100644 index ed106b49..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_null_source.xml b/grc/data/platforms/python/blocks/gr_null_source.xml deleted file mode 100644 index 6132eae3..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_or_xx.xml b/grc/data/platforms/python/blocks/gr_or_xx.xml deleted file mode 100644 index b374aa22..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_packed_to_unpacked_xx.xml b/grc/data/platforms/python/blocks/gr_packed_to_unpacked_xx.xml deleted file mode 100644 index 5fd9729a..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_peak_detector2_fb.xml b/grc/data/platforms/python/blocks/gr_peak_detector2_fb.xml deleted file mode 100644 index 128c6244..00000000 --- a/grc/data/platforms/python/blocks/gr_peak_detector2_fb.xml +++ /dev/null @@ -1,38 +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) - - 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 deleted file mode 100644 index 394b0697..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_phase_modulator_fc.xml b/grc/data/platforms/python/blocks/gr_phase_modulator_fc.xml deleted file mode 100644 index 758c5086..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_pll_carriertracking_cc.xml b/grc/data/platforms/python/blocks/gr_pll_carriertracking_cc.xml deleted file mode 100644 index 5b876b25..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_pll_freqdet_cf.xml b/grc/data/platforms/python/blocks/gr_pll_freqdet_cf.xml deleted file mode 100644 index 8ec1fb3b..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_pll_refout_cc.xml b/grc/data/platforms/python/blocks/gr_pll_refout_cc.xml deleted file mode 100644 index 64cf2bfb..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_pn_correlator_cc.xml b/grc/data/platforms/python/blocks/gr_pn_correlator_cc.xml deleted file mode 100644 index 094f46cd..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_probe_avg_mag_sqrd_x.xml b/grc/data/platforms/python/blocks/gr_probe_avg_mag_sqrd_x.xml deleted file mode 100644 index eb855956..00000000 --- a/grc/data/platforms/python/blocks/gr_probe_avg_mag_sqrd_x.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - Probe Avg Mag^2 - gr_probe_avg_mag_sqrd_x - from grc_gnuradio import blks2 as grc_blks2 - grc_blks2.probe_avg_mag_sqrd_$(type)( - threshold=$threshold, - alpha=$alpha, - probe_rate=$probe_rate, -) - set_alpha($alpha) - set_threshold($threshold) - set_probe_rate($probe_rate) - - Type - type - enum - - - - - Threshold (dB) - threshold - 0 - real - - - Alpha - alpha - 1 - real - - - Probe Rate - probe_rate - 10 - real - - - in - $type.input - - - out - float - - diff --git a/grc/data/platforms/python/blocks/gr_probe_density_b.xml b/grc/data/platforms/python/blocks/gr_probe_density_b.xml deleted file mode 100644 index 74d3b0a2..00000000 --- a/grc/data/platforms/python/blocks/gr_probe_density_b.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - Probe Density - gr_probe_density_b - from grc_gnuradio import blks2 as grc_blks2 - grc_blks2.probe_density_b( - alpha=$alpha, - probe_rate=$probe_rate, -) - set_alpha($alpha) - set_probe_rate($probe_rate) - - Alpha - alpha - 1 - real - - - Probe Rate - probe_rate - 10 - real - - - in - byte - - - out - float - - diff --git a/grc/data/platforms/python/blocks/gr_probe_mpsk_snr_c.xml b/grc/data/platforms/python/blocks/gr_probe_mpsk_snr_c.xml deleted file mode 100644 index 7f562d2f..00000000 --- a/grc/data/platforms/python/blocks/gr_probe_mpsk_snr_c.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - Probe MPSK SNR - gr_probe_mpsk_snr_c - from grc_gnuradio import blks2 as grc_blks2 - grc_blks2.probe_mpsk_snr_c( - type='$type', - alpha=$alpha, - probe_rate=$probe_rate, -) - set_alpha($alpha) - set_probe_rate($probe_rate) - - Type - type - enum - - - - - - Alpha - alpha - 1 - real - - - Probe Rate - probe_rate - 10 - real - - - in - complex - - - out - float - - diff --git a/grc/data/platforms/python/blocks/gr_pwr_squelch_xx.xml b/grc/data/platforms/python/blocks/gr_pwr_squelch_xx.xml deleted file mode 100644 index 08d62117..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_quadrature_demod_cf.xml b/grc/data/platforms/python/blocks/gr_quadrature_demod_cf.xml deleted file mode 100644 index a0e630c7..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_rational_resampler_base_xxx.xml b/grc/data/platforms/python/blocks/gr_rational_resampler_base_xxx.xml deleted file mode 100644 index 4b772017..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_repeat.xml b/grc/data/platforms/python/blocks/gr_repeat.xml deleted file mode 100644 index ba652a4d..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_rms_xx.xml b/grc/data/platforms/python/blocks/gr_rms_xx.xml deleted file mode 100644 index 1e094719..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_sample_and_hold_xx.xml b/grc/data/platforms/python/blocks/gr_sample_and_hold_xx.xml deleted file mode 100644 index bfe66bb0..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_scrambler_bb.xml b/grc/data/platforms/python/blocks/gr_scrambler_bb.xml deleted file mode 100644 index d079c401..00000000 --- a/grc/data/platforms/python/blocks/gr_scrambler_bb.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - Scrambler - gr_scrambler_bb - from gnuradio import gr - gr.scrambler_bb($mask, $seed, $len) - - Mask - mask - 0x8A - hex - - - Seed - seed - 0x7F - hex - - - Length - len - 7 - int - - - in - byte - - - out - byte - - diff --git a/grc/data/platforms/python/blocks/gr_short_to_float.xml b/grc/data/platforms/python/blocks/gr_short_to_float.xml deleted file mode 100644 index 8dac97c0..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_sig_source_x.xml b/grc/data/platforms/python/blocks/gr_sig_source_x.xml deleted file mode 100644 index c329dba6..00000000 --- a/grc/data/platforms/python/blocks/gr_sig_source_x.xml +++ /dev/null @@ -1,104 +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_waveform($waveform) - 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 - raw - - - - - - - - - Frequency - freq - 1000 - real - - - Amplitude - amp - 1 - real - - - Offset - offset - 0 - $type.offset_type - - - out - $type - - diff --git a/grc/data/platforms/python/blocks/gr_simple_correlator.xml b/grc/data/platforms/python/blocks/gr_simple_correlator.xml deleted file mode 100644 index 820523a6..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_simple_framer.xml b/grc/data/platforms/python/blocks/gr_simple_framer.xml deleted file mode 100644 index 2a0295c4..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_simple_squelch_cc.xml b/grc/data/platforms/python/blocks/gr_simple_squelch_cc.xml deleted file mode 100644 index 5c0727f5..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_single_pole_iir_filter_xx.xml b/grc/data/platforms/python/blocks/gr_single_pole_iir_filter_xx.xml deleted file mode 100644 index 50cf4a82..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_skiphead.xml b/grc/data/platforms/python/blocks/gr_skiphead.xml deleted file mode 100644 index 0849ad29..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_stream_to_streams.xml b/grc/data/platforms/python/blocks/gr_stream_to_streams.xml deleted file mode 100644 index 82542b8d..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_stream_to_vector.xml b/grc/data/platforms/python/blocks/gr_stream_to_vector.xml deleted file mode 100644 index 296d786f..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_streams_to_stream.xml b/grc/data/platforms/python/blocks/gr_streams_to_stream.xml deleted file mode 100644 index 7aadd7ee..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_streams_to_vector.xml b/grc/data/platforms/python/blocks/gr_streams_to_vector.xml deleted file mode 100644 index 4ecdcb2d..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_sub_xx.xml b/grc/data/platforms/python/blocks/gr_sub_xx.xml deleted file mode 100644 index f1f4797e..00000000 --- a/grc/data/platforms/python/blocks/gr_sub_xx.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - Subtract - gr_sub_xx - from gnuradio import gr - gr.sub_$(type.fcn)($vlen) - - IO Type - type - enum - - - - - - - Vec Length - vlen - 1 - int - - - Num Inputs - num_inputs - 2 - int - - $vlen > 0 - $num_inputs >= 2 - - in - $type - $vlen - $num_inputs - - - out - $type - $vlen - - diff --git a/grc/data/platforms/python/blocks/gr_threshold_ff.xml b/grc/data/platforms/python/blocks/gr_threshold_ff.xml deleted file mode 100644 index 740ce579..00000000 --- a/grc/data/platforms/python/blocks/gr_threshold_ff.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - Threshold - gr_threshold_ff - from gnuradio import gr - gr.threshold_ff($low, $high, $init) - set_hi($high) - set_lo($low) - - 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 deleted file mode 100644 index ab8506f5..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_uchar_to_float.xml b/grc/data/platforms/python/blocks/gr_uchar_to_float.xml deleted file mode 100644 index 0a5f7f96..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_udp_sink.xml b/grc/data/platforms/python/blocks/gr_udp_sink.xml deleted file mode 100644 index e9f6c2be..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_udp_source.xml b/grc/data/platforms/python/blocks/gr_udp_source.xml deleted file mode 100644 index f03adf80..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_unpack_k_bits_bb.xml b/grc/data/platforms/python/blocks/gr_unpack_k_bits_bb.xml deleted file mode 100644 index 9917644a..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_unpacked_to_packed_xx.xml b/grc/data/platforms/python/blocks/gr_unpacked_to_packed_xx.xml deleted file mode 100644 index f7457eb5..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_vco_f.xml b/grc/data/platforms/python/blocks/gr_vco_f.xml deleted file mode 100644 index e49c5396..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_vector_sink_x.xml b/grc/data/platforms/python/blocks/gr_vector_sink_x.xml deleted file mode 100644 index 3bd99869..00000000 --- a/grc/data/platforms/python/blocks/gr_vector_sink_x.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - Vector Sink - gr_vector_sink_x - from gnuradio import gr - gr.vector_sink_$(type.fcn)($vlen) - - Input Type - type - enum - - - - - - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - diff --git a/grc/data/platforms/python/blocks/gr_vector_source_x.xml b/grc/data/platforms/python/blocks/gr_vector_source_x.xml deleted file mode 100644 index 7a6a3aef..00000000 --- a/grc/data/platforms/python/blocks/gr_vector_source_x.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - Vector Source - gr_vector_source_x - from gnuradio import gr - gr.vector_source_$(type.fcn)($vector, $repeat, $vlen) - - Output Type - type - enum - - - - - - - - Vector - vector - 0, 0, 0 - $type.vec_type - - - Repeat - repeat - True - enum - - - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - out - $type - $vlen - - diff --git a/grc/data/platforms/python/blocks/gr_vector_to_stream.xml b/grc/data/platforms/python/blocks/gr_vector_to_stream.xml deleted file mode 100644 index d56d3406..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_vector_to_streams.xml b/grc/data/platforms/python/blocks/gr_vector_to_streams.xml deleted file mode 100644 index 86cb5681..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_wavfile_sink.xml b/grc/data/platforms/python/blocks/gr_wavfile_sink.xml deleted file mode 100644 index f2c8a009..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_wavfile_source.xml b/grc/data/platforms/python/blocks/gr_wavfile_source.xml deleted file mode 100644 index 433bb0af..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/gr_xor_xx.xml b/grc/data/platforms/python/blocks/gr_xor_xx.xml deleted file mode 100644 index c014cbe5..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/high_pass_filter.xml b/grc/data/platforms/python/blocks/high_pass_filter.xml deleted file mode 100644 index 0673fd12..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/import.xml b/grc/data/platforms/python/blocks/import.xml deleted file mode 100644 index feea052d..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/low_pass_filter.xml b/grc/data/platforms/python/blocks/low_pass_filter.xml deleted file mode 100644 index 1e8802c8..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/note.xml b/grc/data/platforms/python/blocks/note.xml deleted file mode 100644 index db6687c0..00000000 --- a/grc/data/platforms/python/blocks/note.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - Note - note - - - Note - note - - string - - diff --git a/grc/data/platforms/python/blocks/options.xml b/grc/data/platforms/python/blocks/options.xml deleted file mode 100644 index 82f30902..00000000 --- a/grc/data/platforms/python/blocks/options.xml +++ /dev/null @@ -1,116 +0,0 @@ - - - - Options - options - from gnuradio import gr -#if $generate_options() == 'wx_gui' -from grc_gnuradio import wxgui as grc_wxgui -import wx -#end if -#if $generate_options() != 'hb' -from optparse import OptionParser -from gnuradio.eng_option import eng_option -#end if - - - - Title - title - untitled - string - - - Author - author - unknown - string - - - Description - description - gnuradio flow graph - string - - - Window Size - window_size - 1280, 1024 - int_vector - part - - - Generate Options - generate_options - wx_gui - enum - - - - - - Category - category - Custom - string - #if $generate_options() == 'hb' then 'none' else 'all'# - - - Realtime Scheduling - realtime_scheduling - - enum - #if $generate_options() == 'hb' -all#slurp -#elif $realtime_scheduling() -none#slurp -#else -part#slurp -#end if - - - - len($window_size) == 2 - 300 <= $(window_size)[0] <= 4096 - 300 <= $(window_size)[1] <= 4096 - -The options block sets special parameters for the flow graph. \ -Only one option block is allowed per flow graph. - -Title, author, and description parameters are for identification purposes. - -The window size controls the dimensions of the flow graph editor. \ -The window size (width, height) must be between (300, 300) and (4096, 4096). - -The generate options controls the type of code generated. \ -Non-graphical flow graphs should avoid using graphical sinks or graphical variable controls. - -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 deleted file mode 100644 index 477f2ad1..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/pad_source.xml b/grc/data/platforms/python/blocks/pad_source.xml deleted file mode 100644 index b6ef2c55..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/parameter.xml b/grc/data/platforms/python/blocks/parameter.xml deleted file mode 100644 index e7bf6156..00000000 --- a/grc/data/platforms/python/blocks/parameter.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - Parameter - parameter - $value - - Label - label - - string - #if $label() then 'none' else 'part'# - - - Value - value - 0 - $type.type - - - Type - type - - enum - $type.hide - - - - - - - - -This block represents a parameter to the flow graph. \ -A parameter can be used to pass command line arguments into a top block. \ -Or, parameters can pass arguments into an instantiated hierarchical block. - -The paramater value cannot depend on any variables. - -Leave the label blank to use the parameter id as the label. \ -The label only applies when this flow graph is instantiated as a hierarchical block. - -When type is not None, this parameter also becomes a command line option of the form --[id] [value]. - - diff --git a/grc/data/platforms/python/blocks/probe_function.xml b/grc/data/platforms/python/blocks/probe_function.xml deleted file mode 100644 index ac0b3dcd..00000000 --- a/grc/data/platforms/python/blocks/probe_function.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - Probe Function - probe_function - from grc_gnuradio import blks2 as grc_blks2 - grc_blks2.probe_function( - probe_callback=self.$(block_id()).$(function_name()), - probe_rate=$probe_rate, -) - set_probe_rate($probe_rate) - - Block ID - block_id - my_block_0 - string - - - Function Name - function_name - get_number - string - - - Probe Rate - probe_rate - 10 - real - - - out - float - - -Polls a function of an arbitrary block and writes the value to the output port. \ -The block id is the id of another block in the flow graph. \ -The function name is the name of a function in the said block. \ -The function should take no arguments and return a floating point or integer number. - - diff --git a/grc/data/platforms/python/blocks/random_source_x.xml b/grc/data/platforms/python/blocks/random_source_x.xml deleted file mode 100644 index 800bae71..00000000 --- a/grc/data/platforms/python/blocks/random_source_x.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - Random Source - random_source_x - from gnuradio import gr - import numpy - gr.vector_source_$(type.fcn)(map(int, numpy.random.randint($min, $max, $num_samps)), $repeat) - - Output Type - type - enum - - - - - - Minimum - min - 0 - int - - - Maximum - max - 2 - 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. - -Ex: With min=0 and max=2, the sequence 01110101... will be generated. - - diff --git a/grc/data/platforms/python/blocks/trellis_encoder_xx.xml b/grc/data/platforms/python/blocks/trellis_encoder_xx.xml deleted file mode 100644 index 74a8cc34..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/trellis_metrics_x.xml b/grc/data/platforms/python/blocks/trellis_metrics_x.xml deleted file mode 100644 index 2016a34c..00000000 --- a/grc/data/platforms/python/blocks/trellis_metrics_x.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - Trellis Metrics - trellis_metrics_x - from gnuradio import trellis - trellis.metrics_$(type)($card, $dim, $table, $metric_type) - set_TABLE($table) - - Type - type - enum - - - - - - - Output Cardinality - card - int - - - Dimensionality - dim - int - - - Constellation - table - $type.table - - - Metric Type - metric_type - enum - - - - - - in - $type.io - - - out - float - - -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 deleted file mode 100644 index 7721cc71..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/trellis_siso_combined_f.xml b/grc/data/platforms/python/blocks/trellis_siso_combined_f.xml deleted file mode 100644 index 98874d7f..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/trellis_siso_f.xml b/grc/data/platforms/python/blocks/trellis_siso_f.xml deleted file mode 100644 index 2b9cfe5f..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/trellis_viterbi_combined_xx.xml b/grc/data/platforms/python/blocks/trellis_viterbi_combined_xx.xml deleted file mode 100644 index 33dcaaf7..00000000 --- a/grc/data/platforms/python/blocks/trellis_viterbi_combined_xx.xml +++ /dev/null @@ -1,123 +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) - set_TABLE($table) - - 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 deleted file mode 100644 index 84b39677..00000000 --- a/grc/data/platforms/python/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 - float - - - out - $type.io - - -Viterbi Decoder. \ -The fsm arguments are passed directly to the trellis.fsm() constructor. - - diff --git a/grc/data/platforms/python/blocks/usrp2_probe.xml b/grc/data/platforms/python/blocks/usrp2_probe.xml deleted file mode 100644 index cc3f9c2f..00000000 --- a/grc/data/platforms/python/blocks/usrp2_probe.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - USRP2 Probe - usrp2_probe - - - Interface - interface - - string - - - Type - type - rx - enum - - - - Press "Probe" to retrieve USRP2 information... - diff --git a/grc/data/platforms/python/blocks/usrp2_sink_xxxx.xml b/grc/data/platforms/python/blocks/usrp2_sink_xxxx.xml deleted file mode 100644 index 639f96cf..00000000 --- a/grc/data/platforms/python/blocks/usrp2_sink_xxxx.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - USRP2 Sink - usrp2_sink_xxxx - from gnuradio import usrp2 - #if not $interface() and not $mac_addr() -usrp2.sink_$(type.fcn)() -#elif not $mac_addr() -usrp2.sink_$(type.fcn)($interface) -#else -usrp2.sink_$(type.fcn)($interface, $mac_addr) -#end if -self.$(id).set_interp($interpolation) -self.$(id).set_center_freq($frequency) -self.$(id).set_gain($gain) -#if $lo_offset() != float('inf') -self.$(id).set_lo_offset($lo_offset) -#end if - set_lo_offset($lo_offset) - set_interp($interpolation) - set_center_freq($frequency) - set_gain($gain) - - Output Type - type - enum - - - - - Interface - interface - - string - - - MAC Addr - mac_addr - - string - - - Interpolation - interpolation - int - - - Frequency (Hz) - frequency - real - - - LO Offset (Hz) - lo_offset - float('inf') - real - #if $lo_offset() == float('inf') then 'part' else 'none'# - - - - Gain (dB) - gain - 0 - real - - - in - $type - - -The USRP2 sink inputs 100 Megasamples per second / interpolation. - -Input amplitude should be between 0.0 and 1.0. - -To use the default ethernet device, leave interface blank. \ -For systems with only 1 USRP2, you may leave the mac address blank. \ -For multi-USRP2 systems, specify the mac address in the form 00:50:C2:85:3x:xx. - - diff --git a/grc/data/platforms/python/blocks/usrp2_source_xxxx.xml b/grc/data/platforms/python/blocks/usrp2_source_xxxx.xml deleted file mode 100644 index 6c776d0a..00000000 --- a/grc/data/platforms/python/blocks/usrp2_source_xxxx.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - USRP2 Source - usrp2_source_xxxx - from gnuradio import usrp2 - #if not $interface() and not $mac_addr() -usrp2.source_$(type.fcn)() -#elif not $mac_addr() -usrp2.source_$(type.fcn)($interface) -#else -usrp2.source_$(type.fcn)($interface, $mac_addr) -#end if -self.$(id).set_decim($decimation) -self.$(id).set_center_freq($frequency) -self.$(id).set_gain($gain) -#if $lo_offset() != float('inf') -self.$(id).set_lo_offset($lo_offset) -#end if - set_lo_offset($lo_offset) - set_decim($decimation) - set_center_freq($frequency) - set_gain($gain) - - Output Type - type - enum - - - - - Interface - interface - - string - - - MAC Addr - mac_addr - - string - - - Decimation - decimation - int - - - Frequency (Hz) - frequency - real - - - LO Offset (Hz) - lo_offset - float('inf') - real - #if $lo_offset() == float('inf') then 'part' else 'none'# - - - - Gain (dB) - gain - 0 - real - - - out - $type - - -The USRP2 source outputs 100 Megasamples per second / decimation. - -To use the default ethernet device, leave interface blank. \ -For systems with only 1 USRP2, you may leave the mac address blank. \ -For multi-USRP2 systems, specify the mac address in the form 00:50:C2:85:3x:xx. - - diff --git a/grc/data/platforms/python/blocks/usrp_dual_sink_x.xml b/grc/data/platforms/python/blocks/usrp_dual_sink_x.xml deleted file mode 100644 index 8f418bec..00000000 --- a/grc/data/platforms/python/blocks/usrp_dual_sink_x.xml +++ /dev/null @@ -1,193 +0,0 @@ - - - - USRP Dual Sink - usrp_dual_sink_x - from grc_gnuradio import usrp as grc_usrp - grc_usrp.dual_sink_$(type.fcn)(which=$which) -self.$(id).set_interp_rate($interpolation) -self.$(id).set_frequency_a($frequency_a, verbose=True) -self.$(id).set_frequency_b($frequency_b, verbose=True) -self.$(id).set_gain_a($gain_a) -self.$(id).set_gain_b($gain_b) -#if $lo_offset_a() != float('inf') -self.$(id).set_lo_offset_a($lo_offset_a) -#end if -#if $lo_offset_b() != float('inf') -self.$(id).set_lo_offset_b($lo_offset_b) -#end if -################################################## -## Flex RF A -################################################## -#if $transmit_a.tx_enb -self.$(id).set_enable_a(True) -#end if -#if $transmit_a.auto_tr -self.$(id).set_auto_tr_a(True) -#end if -################################################## -## Flex RF B -################################################## -#if $transmit_b.tx_enb -self.$(id).set_enable_b(True) -#end if -#if $transmit_b.auto_tr -self.$(id).set_auto_tr_b(True) -#end if - set_interp_rate($interpolation) - set_frequency_a($frequency_a) - set_frequency_b($frequency_b) - set_gain_a($gain_a) - set_gain_b($gain_b) - - Input Type - type - enum - - - - - Unit Number - which - 0 - int - - - Interpolation - interpolation - int - - - Frequency A (Hz) - frequency_a - real - - - Frequency B (Hz) - frequency_b - real - - - LO Offset A (Hz) - lo_offset_a - float('inf') - real - #if $lo_offset_a() == float('inf') then 'part' else 'none'# - - - - LO Offset B (Hz) - lo_offset_b - float('inf') - real - #if $lo_offset_b() == float('inf') then 'part' else 'none'# - - - - Gain A (dB) - gain_a - 0 - real - - - Gain B (dB) - gain_b - 0 - real - - - - Transmit A - transmit_a - - enum - #if $transmit_a.tx_enb then 'none' else 'part'# - - - - - - - Transmit B - transmit_b - - enum - #if $transmit_b.tx_enb then 'none' else 'part'# - - - - - - Ain - $type - - - Bin - $type - - -The USRP sink inputs 128 Megasamples per second / interpolation. - -Input amplitude should be between 0 and 32767. - -Flex RF boards only: The "Transmit Setting" must be configured. \ -When set to "Enable" the transmitter is always on. \ -When set to "Auto Transmit/Receive", the transmitter is disabled while receiving. - - diff --git a/grc/data/platforms/python/blocks/usrp_dual_source_x.xml b/grc/data/platforms/python/blocks/usrp_dual_source_x.xml deleted file mode 100644 index 740895d4..00000000 --- a/grc/data/platforms/python/blocks/usrp_dual_source_x.xml +++ /dev/null @@ -1,198 +0,0 @@ - - - - USRP Dual Source - usrp_dual_source_x - from grc_gnuradio import usrp as grc_usrp - grc_usrp.dual_source_$(type.fcn)(which=$which, rx_ant_a=$rx_ant_a, rx_ant_b=$rx_ant_b) -#if $format() -self.$(id).set_format(width=$format.width, shift=$format.shift) -#end if -self.$(id).set_decim_rate($decimation) -self.$(id).set_frequency_a($frequency_a, verbose=True) -self.$(id).set_frequency_b($frequency_b, verbose=True) -self.$(id).set_gain_a($gain_a) -self.$(id).set_gain_b($gain_b) -#if $lo_offset_a() != float('inf') -self.$(id).set_lo_offset_a($lo_offset_a) -#end if -#if $lo_offset_b() != float('inf') -self.$(id).set_lo_offset_b($lo_offset_b) -#end if - set_decim_rate($decimation) - set_frequency_a($frequency_a) - set_frequency_b($frequency_b) - set_gain_a($gain_a) - set_gain_b($gain_b) - - Output Type - type - enum - - - - - Format - format - - enum - #if $format() then '' else 'part'# - - - - - Unit Number - which - 0 - int - - - Decimation - decimation - int - - - Frequency A (Hz) - frequency_a - real - - - Frequency B (Hz) - frequency_b - real - - - LO Offset A (Hz) - lo_offset_a - float('inf') - real - #if $lo_offset_a() == float('inf') then 'part' else 'none'# - - - - LO Offset B (Hz) - lo_offset_b - float('inf') - real - #if $lo_offset_b() == float('inf') then 'part' else 'none'# - - - - Gain A (dB) - gain_a - 0 - real - - - Gain B (dB) - gain_b - 0 - real - - - - RX Antenna A - rx_ant_a - RXA - string - - - - - - - - - RX Antenna B - rx_ant_b - RXA - string - - - - - - - - Aout - $type - - - Bout - $type - - -The USRP source outputs 64 Megasamples per second / decimation. - -The "Receive Antenna Setting" selects one of the SMA connectors as the data source. \ -Flex RF boards use the "TX/RX" and "RX2" settings. \ -Basic RX and LFRX use the "RXA", "RXB", and "RXAB" settings. \ -All other boards use the "RXA" setting. - - diff --git a/grc/data/platforms/python/blocks/usrp_probe.xml b/grc/data/platforms/python/blocks/usrp_probe.xml deleted file mode 100644 index ee207c28..00000000 --- a/grc/data/platforms/python/blocks/usrp_probe.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - USRP Probe - usrp_probe - - - Unit Number - which - 0 - int - - - Daughter Board - dboard - enum - - - - - - Press "Probe" to retrieve USRP information... - diff --git a/grc/data/platforms/python/blocks/usrp_simple_sink_x.xml b/grc/data/platforms/python/blocks/usrp_simple_sink_x.xml deleted file mode 100644 index f3ccf126..00000000 --- a/grc/data/platforms/python/blocks/usrp_simple_sink_x.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - - USRP Sink - usrp_simple_sink_x - from grc_gnuradio import usrp as grc_usrp - grc_usrp.simple_sink_$(type.fcn)(which=$which, side=$side) -self.$(id).set_interp_rate($interpolation) -self.$(id).set_frequency($frequency, verbose=True) -self.$(id).set_gain($gain) -#if $transmit.tx_enb -self.$(id).set_enable(True) -#end if -#if $transmit.auto_tr -self.$(id).set_auto_tr(True) -#end if -#if $lo_offset() != float('inf') -self.$(id).set_lo_offset($lo_offset) -#end if - set_lo_offset($lo_offset) - set_interp_rate($interpolation) - set_frequency($frequency) - set_gain($gain) - - Input Type - type - enum - - - - - Unit Number - which - 0 - int - - - Interpolation - interpolation - int - - - Frequency (Hz) - frequency - real - - - LO Offset (Hz) - lo_offset - float('inf') - real - #if $lo_offset() == float('inf') then 'part' else 'none'# - - - - Gain (dB) - gain - 0 - real - - - Side - side - A - string - - - - - Transmit - transmit - - enum - #if $transmit.tx_enb then 'none' else 'part'# - - - - - - in - $type - - -The USRP sink inputs 128 Megasamples per second / interpolation. - -Input amplitude should be between 0 and 32767. - -Flex RF boards only: The "Transmit Setting" must be configured. \ -When set to "Enable" the transmitter is always on. \ -When set to "Auto Transmit/Receive", the transmitter is disabled while receiving. - - diff --git a/grc/data/platforms/python/blocks/usrp_simple_source_x.xml b/grc/data/platforms/python/blocks/usrp_simple_source_x.xml deleted file mode 100644 index 1a777bd6..00000000 --- a/grc/data/platforms/python/blocks/usrp_simple_source_x.xml +++ /dev/null @@ -1,163 +0,0 @@ - - - - USRP Source - usrp_simple_source_x - from grc_gnuradio import usrp as grc_usrp - grc_usrp.simple_source_$(type.fcn)(which=$which, side=$side, rx_ant=$rx_ant#if $hb_filters() then ', no_hb=True' else ''#) -#if $format() -self.$(id).set_format(width=$format.width, shift=$format.shift) -#end if -self.$(id).set_decim_rate($decimation) -self.$(id).set_frequency($frequency, verbose=True) -self.$(id).set_gain($gain) -#if $lo_offset() != float('inf') -self.$(id).set_lo_offset($lo_offset) -#end if - set_lo_offset($lo_offset) - set_decim_rate($decimation) - set_frequency($frequency) - set_gain($gain) - - Output Type - type - enum - - - - - Format - format - - enum - #if $format() then '' else 'part'# - - - - - Unit Number - which - 0 - int - - - Decimation - decimation - int - - - Frequency (Hz) - frequency - real - - - LO Offset (Hz) - lo_offset - float('inf') - real - #if $lo_offset() == float('inf') then 'part' else 'none'# - - - - Gain (dB) - gain - 0 - real - - - Side - side - A - string - - - - - RX Antenna - rx_ant - RXA - string - - - - - - - - Halfband Filters - hb_filters - - enum - #if $hb_filters() then 'none' else 'part'# - - - - - out - $type - - -The USRP source outputs 64 Megasamples per second / decimation. - -The "Receive Antenna Setting" selects one of the SMA connectors as the data source. \ -Flex RF boards use the "TX/RX" and "RX2" settings. \ -Basic RX and LFRX use the "RXA", "RXB", and "RXAB" settings. \ -All other boards use the "RXA" setting. - -With the format set to 8 bits and the halfband filters disabled, the USRP can acheive a decimation rate of 4. \ -Disabling the halfband filters requires a special USRP firmware without halfband filters or TX paths. \ -For this reason, the USRP cannot transmit with the halfband filters disabled. - - diff --git a/grc/data/platforms/python/blocks/variable.xml b/grc/data/platforms/python/blocks/variable.xml deleted file mode 100644 index d620e160..00000000 --- a/grc/data/platforms/python/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/platforms/python/blocks/variable_chooser.xml b/grc/data/platforms/python/blocks/variable_chooser.xml deleted file mode 100644 index 3ca33045..00000000 --- a/grc/data/platforms/python/blocks/variable_chooser.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - Variable Chooser - variable_chooser - from gnuradio.wxgui import forms - $value -self['$id'] = $id -self.subscribe('$id', self.set_$(id)) -self._$(id)_control = forms.$(type)( - parent=self.GetWin(), - ps=self, - key='$id', - #if $label() - label=$label, - #else - label='$id', - #end if - choices=$choices, - labels=$labels, -#if $type() == 'radio_buttons' - style=$style, -#end if -) -#set $grid_pos = $grid_pos() -#if not grid_pos -self.Add(self._$(id)_control) -#else -self.GridAdd(self._$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) -#end if - - Label - label - - string - #if $label() then 'none' else 'part'# - - - Default Value - value - 1 - raw - - - Choices - choices - [1, 2, 3] - raw - - - Labels - labels - [] - raw - - - Type - type - drop_down - enum - - - - - - Style - style - wx.RA_HORIZONTAL - enum - #if $type() == 'radio_buttons' then 'part' else 'all'# - - - - - Grid Position - grid_pos - - grid_pos - - $value in $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_slider.xml b/grc/data/platforms/python/blocks/variable_slider.xml deleted file mode 100644 index f8a5543f..00000000 --- a/grc/data/platforms/python/blocks/variable_slider.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - - Variable Slider - variable_slider - from gnuradio.wxgui import forms - $value -self['$id'] = $id -self.subscribe('$id', self.set_$(id)) -self._$(id)_sizer = wx.BoxSizer(wx.VERTICAL) -forms.text_box( - parent=self.GetWin(), - sizer=self._$(id)_sizer, - ps=self, - key='$id', - #if $label() - label=$label, - #else - label='$id', - #end if - converter=forms.$(converver)(), - proportion=0, -) -forms.slider( - parent=self.GetWin(), - sizer=self._$(id)_sizer, - ps=self, - key='$id', - minimum=$min, - maximum=$max, - num_steps=$num_steps, - style=$style, - cast=$(converver.slider_cast), - proportion=1, -) -#set $grid_pos = $grid_pos() -#if not grid_pos -self.Add(self._$(id)_sizer) -#else -self.GridAdd(self._$(id)_sizer, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) -#end if - - Label - label - - string - #if $label() then 'none' else 'part'# - - - Default Value - value - 50 - real - - - Minimum - min - 0 - real - - - Maximum - max - 100 - real - - - Num Steps - num_steps - 100 - int - part - - - Style - style - wx.SL_HORIZONTAL - enum - part - - - - - Converter - converver - float_converter - 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 deleted file mode 100644 index b5acd9d2..00000000 --- a/grc/data/platforms/python/blocks/variable_text_box.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - Variable Text Box - variable_text_box - from gnuradio.wxgui import forms - $value -self['$id'] = $id -self.subscribe('$id', self.set_$(id)) -self._$(id)_control = forms.text_box( - parent=self.GetWin(), - ps=self, - key='$id', - #if $label() - label=$label, - #else - label='$id', - #end if - converter=forms.$(converver)(), -) -#set $grid_pos = $grid_pos() -#if not grid_pos -self.Add(self._$(id)_control) -#else -self.GridAdd(self._$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) -#end if - - Label - label - - string - #if $label() then 'none' else 'part'# - - - Default Value - value - 0 - raw - - - Converter - converver - float_converter - enum - - - - - - - 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 deleted file mode 100644 index 471c9f4a..00000000 --- a/grc/data/platforms/python/blocks/wxgui_constellationsink2.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - Constellation Sink - wxgui_constellationsink2 - from gnuradio.wxgui import constsink_gl - constsink_gl.const_sink_c( - self.GetWin(), - title=$title, - sample_rate=$samp_rate, - frame_rate=$frame_rate, - const_size=$const_size, - M=$M, - theta=$theta, - alpha=$alpha, - fmax=$fmax, - mu=$mu, - gain_mu=$gain_mu, - symbol_rate=$symbol_rate, - omega_limit=$omega_limit, -) -#set $grid_pos = $grid_pos() -#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 Rate - frame_rate - 5 - real - - - Constellation Size - const_size - 2048 - real - - - M - M - 4 - int - - - Theta - theta - 0 - real - - - Alpha - alpha - 0.005 - real - - - Max Freq - fmax - 0.06 - real - - - Mu - mu - 0.5 - real - - - Gain Mu - gain_mu - 0.005 - real - - - Symbol Rate - symbol_rate - samp_rate/4. - real - - - Omega Limit - omega_limit - 0.005 - real - - - 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 deleted file mode 100644 index d7763cb2..00000000 --- a/grc/data/platforms/python/blocks/wxgui_fftsink2.xml +++ /dev/null @@ -1,169 +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, - avg_alpha=#if $avg_alpha() then $avg_alpha else 'None'#, - title=$title, - peak_hold=$peak_hold, -) -#set $grid_pos = $grid_pos() -#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_baseband_freq($baseband_freq) - set_sample_rate($samp_rate) - - 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 - enum - - - - - - - - Y Divs - y_divs - 10 - int - - - Ref Level (dB) - ref_level - 50 - real - - - FFT Size - fft_size - 1024 - int - - - Refresh Rate - fft_rate - 30 - int - - - Peak Hold - peak_hold - False - enum - #if $peak_hold() == 'True' then 'none' else 'part'# - - - - - Average - average - False - enum - #if $average() == 'True' then 'none' else 'part'# - - - - - Average Alpha - avg_alpha - 0 - real - #if $average() == 'True' then 'none' else 'all'# - - - 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_histosink2.xml b/grc/data/platforms/python/blocks/wxgui_histosink2.xml deleted file mode 100644 index 4de57b1c..00000000 --- a/grc/data/platforms/python/blocks/wxgui_histosink2.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - Histo Sink - wxgui_histosink2 - from gnuradio.wxgui import histosink_gl - histosink_gl.histo_sink_f( - self.GetWin(), - title=$title, - num_bins=$num_bins, - frame_size=$frame_size, -) -#set $grid_pos = $grid_pos() -#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_num_bins($num_bins) - set_frame_size($frame_size) - - Title - title - Histogram Plot - string - - - Num Bins - num_bins - 27 - int - - - Frame Size - frame_size - 1000 - int - - - Grid Position - grid_pos - - grid_pos - - - in - float - - -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 deleted file mode 100644 index 7cc90b69..00000000 --- a/grc/data/platforms/python/blocks/wxgui_numbersink2.xml +++ /dev/null @@ -1,171 +0,0 @@ - - - - Number Sink - wxgui_numbersink2 - from gnuradio.wxgui import numbersink2 - numbersink2.$(type.fcn)( - self.GetWin(), - unit=$units, - 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=$average, - avg_alpha=#if $avg_alpha() then $avg_alpha else 'None'#, - label=$title, - peak_hold=$peak_hold, - show_gauge=$show_gauge, -) -#set $grid_pos = $grid_pos() -#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 - - - 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 - 0 - real - - - Number Rate - number_rate - 15 - int - - - Peak Hold - peak_hold - False - enum - #if $peak_hold() == 'True' then 'none' else 'part'# - - - - - Average - average - False - enum - #if $average() == 'True' then 'none' else 'part'# - - - - - Average Alpha - avg_alpha - 0 - real - #if $average() == 'True' then 'none' else 'all'# - - - 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. - -Incoming numbers are multiplied by the factor, and then added-to by the reference level. - - diff --git a/grc/data/platforms/python/blocks/wxgui_scopesink2.xml b/grc/data/platforms/python/blocks/wxgui_scopesink2.xml deleted file mode 100644 index 78c39f80..00000000 --- a/grc/data/platforms/python/blocks/wxgui_scopesink2.xml +++ /dev/null @@ -1,126 +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, - v_scale=$v_scale, - t_scale=$t_scale, - ac_couple=$ac_couple, - xy_mode=$xy_mode, - num_inputs=$num_inputs, -) -#set $grid_pos = $grid_pos() -#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 - - - V Scale - v_scale - 0 - real - - - T Scale - t_scale - 0 - real - - - AC Couple - ac_couple - False - enum - #if $ac_couple() == 'True' then 'none' else 'part'# - - - - - XY Mode - xy_mode - False - enum - #if $xy_mode() == 'True' then 'none' else 'part'# - - - - - Num Inputs - num_inputs - 1 - int - - - Grid Position - grid_pos - - grid_pos - - not $xy_mode or '$type' == 'complex' or $num_inputs != 1 - - in - $type - $num_inputs - - -Set the V Scale to 0 for the scope to auto-scale. - -Set the T Scale to 0 for automatic setting. - -XY Mode allows the scope to initialize as an XY plotter. - -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 deleted file mode 100644 index 6d76ee86..00000000 --- a/grc/data/platforms/python/blocks/wxgui_waterfallsink2.xml +++ /dev/null @@ -1,126 +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, - avg_alpha=#if $avg_alpha() then $avg_alpha else 'None'#, - title=$title, -) -#set $grid_pos = $grid_pos() -#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_baseband_freq($baseband_freq) - set_sample_rate($samp_rate) - - 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 deleted file mode 100644 index dc4d154d..00000000 --- a/grc/data/platforms/python/blocks/xmlrpc_client.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - XMLRPC Client - xmlrpc_client - import xmlrpclib - xmlrpclib.Server('http://$(addr()):$(port)') - $(callback())($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 deleted file mode 100644 index 6c31bd1a..00000000 --- a/grc/data/platforms/python/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/platforms/python/default_flow_graph.grc b/grc/data/platforms/python/default_flow_graph.grc deleted file mode 100644 index dea26f3a..00000000 --- a/grc/data/platforms/python/default_flow_graph.grc +++ /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/platforms/python/flow_graph.tmpl b/grc/data/platforms/python/flow_graph.tmpl deleted file mode 100644 index 4c481dce..00000000 --- a/grc/data/platforms/python/flow_graph.tmpl +++ /dev/null @@ -1,207 +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: $flow_graph.get_option('title') -# Author: $flow_graph.get_option('author') -# Description: $flow_graph.get_option('description') -# Generated: $time.ctime() -$DIVIDER - -######################################################## -##Create Imports -######################################################## -#for $imp in $imports -$imp -#end for - -######################################################## -##Create Class -## Write the class declaration for a top or hier block. -## The parameter names are the arguments to __init__. -## Determine the absolute icon path (wx gui only). -## Setup the IO signature (hier block only). -######################################################## -#set $class_name = $flow_graph.get_option('id') -#if $generate_options == 'wx_gui' - #import gtk - #set $icon = gtk.IconTheme().lookup_icon('gnuradio-grc', 32, 0) -class $(class_name)(grc_wxgui.top_block_gui): - - def __init__(self, options): - grc_wxgui.top_block_gui.__init__( - self, - title="$flow_graph.get_parent().get_name() - Executing: $flow_graph.get_option('title')", - #if $icon - icon="$icon.get_filename()", - #end if - ) -#elif $generate_options == 'no_gui' -class $(class_name)(gr.top_block): - - def __init__(self, options): - 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() - #set $param_str = ', '.join(['self'] + ['%s=%s'%(param.get_id(), param.get_make()) for param in $parameters]) -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 - #if $generate_options != 'hb' - self.$param.get_id() = $param.get_id() = options.$param.get_id() - #else - self.$param.get_id() = $param.get_id() - #end if -#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.$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(($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__': - parser = OptionParser(option_class=eng_option, usage="%prog: [options]") - #for $param in $parameters - #set $type = $param.get_param('type').get_value() - #if $type - parser.add_option("--$param.get_id()", dest="$param.get_id()", type="$type", default=$param.get_make()) - #end if - #end for - (options, args) = parser.parse_args() - #if $flow_graph.get_option('realtime_scheduling') - if gr.enable_realtime_scheduling() != gr.RT_OK: - print "Error: failed to enable realtime scheduling." - #end if - tb = $(class_name)(options) - #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/grc.conf.in b/grc/grc.conf.in new file mode 100644 index 00000000..37a04997 --- /dev/null +++ b/grc/grc.conf.in @@ -0,0 +1,9 @@ +# This file contains system wide configuration data for GNU Radio. +# You may override any setting on a per-user basis by editing +# ~/.gnuradio/config.conf + +[grc] +pythonw = @pythonw@ +doc_dir = @docdir@ +global_blocks_path = @blocksdir@ +local_blocks_path = diff --git a/grc/grc_gnuradio/Makefile.am b/grc/grc_gnuradio/Makefile.am new file mode 100644 index 00000000..9a15eb0e --- /dev/null +++ b/grc/grc_gnuradio/Makefile.am @@ -0,0 +1,49 @@ +# +# 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 + +grc_gnuradio_prefix = $(pythondir)/grc_gnuradio + +rootpythondir = $(grc_gnuradio_prefix) +rootpython_PYTHON = __init__.py + +blks2pythondir = $(grc_gnuradio_prefix)/blks2 +blks2python_PYTHON = \ + blks2/__init__.py \ + blks2/error_rate.py \ + blks2/packet.py \ + blks2/probe.py \ + blks2/selector.py \ + blks2/tcp.py \ + blks2/variable_sink.py + +usrppythondir = $(grc_gnuradio_prefix)/usrp +usrppython_PYTHON = \ + usrp/__init__.py \ + usrp/common.py \ + usrp/dual_usrp.py \ + usrp/simple_usrp.py + +wxguipythondir = $(grc_gnuradio_prefix)/wxgui +wxguipython_PYTHON = \ + wxgui/__init__.py \ + wxgui/top_block_gui.py diff --git a/grc/grc_gnuradio/README b/grc/grc_gnuradio/README new file mode 100644 index 00000000..5a89da54 --- /dev/null +++ b/grc/grc_gnuradio/README @@ -0,0 +1,14 @@ +This is the grc_gnuradio module. +It contains supplemental python modules that grc uses at runtime. +The supplemental modules are meant to mimic modules in gnuradio. +These will be phased-out as new functionaility is merged into gnuradio. + +The blk2s module wraps many blocks in blks2 and gives them streaming outputs. +Will be phased-out by new message passing implementations. +Other blks2 blocks will hopefully make their way into blks2impl. + +The usrp module contains the simple and dual usrp wrappers. +Will be phased-out by generic usrp and/or new usrp api. + +The wxgui module contains a top_block + wxgui frame. +Will be phased-out by gui.py in wxgui and a new top block template. diff --git a/grc/grc_gnuradio/__init__.py b/grc/grc_gnuradio/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/grc/grc_gnuradio/__init__.py @@ -0,0 +1 @@ + diff --git a/grc/grc_gnuradio/blks2/__init__.py b/grc/grc_gnuradio/blks2/__init__.py new file mode 100644 index 00000000..cb1196f2 --- /dev/null +++ b/grc/grc_gnuradio/blks2/__init__.py @@ -0,0 +1,28 @@ +# Copyright 2008, 2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from selector import selector, valve +from packet import options, packet_encoder, packet_decoder, \ + packet_mod_b, packet_mod_s, packet_mod_i, packet_mod_f, packet_mod_c, \ + packet_demod_b, packet_demod_s, packet_demod_i, packet_demod_f, packet_demod_c +from error_rate import error_rate +from probe import probe_function, probe_avg_mag_sqrd_c, probe_avg_mag_sqrd_f, probe_density_b, probe_mpsk_snr_c +from variable_sink import variable_sink_b, variable_sink_s, variable_sink_i, variable_sink_f, variable_sink_c +from tcp import tcp_source, tcp_sink diff --git a/grc/grc_gnuradio/blks2/error_rate.py b/grc/grc_gnuradio/blks2/error_rate.py new file mode 100644 index 00000000..9b2df58e --- /dev/null +++ b/grc/grc_gnuradio/blks2/error_rate.py @@ -0,0 +1,137 @@ +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +default_win_size = 1000 + +from gnuradio import gr +import gnuradio.gr.gr_threading as _threading +import numpy + +#generate 1s counts array +_1s_counts = [sum([1&(i>>j) for j in range(8)]) for i in range(2**8)] + +class input_watcher(_threading.Thread): + """ + Read samples from the message queue and hand them to the callback. + """ + + def __init__(self, msgq, callback): + self._msgq = msgq + self._callback = callback + _threading.Thread.__init__(self) + self.setDaemon(1) + self.keep_running = True + self.start() + + def run(self): + r = '' + while True: + msg = self._msgq.delete_head() + itemsize = int(msg.arg1()) + nitems = int(msg.arg2()) + s = r + msg.to_string() + i = (nitems-nitems%2)*itemsize + r = s[i:] + s = s[:i] + samples = numpy.fromstring(s, numpy.int8) + self._callback(samples) + +class error_rate(gr.hier_block2): + """ + Sample the incoming data streams (byte) and calculate the bit or symbol error rate. + Write the running rate to the output data stream (float). + """ + + def __init__(self, type='BER', win_size=default_win_size, bits_per_symbol=2): + """ + Error rate constructor. + @param type a string 'BER' or 'SER' + @param win_size the number of samples to calculate over + @param bits_per_symbol the number of information bits per symbol (BER only) + """ + #init + gr.hier_block2.__init__( + self, 'error_rate', + gr.io_signature(2, 2, gr.sizeof_char), + gr.io_signature(1, 1, gr.sizeof_float), + ) + assert type in ('BER', 'SER') + self._max_samples = win_size + self._bits_per_symbol = bits_per_symbol + #setup message queue + msg_source = gr.message_source(gr.sizeof_float, 1) + self._msgq_source = msg_source.msgq() + msgq_sink = gr.msg_queue(2) + msg_sink = gr.message_sink(gr.sizeof_char, msgq_sink, False) #False -> blocking + inter = gr.interleave(gr.sizeof_char) + #start thread + self._num_errs = 0 + self._err_index = 0 + self._num_samps = 0 + self._err_array = numpy.zeros(self._max_samples, numpy.int8) + if type == 'BER': + input_watcher(msgq_sink, self._handler_ber) + elif type == 'SER': + input_watcher(msgq_sink, self._handler_ser) + #connect + self.connect(msg_source, self) + self.connect((self, 0), (inter, 0)) + self.connect((self, 1), (inter, 1)) + self.connect(inter, msg_sink) + + def _handler_ber(self, samples): + num = len(samples)/2 + arr = numpy.zeros(num, numpy.float32) + for i in range(num): + old_err = self._err_array[self._err_index] + #record error + self._err_array[self._err_index] = _1s_counts[samples[i*2] ^ samples[i*2 + 1]] + self._num_errs = self._num_errs + self._err_array[self._err_index] - old_err + #increment index + self._err_index = (self._err_index + 1)%self._max_samples + self._num_samps = min(self._num_samps + 1, self._max_samples) + #write sample + arr[i] = float(self._num_errs)/float(self._num_samps*self._bits_per_symbol) + #write message + msg = gr.message_from_string(arr.tostring(), 0, gr.sizeof_float, num) + self._msgq_source.insert_tail(msg) + + def _handler_ser(self, samples): + num = len(samples)/2 + arr = numpy.zeros(num, numpy.float32) + for i in range(num): + old_err = self._err_array[self._err_index] + #record error + ref = samples[i*2] + res = samples[i*2 + 1] + if ref == res: + self._err_array[self._err_index] = 0 + else: + self._err_array[self._err_index] = 1 + #update number of errors + self._num_errs = self._num_errs + self._err_array[self._err_index] - old_err + #increment index + self._err_index = (self._err_index + 1)%self._max_samples + self._num_samps = min(self._num_samps + 1, self._max_samples) + #write sample + arr[i] = float(self._num_errs)/float(self._num_samps) + #write message + msg = gr.message_from_string(arr.tostring(), 0, gr.sizeof_float, num) + self._msgq_source.insert_tail(msg) diff --git a/grc/grc_gnuradio/blks2/packet.py b/grc/grc_gnuradio/blks2/packet.py new file mode 100644 index 00000000..50de99ac --- /dev/null +++ b/grc/grc_gnuradio/blks2/packet.py @@ -0,0 +1,241 @@ +# Copyright 2008, 2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, packet_utils +import gnuradio.gr.gr_threading as _threading + +##payload length in bytes +DEFAULT_PAYLOAD_LEN = 512 + +##how many messages in a queue +DEFAULT_MSGQ_LIMIT = 2 + +##threshold for unmaking packets +DEFAULT_THRESHOLD = 12 + +################################################## +## Options Class for OFDM +################################################## +class options(object): + def __init__(self, **kwargs): + for key, value in kwargs.iteritems(): setattr(self, key, value) + +################################################## +## Packet Encoder +################################################## +class _packet_encoder_thread(_threading.Thread): + + def __init__(self, msgq, payload_length, send): + self._msgq = msgq + self._payload_length = payload_length + self._send = send + _threading.Thread.__init__(self) + self.setDaemon(1) + self.keep_running = True + self.start() + + def run(self): + sample = '' #residual sample + while self.keep_running: + msg = self._msgq.delete_head() #blocking read of message queue + sample = sample + msg.to_string() #get the body of the msg as a string + while len(sample) >= self._payload_length: + payload = sample[:self._payload_length] + sample = sample[self._payload_length:] + self._send(payload) + +class packet_encoder(gr.hier_block2): + """ + Hierarchical block for wrapping packet-based modulators. + """ + + def __init__(self, samples_per_symbol, bits_per_symbol, access_code='', pad_for_usrp=True): + """ + packet_mod constructor. + @param samples_per_symbol number of samples per symbol + @param bits_per_symbol number of bits per symbol + @param access_code AKA sync vector + @param pad_for_usrp If true, packets are padded such that they end up a multiple of 128 samples + @param payload_length number of bytes in a data-stream slice + """ + #setup parameters + self._samples_per_symbol = samples_per_symbol + self._bits_per_symbol = bits_per_symbol + self._pad_for_usrp = pad_for_usrp + if not access_code: #get access code + access_code = packet_utils.default_access_code + if not packet_utils.is_1_0_string(access_code): + raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) + self._access_code = access_code + self._pad_for_usrp = pad_for_usrp + #create blocks + msg_source = gr.message_source(gr.sizeof_char, DEFAULT_MSGQ_LIMIT) + self._msgq_out = msg_source.msgq() + #initialize hier2 + gr.hier_block2.__init__( + self, + "packet_encoder", + gr.io_signature(0, 0, 0), # Input signature + gr.io_signature(1, 1, gr.sizeof_char) # Output signature + ) + #connect + self.connect(msg_source, self) + + def send_pkt(self, payload): + """ + Wrap the payload in a packet and push onto the message queue. + @param payload string, data to send + """ + packet = packet_utils.make_packet( + payload, + self._samples_per_symbol, + self._bits_per_symbol, + self._access_code, + self._pad_for_usrp + ) + msg = gr.message_from_string(packet) + self._msgq_out.insert_tail(msg) + +################################################## +## Packet Decoder +################################################## +class _packet_decoder_thread(_threading.Thread): + + def __init__(self, msgq, callback): + _threading.Thread.__init__(self) + self.setDaemon(1) + self._msgq = msgq + self.callback = callback + self.keep_running = True + self.start() + + def run(self): + while self.keep_running: + msg = self._msgq.delete_head() + ok, payload = packet_utils.unmake_packet(msg.to_string(), int(msg.arg1())) + if self.callback: + self.callback(ok, payload) + +class packet_decoder(gr.hier_block2): + """ + Hierarchical block for wrapping packet-based demodulators. + """ + + def __init__(self, access_code='', threshold=-1, callback=None): + """ + packet_demod constructor. + @param access_code AKA sync vector + @param threshold detect access_code with up to threshold bits wrong (0 -> use default) + @param callback a function of args: ok, payload + """ + #access code + if not access_code: #get access code + access_code = packet_utils.default_access_code + if not packet_utils.is_1_0_string(access_code): + raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) + self._access_code = access_code + #threshold + if threshold < 0: threshold = DEFAULT_THRESHOLD + self._threshold = threshold + #blocks + msgq = gr.msg_queue(DEFAULT_MSGQ_LIMIT) #holds packets from the PHY + correlator = gr.correlate_access_code_bb(self._access_code, self._threshold) + framer_sink = gr.framer_sink_1(msgq) + #initialize hier2 + gr.hier_block2.__init__( + self, + "packet_decoder", + gr.io_signature(1, 1, gr.sizeof_char), # Input signature + gr.io_signature(0, 0, 0) # Output signature + ) + #connect + self.connect(self, correlator, framer_sink) + #start thread + _packet_decoder_thread(msgq, callback) + +################################################## +## Packet Mod for OFDM Mod and Packet Encoder +################################################## +class packet_mod_base(gr.hier_block2): + """ + Hierarchical block for wrapping packet source block. + """ + + def __init__(self, packet_source=None, payload_length=0): + if not payload_length: #get payload length + payload_length = DEFAULT_PAYLOAD_LEN + if payload_length%self._item_size_in != 0: #verify that packet length is a multiple of the stream size + raise ValueError, 'The payload length: "%d" is not a mutiple of the stream size: "%d".'%(payload_length, self._item_size_in) + #initialize hier2 + gr.hier_block2.__init__( + self, + "ofdm_mod", + gr.io_signature(1, 1, self._item_size_in), # Input signature + gr.io_signature(1, 1, packet_source._hb.output_signature().sizeof_stream_item(0)) # Output signature + ) + #create blocks + msgq = gr.msg_queue(DEFAULT_MSGQ_LIMIT) + msg_sink = gr.message_sink(self._item_size_in, msgq, False) #False -> blocking + #connect + self.connect(self, msg_sink) + self.connect(packet_source, self) + #start thread + _packet_encoder_thread(msgq, payload_length, packet_source.send_pkt) + +class packet_mod_b(packet_mod_base): _item_size_in = gr.sizeof_char +class packet_mod_s(packet_mod_base): _item_size_in = gr.sizeof_short +class packet_mod_i(packet_mod_base): _item_size_in = gr.sizeof_int +class packet_mod_f(packet_mod_base): _item_size_in = gr.sizeof_float +class packet_mod_c(packet_mod_base): _item_size_in = gr.sizeof_gr_complex + +################################################## +## Packet Demod for OFDM Demod and Packet Decoder +################################################## +class packet_demod_base(gr.hier_block2): + """ + Hierarchical block for wrapping packet sink block. + """ + + def __init__(self, packet_sink=None): + #initialize hier2 + gr.hier_block2.__init__( + self, + "ofdm_mod", + gr.io_signature(1, 1, packet_sink._hb.input_signature().sizeof_stream_item(0)), # Input signature + gr.io_signature(1, 1, self._item_size_out) # Output signature + ) + #create blocks + msg_source = gr.message_source(self._item_size_out, DEFAULT_MSGQ_LIMIT) + self._msgq_out = msg_source.msgq() + #connect + self.connect(self, packet_sink) + self.connect(msg_source, self) + if packet_sink._hb.output_signature().sizeof_stream_item(0): + self.connect(packet_sink, gr.null_sink(packet_sink._hb.output_signature().sizeof_stream_item(0))) + + def recv_pkt(self, ok, payload): + msg = gr.message_from_string(payload, 0, self._item_size_out, len(payload)/self._item_size_out) + if ok: self._msgq_out.insert_tail(msg) + +class packet_demod_b(packet_demod_base): _item_size_out = gr.sizeof_char +class packet_demod_s(packet_demod_base): _item_size_out = gr.sizeof_short +class packet_demod_i(packet_demod_base): _item_size_out = gr.sizeof_int +class packet_demod_f(packet_demod_base): _item_size_out = gr.sizeof_float +class packet_demod_c(packet_demod_base): _item_size_out = gr.sizeof_gr_complex diff --git a/grc/grc_gnuradio/blks2/probe.py b/grc/grc_gnuradio/blks2/probe.py new file mode 100644 index 00000000..8db81f05 --- /dev/null +++ b/grc/grc_gnuradio/blks2/probe.py @@ -0,0 +1,123 @@ +# +# 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 threading +import numpy +import time + +####################################################################################### +## Probe: Function +####################################################################################### +class probe_function(gr.hier_block2, threading.Thread): + """ + The thread polls the function for values and writes to a message source. + """ + + def __init__(self, probe_callback, probe_rate): + #init hier block + gr.hier_block2.__init__( + self, 'probe_function', + gr.io_signature(0, 0, 0), + gr.io_signature(1, 1, gr.sizeof_float), + ) + self._probe_callback = probe_callback + self.set_probe_rate(probe_rate) + #create message source + message_source = gr.message_source(gr.sizeof_float, 1) + self._msgq = message_source.msgq() + #connect + self.connect(message_source, self) + #setup thread + threading.Thread.__init__(self) + self.setDaemon(True) + self.start() + + def run(self): + """ + Infinite polling loop. + """ + while True: + time.sleep(1.0/self._probe_rate) + arr = numpy.array(self._probe_callback(), numpy.float32) + msg = gr.message_from_string(arr.tostring(), 0, gr.sizeof_float, 1) + self._msgq.insert_tail(msg) + + def set_probe_rate(self, probe_rate): + self._probe_rate = probe_rate + +class _probe_base(gr.hier_block2): + def __init__(self, probe_block, probe_callback, probe_rate): + #init hier block + gr.hier_block2.__init__( + self, 'probe', + gr.io_signature(1, 1, probe_block.input_signature().sizeof_stream_items()[0]), + gr.io_signature(1, 1, gr.sizeof_float), + ) + probe_function_block = probe_function(probe_callback, probe_rate) + #forward callbacks + self.set_probe_rate = probe_function_block.set_probe_rate + #connect + self.connect(self, probe_block) + self.connect(probe_function_block, self) + +####################################################################################### +## Probe: Average Magnitude Squared +####################################################################################### +class _probe_avg_mag_sqrd_base(_probe_base): + def __init__(self, threshold, alpha, probe_rate): + #create block + probe_block = self._probe_block_contructor[0](threshold, alpha) + #forward callbacks + self.set_alpha = probe_block.set_alpha + self.set_threshold = probe_block.set_threshold + #init + _probe_base.__init__(self, probe_block, probe_block.level, probe_rate) + +class probe_avg_mag_sqrd_c(_probe_avg_mag_sqrd_base): _probe_block_contructor = (gr.probe_avg_mag_sqrd_c,) +class probe_avg_mag_sqrd_f(_probe_avg_mag_sqrd_base): _probe_block_contructor = (gr.probe_avg_mag_sqrd_f,) + +####################################################################################### +## Probe: Density +####################################################################################### +class probe_density_b(_probe_base): + def __init__(self, alpha, probe_rate): + #create block + probe_block = gr.probe_density_b(alpha) + #forward callbacks + self.set_alpha = probe_block.set_alpha + #init + _probe_base.__init__(self, probe_block, probe_block.density, probe_rate) + +####################################################################################### +## Probe: MPSK SNR +####################################################################################### +class probe_mpsk_snr_c(_probe_base): + def __init__(self, type, alpha, probe_rate): + """ + Type can be "snr", "signal_mean", or "noise_variance" + """ + #create block + probe_block = gr.probe_mpsk_snr_c(alpha) + #forward callbacks + self.set_alpha = probe_block.set_alpha + #init + _probe_base.__init__(self, probe_block, getattr(probe_block, type), probe_rate) diff --git a/grc/grc_gnuradio/blks2/selector.py b/grc/grc_gnuradio/blks2/selector.py new file mode 100644 index 00000000..f0f6d5dd --- /dev/null +++ b/grc/grc_gnuradio/blks2/selector.py @@ -0,0 +1,128 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr + +class selector(gr.hier_block2): + """A hier2 block with N inputs and M outputs, where data is only forwarded through input n to output m.""" + def __init__(self, item_size, num_inputs, num_outputs, input_index, output_index): + """ + Selector constructor. + @param item_size the size of the gr data stream in bytes + @param num_inputs the number of inputs (integer) + @param num_outputs the number of outputs (integer) + @param input_index the index for the source data + @param output_index the index for the destination data + """ + gr.hier_block2.__init__( + self, 'selector', + gr.io_signature(num_inputs, num_inputs, item_size), + gr.io_signature(num_outputs, num_outputs, item_size), + ) + #terminator blocks for unused inputs and outputs + self.input_terminators = [gr.null_sink(item_size) for i in range(num_inputs)] + self.output_terminators = [gr.head(item_size, 0) for i in range(num_outputs)] + self.copy = gr.kludge_copy(item_size) + #connections + for i in range(num_inputs): self.connect((self, i), self.input_terminators[i]) + for i in range(num_outputs): self.connect(gr.null_source(item_size), self.output_terminators[i], (self, i)) + self.item_size = item_size + self.input_index = input_index + self.output_index = output_index + self.num_inputs = num_inputs + self.num_outputs = num_outputs + self._connect_current() + + def _indexes_valid(self): + """ + Are the input and output indexes within range of the number of inputs and outputs? + @return true if input index and output index are in range + """ + return self.input_index in range(self.num_inputs) and self.output_index in range(self.num_outputs) + + def _connect_current(self): + """If the input and output indexes are valid: + disconnect the blocks at the input and output index from their terminators, + and connect them to one another. Then connect the terminators to one another.""" + if self._indexes_valid(): + self.disconnect((self, self.input_index), self.input_terminators[self.input_index]) + self.disconnect(self.output_terminators[self.output_index], (self, self.output_index)) + self.connect((self, self.input_index), self.copy) + self.connect(self.copy, (self, self.output_index)) + self.connect(self.output_terminators[self.output_index], self.input_terminators[self.input_index]) + + def _disconnect_current(self): + """If the input and output indexes are valid: + disconnect the blocks at the input and output index from one another, + and the terminators at the input and output index from one another. + Reconnect the blocks to the terminators.""" + if self._indexes_valid(): + self.disconnect((self, self.input_index), self.copy) + self.disconnect(self.copy, (self, self.output_index)) + self.disconnect(self.output_terminators[self.output_index], self.input_terminators[self.input_index]) + self.connect((self, self.input_index), self.input_terminators[self.input_index]) + self.connect(self.output_terminators[self.output_index], (self, self.output_index)) + + def set_input_index(self, input_index): + """ + Change the block to the new input index if the index changed. + @param input_index the new input index + """ + if self.input_index != input_index: + self.lock() + self._disconnect_current() + self.input_index = input_index + self._connect_current() + self.unlock() + + def set_output_index(self, output_index): + """ + Change the block to the new output index if the index changed. + @param output_index the new output index + """ + if self.output_index != output_index: + self.lock() + self._disconnect_current() + self.output_index = output_index + self._connect_current() + self.unlock() + +class valve(selector): + """Wrapper for selector with 1 input and 1 output.""" + + def __init__(self, item_size, open): + """ + Constructor for valve. + @param item_size the size of the gr data stream in bytes + @param open true if initial valve state is open + """ + if open: output_index = -1 + else: output_index = 0 + selector.__init__(self, item_size, 1, 1, 0, output_index) + + def set_open(self, open): + """ + Callback to set open state. + @param open true to set valve state to open + """ + if open: output_index = -1 + else: output_index = 0 + self.set_output_index(output_index) diff --git a/grc/grc_gnuradio/blks2/tcp.py b/grc/grc_gnuradio/blks2/tcp.py new file mode 100644 index 00000000..c6739b71 --- /dev/null +++ b/grc/grc_gnuradio/blks2/tcp.py @@ -0,0 +1,66 @@ +# +# Copyright 2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +import socket +import os + +def _get_sock_fd(addr, port, server): + """ + Get the file descriptor for the socket. + As a client, block on connect, dup the socket descriptor. + As a server, block on accept, dup the client descriptor. + @param addr the ip address string + @param port the tcp port number + @param server true for server mode, false for client mode + @return the file descriptor number + """ + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + if server: + sock.bind((addr, port)) + sock.listen(1) + clientsock, address = sock.accept() + return os.dup(clientsock.fileno()) + else: + sock.connect((addr, port)) + return os.dup(sock.fileno()) + +class tcp_source(gr.hier_block2): + def __init__(self, itemsize, addr, port, server=True): + #init hier block + gr.hier_block2.__init__( + self, 'tcp_source', + gr.io_signature(0, 0, 0), + gr.io_signature(1, 1, itemsize), + ) + fd = _get_sock_fd(addr, port, server) + self.connect(gr.file_descriptor_source(itemsize, fd), self) + +class tcp_sink(gr.hier_block2): + def __init__(self, itemsize, addr, port, server=False): + #init hier block + gr.hier_block2.__init__( + self, 'tcp_sink', + gr.io_signature(1, 1, itemsize), + gr.io_signature(0, 0, 0), + ) + fd = _get_sock_fd(addr, port, server) + self.connect(self, gr.file_descriptor_sink(itemsize, fd)) diff --git a/grc/grc_gnuradio/blks2/variable_sink.py b/grc/grc_gnuradio/blks2/variable_sink.py new file mode 100644 index 00000000..cad3b8b0 --- /dev/null +++ b/grc/grc_gnuradio/blks2/variable_sink.py @@ -0,0 +1,64 @@ +# +# Copyright 2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +import threading +import numpy + +class _variable_sink_base(gr.hier_block2, threading.Thread): + """ + The thread polls the message queue for values and writes to a callback. + """ + + def __init__(self, vlen, decim, callback): + self._vlen = vlen + self._callback = callback + self._item_size = self._size*self._vlen + #init hier block + gr.hier_block2.__init__( + self, 'variable_sink', + gr.io_signature(1, 1, self._item_size), + gr.io_signature(0, 0, 0), + ) + #create blocks + self._decimator = gr.keep_one_in_n(self._item_size, decim) + self._msgq = gr.msg_queue(2) + message_sink = gr.message_sink(self._item_size, self._msgq, False) + #connect + self.connect(self, self._decimator, message_sink) + #setup thread + threading.Thread.__init__(self) + self.setDaemon(True) + self.start() + + def set_decim(self, decim): self._decimator.set_n(decim) + + def run(self): + while True: #truncate to item size, convert to array, callback + msg = self._msgq.delete_head().to_string()[-self._item_size:] + arr = map(self._cast, numpy.fromstring(msg, self._numpy)) + self._callback(self._vlen > 1 and arr or arr[0]) + +class variable_sink_b(_variable_sink_base): _numpy, _size, _cast = numpy.int8, gr.sizeof_char, int +class variable_sink_s(_variable_sink_base): _numpy, _size, _cast = numpy.int16, gr.sizeof_short, int +class variable_sink_i(_variable_sink_base): _numpy, _size, _cast = numpy.int32, gr.sizeof_int, int +class variable_sink_f(_variable_sink_base): _numpy, _size, _cast = numpy.float32, gr.sizeof_float, float +class variable_sink_c(_variable_sink_base): _numpy, _size, _cast = numpy.complex64, gr.sizeof_gr_complex, complex diff --git a/grc/grc_gnuradio/usrp/__init__.py b/grc/grc_gnuradio/usrp/__init__.py new file mode 100644 index 00000000..1956bbd5 --- /dev/null +++ b/grc/grc_gnuradio/usrp/__init__.py @@ -0,0 +1,26 @@ +# 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, \ + simple_sink_c, simple_sink_s +from dual_usrp import \ + dual_source_c, dual_source_s, \ + dual_sink_c, dual_sink_s diff --git a/grc/grc_gnuradio/usrp/common.py b/grc/grc_gnuradio/usrp/common.py new file mode 100644 index 00000000..65c1e7e2 --- /dev/null +++ b/grc/grc_gnuradio/usrp/common.py @@ -0,0 +1,75 @@ +# Copyright 2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import sys +from gnuradio import usrp, gr + +################################################## +# USRP base class with common methods +################################################## +class usrp_helper(object): + def _make_usrp(self, *args, **kwargs): self._u = self._usrp_args[0](*args, **kwargs) + def _get_u(self): return self._u + def _get_io_size(self): return self._usrp_args[1] + def _set_frequency(self, chan, subdev, frequency, verbose=False): + """ + Set the carrier frequency for the given subdevice. + @param chan specifies the DDC/DUC number + @param frequency the carrier frequency in Hz + @param verbose if true, print usrp tuning information + """ + r = self._get_u().tune(chan, subdev, frequency) + if not verbose: return + print subdev.side_and_name() + if r: + print "\tr.baseband_frequency =", r.baseband_freq + print "\tr.dxc_frequency =", r.dxc_freq + print "\tr.residual_frequency =", r.residual_freq + print "\tr.inverted =", r.inverted, "\n" + else: print >> sys.stderr, 'Error calling tune on subdevice.' + def set_format(self, width, shift): self._get_u().set_format(self._get_u().make_format(width, shift)) + +################################################## +# Classes to associate usrp constructor w/ io size +################################################## +class usrp_source_c(usrp_helper): _usrp_args = (usrp.source_c, gr.sizeof_gr_complex) +class usrp_source_s(usrp_helper): _usrp_args = (usrp.source_s, gr.sizeof_short) +class usrp_sink_c(usrp_helper): _usrp_args = (usrp.sink_c, gr.sizeof_gr_complex) +class usrp_sink_s(usrp_helper): _usrp_args = (usrp.sink_s, gr.sizeof_short) + +################################################## +# Side spec and antenna spec functions +################################################## +def is_flex(rx_ant): return rx_ant.upper() in ('TX/RX', 'RX2') +def to_spec(side, rx_ant='RXA'): + """ + Convert the side to a spec number. + @param side A or B + @param rx_ant antenna type + @return the spec (0/1, 0/1/2) + """ + #determine the side spec + try: side_spec = {'A': 0, 'B': 1}[side.upper()] + except: raise ValueError, 'Side A or B expected.' + #determine the subdevice spec + if rx_ant.upper() == 'RXB': subdev_spec = 1 + elif rx_ant.upper() == 'RXAB': subdev_spec = 2 + else: subdev_spec = 0 + return (side_spec, subdev_spec) diff --git a/grc/grc_gnuradio/usrp/dual_usrp.py b/grc/grc_gnuradio/usrp/dual_usrp.py new file mode 100644 index 00000000..1ecf7c47 --- /dev/null +++ b/grc/grc_gnuradio/usrp/dual_usrp.py @@ -0,0 +1,132 @@ +# Copyright 2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import common +from gnuradio import gr, usrp + +#################################################################### +# Dual USRP Source +#################################################################### +class _dual_source(gr.hier_block2): + """A dual usrp source of IO type short or complex.""" + + def __init__(self, which, rx_ant_a='RXA', rx_ant_b='RXA'): + """ + USRP dual source contructor. + @param which the unit number + @param rx_ant_a the antenna choice + @param rx_ant_b the antenna choice + """ + #initialize hier2 block + gr.hier_block2.__init__( + self, 'usrp_dual_source', + gr.io_signature(0, 0, 0), + gr.io_signature(2, 2, self._get_io_size()), + ) + #create usrp object + self._make_usrp(which=which, nchan=2) + subdev_spec_a = common.to_spec('A', rx_ant_a) + subdev_spec_b = common.to_spec('B', rx_ant_b) + self._get_u().set_mux(self._get_u().determine_rx_mux_value(subdev_spec_a, subdev_spec_b)) + self._subdev_a = self._get_u().selected_subdev(subdev_spec_a) + self._subdev_b = self._get_u().selected_subdev(subdev_spec_b) + #connect + deinter = gr.deinterleave(self._get_io_size()) + self.connect(self._get_u(), deinter) + for i in range(2): self.connect((deinter, i), (self, i)) + + def set_decim_rate(self, decim): self._get_u().set_decim_rate(int(decim)) + def set_frequency_a(self, frequency, verbose=False): + self._set_frequency( + chan=0, #ddc0 + subdev=self._subdev_a, + frequency=frequency, + verbose=verbose, + ) + def set_frequency_b(self, frequency, verbose=False): + self._set_frequency( + chan=1, #ddc1 + subdev=self._subdev_b, + frequency=frequency, + verbose=verbose, + ) + def set_lo_offset_a(self, lo_offset): self._subdev_a.set_lo_offset(lo_offset) + def set_lo_offset_b(self, lo_offset): self._subdev_b.set_lo_offset(lo_offset) + def set_gain_a(self, gain): self._subdev_a.set_gain(gain) + def set_gain_b(self, gain): self._subdev_b.set_gain(gain) + +class dual_source_c(_dual_source, common.usrp_source_c): pass +class dual_source_s(_dual_source, common.usrp_source_s): pass + +#################################################################### +# Dual USRP Sink +#################################################################### +class _dual_sink(gr.hier_block2): + """A dual usrp sink of IO type short or complex.""" + + def __init__(self, which): + """ + USRP simple sink contructor. + @param which the unit number + """ + #initialize hier2 block + gr.hier_block2.__init__( + self, 'usrp_dual_sink', + gr.io_signature(2, 2, self._get_io_size()), + gr.io_signature(0, 0, 0), + ) + #create usrp object + self._make_usrp(which=which, nchan=2) + subdev_spec_a = common.to_spec('A') + subdev_spec_b = common.to_spec('B') + self._get_u().set_mux(self._get_u().determine_tx_mux_value(subdev_spec_a, subdev_spec_b)) + self._subdev_a = self._get_u().selected_subdev(subdev_spec_a) + self._subdev_b = self._get_u().selected_subdev(subdev_spec_b) + #connect + inter = gr.interleave(self._get_io_size()) + self.connect(inter, self._get_u()) + for i in range(2): self.connect((self, i), (inter, i)) + + def set_interp_rate(self, interp): self._get_u().set_interp_rate(int(interp)) + def set_frequency_a(self, frequency, verbose=False): + self._set_frequency( + chan=self._subdev_a.which(), + subdev=self._subdev_a, + frequency=frequency, + verbose=verbose, + ) + def set_frequency_b(self, frequency, verbose=False): + self._set_frequency( + chan=self._subdev_b.which(), + subdev=self._subdev_b, + frequency=frequency, + verbose=verbose, + ) + def set_lo_offset_a(self, lo_offset): self._subdev_a.set_lo_offset(lo_offset) + def set_lo_offset_b(self, lo_offset): self._subdev_b.set_lo_offset(lo_offset) + def set_gain_a(self, gain): self._subdev_a.set_gain(gain) + def set_gain_b(self, gain): self._subdev_b.set_gain(gain) + def set_enable_a(self, enable): self._subdev_a.set_enable(enable) + def set_enable_b(self, enable): self._subdev_b.set_enable(enable) + def set_auto_tr_a(self, auto_tr): self._subdev_a.set_auto_tr(auto_tr) + def set_auto_tr_b(self, auto_tr): self._subdev_b.set_auto_tr(auto_tr) + +class dual_sink_c(_dual_sink, common.usrp_sink_c): pass +class dual_sink_s(_dual_sink, common.usrp_sink_s): pass diff --git a/grc/grc_gnuradio/usrp/simple_usrp.py b/grc/grc_gnuradio/usrp/simple_usrp.py new file mode 100644 index 00000000..9065c7fe --- /dev/null +++ b/grc/grc_gnuradio/usrp/simple_usrp.py @@ -0,0 +1,113 @@ +# Copyright 2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import common +from gnuradio import gr, usrp + +#################################################################### +# Simple USRP Source +#################################################################### +class _simple_source(gr.hier_block2): + """A single usrp source of IO type short or complex.""" + + def __init__(self, which, side='A', rx_ant='RXA', no_hb=False): + """ + USRP simple source contructor. + @param which the unit number + @param side the usrp side A or B + @param rx_ant the antenna choice + @param no_hb disable half band filters + """ + self._no_hb = no_hb + #initialize hier2 block + gr.hier_block2.__init__( + self, 'usrp_simple_source', + gr.io_signature(0, 0, 0), + gr.io_signature(1, 1, self._get_io_size()), + ) + #create usrp object + if self._no_hb: self._make_usrp(which=which, nchan=1, fpga_filename="std_4rx_0tx.rbf") + else: self._make_usrp(which=which, nchan=1) + subdev_spec = common.to_spec(side, rx_ant) + self._get_u().set_mux(self._get_u().determine_rx_mux_value(subdev_spec)) + self._subdev = self._get_u().selected_subdev(subdev_spec) + if common.is_flex(rx_ant): self._subdev.select_rx_antenna(rx_ant) + #connect + self.connect(self._get_u(), self) + + def set_decim_rate(self, decim): + self._get_u().set_decim_rate(int(decim)) + if self._no_hb: #set the BW to half the sample rate + self._subdev.set_bw(self._get_u().converter_rate()/decim/2) + def set_lo_offset(self, lo_offset): self._subdev.set_lo_offset(lo_offset) + def set_frequency(self, frequency, verbose=False): + self._set_frequency( + chan=0, #ddc0 + subdev=self._subdev, + frequency=frequency, + verbose=verbose, + ) + def set_gain(self, gain): self._subdev.set_gain(gain) + +class simple_source_c(_simple_source, common.usrp_source_c): pass +class simple_source_s(_simple_source, common.usrp_source_s): pass + +#################################################################### +# Simple USRP Sink +#################################################################### +class _simple_sink(gr.hier_block2): + """A single usrp sink of IO type short or complex.""" + + def __init__(self, which, side='A'): + """ + USRP simple sink contructor. + @param which the unit number + @param side the usrp side A or B + """ + #initialize hier2 block + gr.hier_block2.__init__( + self, 'usrp_simple_sink', + gr.io_signature(1, 1, self._get_io_size()), + gr.io_signature(0, 0, 0), + ) + #create usrp object + self._make_usrp(which=which, nchan=1) + subdev_spec = common.to_spec(side) + self._get_u().set_mux(self._get_u().determine_tx_mux_value(subdev_spec)) + self._subdev = self._get_u().selected_subdev(subdev_spec) + #connect + self.connect(self, self._get_u()) + + def set_interp_rate(self, interp): self._get_u().set_interp_rate(int(interp)) + def set_frequency(self, frequency, verbose=False): + self._set_frequency( + chan=self._subdev.which(), + subdev=self._subdev, + frequency=frequency, + verbose=verbose, + ) + def set_lo_offset(self, lo_offset): self._subdev.set_lo_offset(lo_offset) + def set_gain(self, gain): self._subdev.set_gain(gain) + def set_enable(self, enable): self._subdev.set_enable(enable) + def set_auto_tr(self, auto_tr): self._subdev.set_auto_tr(auto_tr) + +class simple_sink_c(_simple_sink, common.usrp_sink_c): pass +class simple_sink_s(_simple_sink, common.usrp_sink_s): pass + diff --git a/grc/grc_gnuradio/wxgui/__init__.py b/grc/grc_gnuradio/wxgui/__init__.py new file mode 100644 index 00000000..94a0adb8 --- /dev/null +++ b/grc/grc_gnuradio/wxgui/__init__.py @@ -0,0 +1,21 @@ +# 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 top_block_gui import top_block_gui diff --git a/grc/grc_gnuradio/wxgui/top_block_gui.py b/grc/grc_gnuradio/wxgui/top_block_gui.py new file mode 100644 index 00000000..97bed04a --- /dev/null +++ b/grc/grc_gnuradio/wxgui/top_block_gui.py @@ -0,0 +1,105 @@ +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import wx +import sys, os +from gnuradio import gr + +default_gui_size = (200, 100) + +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 + @param size the main window size tuple in pixels + @param icon the file path to an icon or None + """ + #initialize + gr.top_block.__init__(self) + self._size = size + #set the icon + if icon and os.path.isfile(icon): self._icon = icon + else: self._icon = None + #create gui elements + self._wx_app = wx.App() + self._wx_frame = wx.Frame(None , -1, title) + self._wx_grid = wx.GridBagSizer(5, 5) + 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) + @param col the column specification (integer >= 0) + @param row_span the row span specification (integer >= 1) + @param col_span the column span specification (integer >= 1) + """ + self._wx_grid.Add(win, wx.GBPosition(row, col), wx.GBSpan(row_span, col_span), wx.EXPAND) + + def start(self, start=True): + if start: + gr.top_block.start(self) + else: + gr.top_block.stop(self) + gr.top_block.wait(self) + + def Run(self, autostart=True): + """ + Setup the wx gui elements. + Start the gr top block. + Block with the wx main loop. + """ + #set wx app icon + if self._icon: self._wx_frame.SetIcon(wx.Icon(self._icon, wx.BITMAP_TYPE_ANY)) + #set minimal window size + self._wx_frame.SetSizeHints(*self._size) + #create callback for quit + def _quit(event): + gr.top_block.stop(self) + self._wx_frame.Destroy() + #setup app + self._wx_vbox.Add(self._wx_grid, 0, wx.EXPAND) + self._wx_frame.Bind(wx.EVT_CLOSE, _quit) + self._wx_frame.SetSizerAndFit(self._wx_vbox) + self._wx_frame.Show() + self._wx_app.SetTopWindow(self._wx_frame) + #start flow graph + self.start(autostart) + #blocking main loop + self._wx_app.MainLoop() diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py new file mode 100644 index 00000000..2c411a17 --- /dev/null +++ b/grc/gui/ActionHandler.py @@ -0,0 +1,411 @@ +""" +Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import os +import signal +from Constants import IMAGE_FILE_EXTENSION +import Actions +import pygtk +pygtk.require('2.0') +import gtk +import gobject +import Preferences +from threading import Thread +import Messages +from .. base import ParseXML +import random +from Platform import Platform +from MainWindow import MainWindow +from ParamsDialog import ParamsDialog +import Dialogs +from FileDialogs import OpenFlowGraphFileDialog, SaveFlowGraphFileDialog, SaveImageFileDialog + +gobject.threads_init() + +class ActionHandler: + """ + The action handler will setup all the major window components, + and handle button presses and flow graph operations from the GUI. + """ + + def __init__(self, file_paths, platform): + """ + ActionHandler constructor. + Create the main window, setup the message handler, import the preferences, + and connect all of the action handlers. Finally, enter the gtk main loop and block. + @param file_paths a list of flow graph file passed from command line + @param platform platform module + """ + self.clipboard = None + platform = Platform(platform) + for action in Actions.get_all_actions(): 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.get_focus_flag + #setup the messages + Messages.register_messenger(self.main_window.add_report_line) + Messages.send_init(platform) + #initialize + self.init_file_paths = file_paths + self.handle_states(Actions.APPLICATION_INITIALIZE) + #enter the mainloop + gtk.main() + + def _handle_key_press(self, widget, event): + """ + Handle key presses from the keyboard and translate key combinations into actions. + This key press handler is called prior to the gtk key press handler. + This handler bypasses built in accelerator key handling when in focus because + * some keys are ignored by the accelerators like the direction keys, + * some keys are not registered to any accelerators but are still used. + When not in focus, gtk and the accelerators handle the the key press. + @return false to let gtk handle the key action + """ + #dont allow key presses to queue up + if gtk.events_pending(): return True + #extract action name from this key press + key_name = gtk.gdk.keyval_name(event.keyval) + mod_mask = event.state + action_name = Actions.get_action_name_from_key_name(key_name, mod_mask) + #handle the action if flow graph is in focus + if action_name and self.get_focus_flag(): + self.handle_states(action_name) + return True #handled by this method + return False #let gtk handle the key press + + 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.get_all_actions(): action.set_sensitive(False) #set all actions disabled + # enable a select few actions + for action in ( + Actions.APPLICATION_QUIT, Actions.FLOW_GRAPH_NEW, + Actions.FLOW_GRAPH_OPEN, Actions.FLOW_GRAPH_SAVE_AS, + Actions.FLOW_GRAPH_CLOSE, Actions.ABOUT_WINDOW_DISPLAY, + Actions.FLOW_GRAPH_SCREEN_CAPTURE, Actions.HELP_WINDOW_DISPLAY, + Actions.COLORS_WINDOW_DISPLAY, + ): Actions.get_action_from_name(action).set_sensitive(True) + if not self.init_file_paths: + self.init_file_paths = Preferences.files_open() + if not self.init_file_paths: self.init_file_paths = [''] + for file_path in self.init_file_paths: + if file_path: self.main_window.new_page(file_path) #load pages from file paths + if Preferences.file_open() in self.init_file_paths: + self.main_window.new_page(Preferences.file_open(), show=True) + if not self.get_page(): self.main_window.new_page() #ensure that at least a blank page exists + elif state == Actions.APPLICATION_QUIT: + if self.main_window.close_pages(): + gtk.main_quit() + exit(0) + ################################################## + # Selections + ################################################## + elif state == Actions.ELEMENT_SELECT: + pass #do nothing, update routines below + elif state == Actions.NOTHING_SELECT: + self.get_flow_graph().unselect() + ################################################## + # 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(Actions.BLOCK_COPY) + self.handle_states(Actions.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_CCW: + if self.get_flow_graph().rotate_selected(90): + self.get_flow_graph().update() + self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) + self.get_page().set_saved(False) + elif state == Actions.BLOCK_ROTATE_CW: + if self.get_flow_graph().rotate_selected(-90): + self.get_flow_graph().update() + self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) + self.get_page().set_saved(False) + elif state == Actions.ELEMENT_DELETE: + if self.get_flow_graph().remove_selected(): + self.get_flow_graph().update() + self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) + self.handle_states(Actions.NOTHING_SELECT) + self.get_page().set_saved(False) + elif state == Actions.ELEMENT_CREATE: + self.get_flow_graph().update() + 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.ABOUT_WINDOW_DISPLAY: + Dialogs.AboutDialog(self.get_flow_graph().get_parent()) + elif state == Actions.HELP_WINDOW_DISPLAY: + Dialogs.HelpDialog() + elif state == Actions.COLORS_WINDOW_DISPLAY: + Dialogs.ColorsDialog(self.get_flow_graph().get_parent()) + ################################################## + # Param Modifications + ################################################## + elif state == Actions.BLOCK_PARAM_MODIFY: + selected_block = self.get_flow_graph().get_selected_block() + if selected_block and ParamsDialog(selected_block).run(): + 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: + #read-only or undefined file path, do save-as + if self.get_page().get_read_only() or not self.get_page().get_file_path(): + self.handle_states(Actions.FLOW_GRAPH_SAVE_AS) + #otherwise try to save + else: + try: + ParseXML.to_file(self.get_flow_graph().export_data(), self.get_page().get_file_path()) + self.get_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 is not 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 is not None: + pixmap = self.get_flow_graph().get_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_CCW).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + Actions.get_action_from_name(Actions.BLOCK_ROTATE_CW).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() + try: #set the size of the flow graph area (if changed) + new_size = self.get_flow_graph().get_option('window_size') + if self.get_flow_graph().get_size() != tuple(new_size): + self.get_flow_graph().set_size(*new_size) + except: pass + #draw the flow graph + self.get_flow_graph().update_selected() + self.get_flow_graph().queue_draw() + + 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 executing process by reading from its stdout. + Use gobject.idle_add when calling functions that modify gtk objects. + """ + #handle completion + r = "\n" + while(r): + gobject.idle_add(Messages.send_verbose_exec, r) + r = os.read(self.p.stdout.fileno(), 1024) + gobject.idle_add(self.done) + + def done(self): + """Perform end of execution tasks.""" + Messages.send_end_exec() + self.page.set_pid(None) + self.update_exec_stop() diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py new file mode 100644 index 00000000..3695e09e --- /dev/null +++ b/grc/gui/Actions.py @@ -0,0 +1,169 @@ +""" +Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import pygtk +pygtk.require('2.0') +import gtk + +###################################################################################################### +# Action Names +###################################################################################################### +APPLICATION_INITIALIZE = 'app init' +APPLICATION_QUIT = 'app quit' +PARAM_MODIFY = 'param modify' +BLOCK_MOVE = 'block move' +BLOCK_ROTATE_CCW = 'block rotate ccw' +BLOCK_ROTATE_CW = 'block rotate cw' +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' +HELP_WINDOW_DISPLAY = 'help window display' +COLORS_WINDOW_DISPLAY = 'colors window display' + +###################################################################################################### +# Action Key Map +###################################################################################################### +_actions_key_list = ( + #action name, key name, mod mask + (FLOW_GRAPH_NEW, 'n', gtk.gdk.CONTROL_MASK), + (FLOW_GRAPH_OPEN, 'o', gtk.gdk.CONTROL_MASK), + (FLOW_GRAPH_SAVE, 's', gtk.gdk.CONTROL_MASK), + (FLOW_GRAPH_SAVE_AS, 's', gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK), + (FLOW_GRAPH_CLOSE, 'w', gtk.gdk.CONTROL_MASK), + (APPLICATION_QUIT, 'q', gtk.gdk.CONTROL_MASK), + (FLOW_GRAPH_UNDO, 'z', gtk.gdk.CONTROL_MASK), + (FLOW_GRAPH_REDO, 'y', gtk.gdk.CONTROL_MASK), + (ELEMENT_DELETE, 'Delete', 0), + (BLOCK_ROTATE_CCW, 'Left', 0), + (BLOCK_ROTATE_CW, 'Right', 0), + (BLOCK_DEC_TYPE, 'Up', 0), + (BLOCK_INC_TYPE, 'Down', 0), + (BLOCK_PARAM_MODIFY, 'Return', 0), + (BLOCK_ENABLE, 'e', 0), + (BLOCK_DISABLE, 'd', 0), + (BLOCK_CUT, 'x', gtk.gdk.CONTROL_MASK), + (BLOCK_COPY, 'c', gtk.gdk.CONTROL_MASK), + (BLOCK_PASTE, 'v', gtk.gdk.CONTROL_MASK), + (FLOW_GRAPH_GEN, 'F5', 0), + (FLOW_GRAPH_EXEC, 'F6', 0), + (FLOW_GRAPH_KILL, 'F7', 0), + (FLOW_GRAPH_SCREEN_CAPTURE, 'Print', 0), + (HELP_WINDOW_DISPLAY, 'F1', 0), + #the following have no associated gtk.Action + (PORT_CONTROLLER_INC, 'equal', 0), + (PORT_CONTROLLER_INC, 'plus', 0), + (PORT_CONTROLLER_INC, 'KP_Add', 0), + (PORT_CONTROLLER_DEC, 'minus', 0), + (PORT_CONTROLLER_DEC, 'KP_Subtract', 0), +) + +_actions_key_dict = dict(((key_name, mod_mask), action_name) for action_name, key_name, mod_mask in _actions_key_list) +def get_action_name_from_key_name(key_name, mod_mask=0): + """ + Get the action name associated with the key name and mask. + Both keyname and mask have to match. + @param key_name the name of the key + @param mod_mask the key press mask (shift, ctrl) 0 for none + @return the action name or blank string + """ + key_name_mod_mask = (key_name, mod_mask) + if key_name_mod_mask in _actions_key_dict: return _actions_key_dict[key_name_mod_mask] + return '' + +###################################################################################################### +# Actions +###################################################################################################### +_actions_list = ( + gtk.Action(FLOW_GRAPH_NEW, '_New', 'Create a new flow graph', gtk.STOCK_NEW), + gtk.Action(FLOW_GRAPH_OPEN, '_Open', 'Open an existing flow graph', gtk.STOCK_OPEN), + gtk.Action(FLOW_GRAPH_SAVE, '_Save', 'Save the current flow graph', gtk.STOCK_SAVE), + gtk.Action(FLOW_GRAPH_SAVE_AS, 'Save _As', 'Save the current flow graph as...', gtk.STOCK_SAVE_AS), + gtk.Action(FLOW_GRAPH_CLOSE, '_Close', 'Close the current flow graph', gtk.STOCK_CLOSE), + gtk.Action(APPLICATION_QUIT, '_Quit', 'Quit program', gtk.STOCK_QUIT), + gtk.Action(FLOW_GRAPH_UNDO, '_Undo', 'Undo a change to the flow graph', gtk.STOCK_UNDO), + gtk.Action(FLOW_GRAPH_REDO, '_Redo', 'Redo a change to the flow graph', gtk.STOCK_REDO), + gtk.Action(ELEMENT_DELETE, '_Delete', 'Delete the selected blocks', gtk.STOCK_DELETE), + gtk.Action(BLOCK_ROTATE_CCW, 'Rotate Counterclockwise', 'Rotate the selected blocks 90 degrees to the left', gtk.STOCK_GO_BACK), + gtk.Action(BLOCK_ROTATE_CW, 'Rotate Clockwise', 'Rotate the selected blocks 90 degrees to the right', gtk.STOCK_GO_FORWARD), + gtk.Action(BLOCK_PARAM_MODIFY, '_Properties', 'Modify params for the selected block', gtk.STOCK_PROPERTIES), + gtk.Action(BLOCK_ENABLE, 'E_nable', 'Enable the selected blocks', gtk.STOCK_CONNECT), + gtk.Action(BLOCK_DISABLE, 'D_isable', 'Disable the selected blocks', gtk.STOCK_DISCONNECT), + gtk.Action(BLOCK_CUT, 'Cu_t', 'Cut', gtk.STOCK_CUT), + gtk.Action(BLOCK_COPY, '_Copy', 'Copy', gtk.STOCK_COPY), + gtk.Action(BLOCK_PASTE, '_Paste', 'Paste', gtk.STOCK_PASTE), + gtk.Action(ABOUT_WINDOW_DISPLAY, '_About', 'About this program', gtk.STOCK_ABOUT), + gtk.Action(HELP_WINDOW_DISPLAY, '_Help', 'Usage Tips', gtk.STOCK_HELP), + gtk.Action(COLORS_WINDOW_DISPLAY, '_Colors', 'Color Mapping', gtk.STOCK_DIALOG_INFO), + gtk.Action(FLOW_GRAPH_GEN, '_Generate', 'Generate the flow graph', gtk.STOCK_CONVERT), + gtk.Action(FLOW_GRAPH_EXEC, '_Execute', 'Execute the flow graph', gtk.STOCK_EXECUTE), + gtk.Action(FLOW_GRAPH_KILL, '_Kill', 'Kill the flow graph', gtk.STOCK_STOP), + gtk.Action(FLOW_GRAPH_SCREEN_CAPTURE, 'S_creen Capture', 'Create a screen capture of the flow graph', gtk.STOCK_PRINT), +) +def get_all_actions(): return _actions_list + +_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 action_name in _actions_dict: return _actions_dict[action_name] + raise KeyError('Action Name: "%s" does not exist'%action_name) + +###################################################################################################### +# Accelerators +###################################################################################################### +_accel_group = gtk.AccelGroup() +def get_accel_group(): return _accel_group + +#set the accelerator group, and accelerator path +#register the key name and mod mask with the accelerator path +for action_name, key_name, mod_mask in _actions_key_list: + try: + accel_path = '
/'+action_name + get_action_from_name(action_name).set_accel_group(get_accel_group()) + get_action_from_name(action_name).set_accel_path(accel_path) + gtk.accel_map_add_entry(accel_path, gtk.gdk.keyval_from_name(key_name), mod_mask) + except KeyError: pass #no action was created for this action name diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py new file mode 100644 index 00000000..e0c547eb --- /dev/null +++ b/grc/gui/Bars.py @@ -0,0 +1,138 @@ +""" +Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import Actions +import pygtk +pygtk.require('2.0') +import gtk + +##The list of actions for the toolbar. +TOOLBAR_LIST = ( + Actions.FLOW_GRAPH_NEW, + Actions.FLOW_GRAPH_OPEN, + Actions.FLOW_GRAPH_SAVE, + Actions.FLOW_GRAPH_CLOSE, + None, + Actions.FLOW_GRAPH_SCREEN_CAPTURE, + None, + Actions.BLOCK_CUT, + Actions.BLOCK_COPY, + Actions.BLOCK_PASTE, + Actions.ELEMENT_DELETE, + None, + Actions.FLOW_GRAPH_UNDO, + Actions.FLOW_GRAPH_REDO, + None, + Actions.FLOW_GRAPH_GEN, + Actions.FLOW_GRAPH_EXEC, + Actions.FLOW_GRAPH_KILL, + None, + Actions.BLOCK_ROTATE_CCW, + Actions.BLOCK_ROTATE_CW, + None, + Actions.BLOCK_ENABLE, + Actions.BLOCK_DISABLE, +) + +##The list of actions and categories for the menu bar. +MENU_BAR_LIST = ( + (gtk.Action('File', '_File', None, None), [ + Actions.FLOW_GRAPH_NEW, + Actions.FLOW_GRAPH_OPEN, + None, + Actions.FLOW_GRAPH_SAVE, + Actions.FLOW_GRAPH_SAVE_AS, + None, + Actions.FLOW_GRAPH_SCREEN_CAPTURE, + None, + Actions.FLOW_GRAPH_CLOSE, + Actions.APPLICATION_QUIT, + ]), + (gtk.Action('Edit', '_Edit', None, None), [ + Actions.FLOW_GRAPH_UNDO, + Actions.FLOW_GRAPH_REDO, + None, + Actions.BLOCK_CUT, + Actions.BLOCK_COPY, + Actions.BLOCK_PASTE, + Actions.ELEMENT_DELETE, + None, + Actions.BLOCK_ROTATE_CCW, + Actions.BLOCK_ROTATE_CW, + None, + Actions.BLOCK_ENABLE, + Actions.BLOCK_DISABLE, + None, + Actions.BLOCK_PARAM_MODIFY, + ]), + (gtk.Action('Build', '_Build', None, None), [ + Actions.FLOW_GRAPH_GEN, + Actions.FLOW_GRAPH_EXEC, + Actions.FLOW_GRAPH_KILL, + ]), + (gtk.Action('Help', '_Help', None, None), [ + Actions.HELP_WINDOW_DISPLAY, + Actions.COLORS_WINDOW_DISPLAY, + None, + Actions.ABOUT_WINDOW_DISPLAY, + ]), +) + +class Toolbar(gtk.Toolbar): + """The gtk toolbar with actions added from the toolbar list.""" + + def __init__(self): + """ + Parse the list of action names in the toolbar list. + Look up the action for each name in the action list and add it to the toolbar. + """ + gtk.Toolbar.__init__(self) + self.set_style(gtk.TOOLBAR_ICONS) + for action_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/gui/Block.py b/grc/gui/Block.py new file mode 100644 index 00000000..0496f0a2 --- /dev/null +++ b/grc/gui/Block.py @@ -0,0 +1,199 @@ +""" +Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from Element import Element +import Utils +import Colors +from .. base import odict +from Constants import BORDER_PROXIMITY_SENSITIVITY +from Constants import \ + BLOCK_LABEL_PADDING, \ + PORT_SEPARATION, LABEL_SEPARATION, \ + PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS +import pygtk +pygtk.require('2.0') +import gtk + +BLOCK_MARKUP_TMPL="""\ +#set $foreground = $block.is_valid() and 'black' or 'red' +$encode($block.get_name())""" + +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, + odict({ + 'name': 'GUI Coordinate', + 'key': '_coordinate', + 'type': 'raw', + 'value': '(0, 0)', + 'hide': 'all', + }) + ) + self._params['_rotation'] = self.get_parent().get_parent().Param( + self, + odict({ + 'name': 'GUI Rotation', + 'key': '_rotation', + 'type': 'raw', + 'value': '0', + 'hide': 'all', + }) + ) + Element.__init__(self) + + def get_coordinate(self): + """ + Get the coordinate from the position param. + @return the coordinate tuple (x, y) or (0, 0) if failure + """ + try: #should evaluate to tuple + coor = eval(self.get_param('_coordinate').get_value()) + x, y = map(int, coor) + fgW,fgH = self.get_parent().get_size() + if x <= 0: + x = 0 + elif x >= fgW - BORDER_PROXIMITY_SENSITIVITY: + x = fgW - BORDER_PROXIMITY_SENSITIVITY + if y <= 0: + y = 0 + elif y >= fgH - BORDER_PROXIMITY_SENSITIVITY: + y = fgH - BORDER_PROXIMITY_SENSITIVITY + return (x, y) + except: + self.set_coordinate((0, 0)) + return (0, 0) + + def set_coordinate(self, coor): + """ + Set the coordinate into the position param. + @param coor the coordinate tuple (x, y) + """ + self.get_param('_coordinate').set_value(str(coor)) + + def get_rotation(self): + """ + Get the rotation from the position param. + @return the rotation in degrees or 0 if failure + """ + try: #should evaluate to dict + rotation = eval(self.get_param('_rotation').get_value()) + return int(rotation) + except: + self.set_rotation(POSSIBLE_ROTATIONS[0]) + return POSSIBLE_ROTATIONS[0] + + def set_rotation(self, rot): + """ + Set the rotation into the position param. + @param rot the rotation in degrees + """ + self.get_param('_rotation').set_value(str(rot)) + + def update(self): + """Update the block, parameters, and ports when a change occurs.""" + self._bg_color = self.get_enabled() and Colors.BLOCK_ENABLED_COLOR or Colors.BLOCK_DISABLED_COLOR + self.clear() + self._create_labels() + self.W = self.label_width + 2*BLOCK_LABEL_PADDING + self.H = max(*( + [self.label_height+2*BLOCK_LABEL_PADDING] + [2*PORT_BORDER_SEPARATION + \ + sum([port.H + PORT_SEPARATION for port in ports]) - PORT_SEPARATION + for ports in (self.get_sources(), self.get_sinks())] + )) + 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_ports()) + + 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) + layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self)) + self.label_width, self.label_height = layout.get_pixel_size() + #display the params + for param in filter(lambda p: p.get_hide() not in ('all', 'part'), self.get_params()): + 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 = self.get_parent().new_pixmap(width, height) + gc = pixmap.new_gc() + gc.set_foreground(self._bg_color) + pixmap.draw_rectangle(gc, True, 0, 0, width, height) + #draw the layouts + h_off = 0 + for i,layout in enumerate(layouts): + w,h = layout.get_pixel_size() + if i == 0: w_off = (width-w)/2 + else: w_off = 0 + pixmap.draw_layout(gc, w_off, h_off, layout) + h_off = h + h_off + LABEL_SEPARATION + #create vertical and horizontal 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)) + map(lambda p: p._create_labels(), self.get_ports()) + + def draw(self, gc, window): + """ + Draw the signal block with label and inputs/outputs. + @param gc the graphics context + @param window the gtk window to draw on + """ + x, y = self.get_coordinate() + #draw main block + Element.draw( + self, gc, window, bg_color=self._bg_color, + border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or Colors.BORDER_COLOR, + ) + #draw label image + if self.is_horizontal(): + window.draw_image(gc, self.horizontal_label, 0, 0, x+BLOCK_LABEL_PADDING, y+(self.H-self.label_height)/2, -1, -1) + elif self.is_vertical(): + window.draw_image(gc, self.vertical_label, 0, 0, x+(self.H-self.label_height)/2, y+BLOCK_LABEL_PADDING, -1, -1) + #draw ports + for port in self.get_ports(): port.draw(gc, window) + + def what_is_selected(self, coor, coor_m=None): + """ + Get the element that is selected. + @param coor the (x,y) tuple + @param coor_m the (x_m, y_m) tuple + @return this block, a port, or None + """ + for port in self.get_ports(): + port_selected = port.what_is_selected(coor, coor_m) + if port_selected: return port_selected + return Element.what_is_selected(self, coor, coor_m) diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py new file mode 100644 index 00000000..379c4a6a --- /dev/null +++ b/grc/gui/BlockTreeWindow.py @@ -0,0 +1,168 @@ +""" +Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from Constants import DEFAULT_BLOCKS_WINDOW_WIDTH, DND_TARGETS +import Utils +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +NAME_INDEX = 0 +KEY_INDEX = 1 +DOC_INDEX = 2 + +class BlockTreeWindow(gtk.VBox): + """The block selection panel.""" + + def __init__(self, platform, get_flow_graph): + """ + BlockTreeWindow constructor. + Create a tree view of the possible blocks in the platform. + The tree view nodes will be category names, the leaves will be block names. + A mouse double click or button press action will trigger the add block event. + @param platform the particular platform will all block prototypes + @param get_flow_graph get the selected flow graph + """ + gtk.VBox.__init__(self) + self.platform = platform + self.get_flow_graph = get_flow_graph + #make the tree model for holding blocks + self.treestore = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) + self.treeview = gtk.TreeView(self.treestore) + self.treeview.set_enable_search(False) #disable pop up search box + self.treeview.add_events(gtk.gdk.BUTTON_PRESS_MASK) + self.treeview.connect('button_press_event', self._handle_mouse_button_press) + selection = self.treeview.get_selection() + selection.set_mode('single') + selection.connect('changed', self._handle_selection_change) + renderer = gtk.CellRendererText() + column = gtk.TreeViewColumn('Blocks', renderer, text=NAME_INDEX) + self.treeview.append_column(column) + #try to enable the tooltips (available in pygtk 2.12 and above) + try: self.treeview.set_tooltip_column(DOC_INDEX) + except: pass + #setup drag and drop + self.treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, DND_TARGETS, gtk.gdk.ACTION_COPY) + self.treeview.connect('drag-data-get', self._handle_drag_get_data) + #make the scrolled window to hold the tree view + scrolled_window = gtk.ScrolledWindow() + scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + scrolled_window.add_with_viewport(self.treeview) + scrolled_window.set_size_request(DEFAULT_BLOCKS_WINDOW_WIDTH, -1) + self.pack_start(scrolled_window) + #add button + self.add_button = gtk.Button(None, gtk.STOCK_ADD) + self.add_button.connect('clicked', self._handle_add_button) + self.pack_start(self.add_button, False) + #map categories to iters, automatic mapping for root + self._categories = {tuple(): None} + #add blocks and categories + self.platform.load_block_tree(self) + #initialize + self._update_add_button() + + ############################################################ + ## Block Tree Methods + ############################################################ + def add_block(self, category, block=None): + """ + Add a block with category to this selection window. + Add only the category when block is None. + @param category the category list or path string + @param block the block object or None + """ + if isinstance(category, str): category = category.split('/') + category = tuple(filter(lambda x: x, category)) #tuple is hashable + #add category and all sub categories + for i, cat_name in enumerate(category): + sub_category = category[:i+1] + if sub_category not in self._categories: + iter = self.treestore.insert_before(self._categories[sub_category[:-1]], None) + self.treestore.set_value(iter, NAME_INDEX, '[ %s ]'%cat_name) + self.treestore.set_value(iter, KEY_INDEX, '') + self.treestore.set_value(iter, DOC_INDEX, Utils.xml_encode('Category: %s'%cat_name)) + self._categories[sub_category] = iter + #add block + if block is None: return + iter = self.treestore.insert_before(self._categories[category], None) + self.treestore.set_value(iter, NAME_INDEX, block.get_name()) + self.treestore.set_value(iter, KEY_INDEX, block.get_key()) + self.treestore.set_value(iter, DOC_INDEX, Utils.xml_encode(block.get_doc() or 'undocumented')) + + ############################################################ + ## 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_drag_get_data(self, widget, drag_context, selection_data, info, time): + """ + Handle a drag and drop by setting the key to the selection object. + This will call the destination handler for drag and drop. + Only call set when the key is valid to ignore DND from categories. + """ + key = self._get_selected_block_key() + if key: selection_data.set(selection_data.target, 8, key) + + def _handle_mouse_button_press(self, widget, event): + """ + Handle the mouse button press. + If a left double click is detected, call add selected block. + """ + if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS: + self._add_selected_block() + + def _handle_selection_change(self, selection): + """ + Handle a selection change in the tree view. + If a selection changes, set the add button sensitive. + """ + self._update_add_button() + + def _handle_add_button(self, widget): + """ + Handle the add button clicked signal. + Call add selected block. + """ + self._add_selected_block() diff --git a/grc/gui/Colors.py b/grc/gui/Colors.py new file mode 100644 index 00000000..f0b989b3 --- /dev/null +++ b/grc/gui/Colors.py @@ -0,0 +1,37 @@ +""" +Copyright 2008 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import pygtk +pygtk.require('2.0') +import gtk + +_COLORMAP = gtk.gdk.colormap_get_system() #create all of the colors +def get_color(color_code): return _COLORMAP.alloc_color(color_code, True, True) + +HIGHLIGHT_COLOR = get_color('#00FFFF') +BORDER_COLOR = get_color('black') +#flow graph color constants +FLOWGRAPH_BACKGROUND_COLOR = get_color('#FFF9FF') +#block color constants +BLOCK_ENABLED_COLOR = get_color('#F1ECFF') +BLOCK_DISABLED_COLOR = get_color('#CCCCCC') +#connection color constants +CONNECTION_ENABLED_COLOR = get_color('black') +CONNECTION_DISABLED_COLOR = get_color('#999999') +CONNECTION_ERROR_COLOR = get_color('red') diff --git a/grc/gui/Connection.py b/grc/gui/Connection.py new file mode 100644 index 00000000..013bcb00 --- /dev/null +++ b/grc/gui/Connection.py @@ -0,0 +1,140 @@ +""" +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. + The connection has 2 parts, the arrow and the wire. + The coloring of the arrow and wire exposes the status of 3 states: + enabled/disabled, valid/invalid, highlighted/non-highlighted. + The wire coloring exposes the enabled and highlighted states. + The arrow coloring exposes the enabled and valid states. + """ + + def 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() + if not self.get_enabled(): self._arrow_color = Colors.CONNECTION_DISABLED_COLOR + elif not self.is_valid(): self._arrow_color = Colors.CONNECTION_ERROR_COLOR + else: self._arrow_color = Colors.CONNECTION_ENABLED_COLOR + + def _update_after_move(self): + """Calculate coordinates.""" + self.clear() + #source connector + source = self.get_source() + X, Y = source.get_connector_coordinate() + x1, y1 = self.x1 + X, self.y1 + Y + self.add_line((x1, y1), (X, Y)) + #sink connector + sink = self.get_sink() + X, Y = sink.get_connector_coordinate() + x2, y2 = self.x2 + X, self.y2 + Y + self.add_line((x2, y2), (X, Y)) + #adjust arrow + self._arrow = [(x+X, y+Y) for x,y in self.arrow] + #add the horizontal and vertical lines in this connection + if abs(source.get_connector_direction() - sink.get_connector_direction()) == 180: + #2 possible point sets to create a 3-line connector + mid_x, mid_y = (x1 + x2)/2.0, (y1 + y2)/2.0 + points = [((mid_x, y1), (mid_x, y2)), ((x1, mid_y), (x2, mid_y))] + #source connector -> points[0][0] should be in the direction of source (if possible) + if Utils.get_angle_from_coordinates((x1, y1), points[0][0]) != source.get_connector_direction(): points.reverse() + #points[0][0] -> sink connector should not be in the direction of sink + if Utils.get_angle_from_coordinates(points[0][0], (x2, y2)) == sink.get_connector_direction(): points.reverse() + #points[0][0] -> source connector should not be in the direction of source + if Utils.get_angle_from_coordinates(points[0][0], (x1, y1)) == source.get_connector_direction(): points.reverse() + #create 3-line connector + p1, p2 = map(int, points[0][0]), map(int, points[0][1]) + self.add_line((x1, y1), p1) + self.add_line(p1, p2) + self.add_line((x2, y2), p2) + else: + #2 possible points to create a right-angled connector + points = [(x1, y2), (x2, y1)] + #source connector -> points[0] should be in the direction of source (if possible) + if Utils.get_angle_from_coordinates((x1, y1), points[0]) != source.get_connector_direction(): points.reverse() + #points[0] -> sink connector should not be in the direction of sink + if Utils.get_angle_from_coordinates(points[0], (x2, y2)) == sink.get_connector_direction(): points.reverse() + #points[0] -> source connector should not be in the direction of source + if Utils.get_angle_from_coordinates(points[0], (x1, y1)) == source.get_connector_direction(): points.reverse() + #create right-angled connector + self.add_line((x1, y1), points[0]) + self.add_line((x2, y2), points[0]) + + def draw(self, gc, window): + """ + Draw the connection. + @param gc the graphics context + @param window the gtk window to draw on + """ + sink = self.get_sink() + source = self.get_source() + #check for changes + if self._sink_rot != sink.get_rotation() or self._source_rot != source.get_rotation(): self.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 + if self.is_highlighted(): border_color = Colors.HIGHLIGHT_COLOR + elif self.get_enabled(): border_color = Colors.CONNECTION_ENABLED_COLOR + else: border_color = Colors.CONNECTION_DISABLED_COLOR + Element.draw(self, gc, window, bg_color=None, border_color=border_color) + #draw arrow on sink port + gc.set_foreground(self._arrow_color) + window.draw_polygon(gc, True, self._arrow) diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py new file mode 100644 index 00000000..7fabcfc0 --- /dev/null +++ b/grc/gui/Constants.py @@ -0,0 +1,83 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import pygtk +pygtk.require('2.0') +import gtk +import os + +##default path for the open/save dialogs +DEFAULT_FILE_PATH = os.getcwd() + +##file extensions +IMAGE_FILE_EXTENSION = '.png' + +##name for new/unsaved flow graphs +NEW_FLOGRAPH_TITLE = 'untitled' + +##main window constraints +MIN_WINDOW_WIDTH = 600 +MIN_WINDOW_HEIGHT = 400 +##dialog constraints +MIN_DIALOG_WIDTH = 500 +MIN_DIALOG_HEIGHT = 500 +##default sizes +DEFAULT_BLOCKS_WINDOW_WIDTH = 100 +DEFAULT_REPORTS_WINDOW_WIDTH = 100 + +##The size of the state saving cache in the flow graph (for undo/redo functionality) +STATE_CACHE_SIZE = 42 + +##Shared targets for drag and drop of blocks +DND_TARGETS = [('STRING', gtk.TARGET_SAME_APP, 0)] + +#label constraint dimensions +LABEL_SEPARATION = 3 +BLOCK_LABEL_PADDING = 7 +PORT_LABEL_PADDING = 2 + +#port constraint dimensions +PORT_SEPARATION = 17 +PORT_BORDER_SEPARATION = 9 +PORT_MIN_WIDTH = 20 + +#minimal length of connector +CONNECTOR_EXTENSION_MINIMAL = 11 + +#increment length for connector +CONNECTOR_EXTENSION_INCREMENT = 11 + +#connection arrow dimensions +CONNECTOR_ARROW_BASE = 13 +CONNECTOR_ARROW_HEIGHT = 17 + +#possible rotations in degrees +POSSIBLE_ROTATIONS = (0, 90, 180, 270) + +#How close can the mouse get to the window border before mouse events are ignored. +BORDER_PROXIMITY_SENSITIVITY = 50 + +#How close the mouse can get to the edge of the visible window before scrolling is invoked. +SCROLL_PROXIMITY_SENSITIVITY = 30 + +#When the window has to be scrolled, move it this distance in the required direction. +SCROLL_DISTANCE = 15 + +#How close the mouse click can be to a line and register a connection select. +LINE_SELECT_SENSITIVITY = 5 diff --git a/grc/gui/Dialogs.py b/grc/gui/Dialogs.py new file mode 100644 index 00000000..8d764e28 --- /dev/null +++ b/grc/gui/Dialogs.py @@ -0,0 +1,105 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import pygtk +pygtk.require('2.0') +import gtk +import Preferences +import Utils + +class TextDisplay(gtk.TextView): + """A non editable gtk text view.""" + + def __init__(self, text=''): + """ + TextDisplay constructor. + @param text the text to display (string) + """ + text_buffer = gtk.TextBuffer() + text_buffer.set_text(text) + self.set_text = text_buffer.set_text + self.insert = lambda line: text_buffer.insert(text_buffer.get_end_iter(), line) + gtk.TextView.__init__(self, text_buffer) + self.set_editable(False) + self.set_cursor_visible(False) + self.set_wrap_mode(gtk.WRAP_WORD_CHAR) + +def MessageDialogHelper(type, buttons, title=None, markup=None): + """ + Create a modal message dialog and run it. + @param type the type of message: gtk.MESSAGE_INFO, gtk.MESSAGE_WARNING, gtk.MESSAGE_QUESTION or gtk.MESSAGE_ERROR + @param buttons the predefined set of buttons to use: + gtk.BUTTONS_NONE, gtk.BUTTONS_OK, gtk.BUTTONS_CLOSE, gtk.BUTTONS_CANCEL, gtk.BUTTONS_YES_NO, gtk.BUTTONS_OK_CANCEL + @param tittle the title of the window (string) + @param markup the message text with pango markup + @return the gtk response from run() + """ + message_dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, type, buttons) + if title: message_dialog.set_title(title) + if markup: message_dialog.set_markup(markup) + response = message_dialog.run() + message_dialog.destroy() + return response + +class AboutDialog(gtk.AboutDialog): + """A cute little about dialog.""" + + def __init__(self, platform): + """AboutDialog constructor.""" + gtk.AboutDialog.__init__(self) + self.set_name(platform.get_name()) + self.set_version(platform.get_version()) + self.set_license(platform.get_license()) + self.set_copyright(platform.get_license().splitlines()[0]) + self.set_website(platform.get_website()) + self.run() + self.destroy() + +def HelpDialog(): MessageDialogHelper( + type=gtk.MESSAGE_INFO, + buttons=gtk.BUTTONS_CLOSE, + title='Help', + markup="""\ +Usage Tips + +Add block: drag and drop or double click a block in the block selection window. +Rotate block: Select a block, press left/right on the keyboard. +Change type: Select a block, press up/down on the keyboard. +Edit parameters: double click on a block in the flow graph. +Make connection: click on the source port of one block, then click on the sink port of another block. +Remove connection: select the connection and press delete, or drag the connection. + +* See the menu for other keyboard shortcuts.""") + +COLORS_DIALOG_MARKUP_TMPL = """\ +Color Mapping + +#if $colors + #set $max_len = max([len(color[0]) for color in $colors]) + 10 + #for $title, $color_spec in $colors +$($encode($title).center($max_len)) + #end for +#end if +""" + +def ColorsDialog(platform): MessageDialogHelper( + type=gtk.MESSAGE_INFO, + buttons=gtk.BUTTONS_CLOSE, + title='Colors', + markup=Utils.parse_template(COLORS_DIALOG_MARKUP_TMPL, colors=platform.get_colors())) diff --git a/grc/gui/DrawingArea.py b/grc/gui/DrawingArea.py new file mode 100644 index 00000000..6f90049c --- /dev/null +++ b/grc/gui/DrawingArea.py @@ -0,0 +1,126 @@ +""" +Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import pygtk +pygtk.require('2.0') +import gtk +from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT, DND_TARGETS + +class DrawingArea(gtk.DrawingArea): + """ + DrawingArea is the gtk pixel map that graphical elements may draw themselves on. + The drawing area also responds to mouse and key events. + """ + + def __init__(self, flow_graph): + """ + DrawingArea contructor. + Connect event handlers. + @param main_window the main_window containing all flow graphs + """ + self.ctrl_mask = False + self._flow_graph = flow_graph + gtk.DrawingArea.__init__(self) + self.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) + self.connect('realize', self._handle_window_realize) + self.connect('configure-event', self._handle_window_configure) + self.connect('expose-event', self._handle_window_expose) + self.connect('motion-notify-event', self._handle_mouse_motion) + self.connect('button-press-event', self._handle_mouse_button_press) + self.connect('button-release-event', self._handle_mouse_button_release) + self.add_events( + gtk.gdk.BUTTON_PRESS_MASK | \ + gtk.gdk.POINTER_MOTION_MASK | \ + gtk.gdk.BUTTON_RELEASE_MASK | \ + gtk.gdk.LEAVE_NOTIFY_MASK | \ + gtk.gdk.ENTER_NOTIFY_MASK + ) + #setup drag and drop + self.drag_dest_set(gtk.DEST_DEFAULT_ALL, DND_TARGETS, gtk.gdk.ACTION_COPY) + self.connect('drag-data-received', self._handle_drag_data_received) + #setup the focus flag + self._focus_flag = False + self.get_focus_flag = lambda: self._focus_flag + def _handle_focus_event(widget, event, focus_flag): self._focus_flag = focus_flag + self.connect('leave-notify-event', _handle_focus_event, False) + self.connect('enter-notify-event', _handle_focus_event, True) + + def new_pixmap(self, width, height): return gtk.gdk.Pixmap(self.window, width, height, -1) + + ########################################################################## + ## Handlers + ########################################################################## + def _handle_drag_data_received(self, widget, drag_context, x, y, selection_data, info, time): + """ + Handle a drag and drop by adding a block at the given coordinate. + """ + self._flow_graph.add_new_block(selection_data.data, (x, y)) + + def _handle_mouse_button_press(self, widget, event): + """ + Forward button click information to the flow graph. + """ + self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK + self._flow_graph.handle_mouse_button_press( + left_click=(event.button == 1), + double_click=(event.type == gtk.gdk._2BUTTON_PRESS), + coordinate=(event.x, event.y), + ) + + 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._flow_graph.handle_mouse_button_release( + left_click=(event.button == 1), + coordinate=(event.x, event.y), + ) + + def _handle_mouse_motion(self, widget, event): + """ + Forward mouse motion information to the flow graph. + """ + self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK + self._flow_graph.handle_mouse_motion( + coordinate=(event.x, event.y), + ) + + def _handle_window_realize(self, widget): + """ + Called when the window is realized. + Update the flowgraph, which calls new pixmap. + """ + self._flow_graph.update() + + def _handle_window_configure(self, widget, event): + """ + Called when the window is resized. + Create a new pixmap for background buffer. + """ + self._pixmap = self.new_pixmap(*self.get_size_request()) + + def _handle_window_expose(self, widget, event): + """ + Called when window is exposed, or queue_draw is called. + Double buffering: draw to pixmap, then draw pixmap to window. + """ + gc = self.window.new_gc() + self._flow_graph.draw(gc, self._pixmap) + self.window.draw_drawable(gc, self._pixmap, 0, 0, 0, 0, -1, -1) diff --git a/grc/gui/Element.py b/grc/gui/Element.py new file mode 100644 index 00000000..31519172 --- /dev/null +++ b/grc/gui/Element.py @@ -0,0 +1,226 @@ +""" +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 Constants import LINE_SELECT_SENSITIVITY +from Constants import POSSIBLE_ROTATIONS + +class Element(object): + """ + GraphicalElement is the base class for all graphical elements. + It contains an X,Y coordinate, a list of rectangular areas that the element occupies, + and methods to detect selection of those areas. + """ + + def __init__(self, *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 draw(self, gc, window, border_color, bg_color): + """ + Draw in the given window. + @param gc the graphics context + @param window the gtk window to draw on + @param border_color the color for lines and rectangle borders + @param bg_color the color for the inside of the rectangle + """ + X,Y = self.get_coordinate() + for (rX,rY),(W,H) in self.areas_dict[self.get_rotation()]: + aX = X + rX + aY = Y + rY + gc.set_foreground(bg_color) + window.draw_rectangle(gc, True, aX, aY, W, H) + gc.set_foreground(border_color) + window.draw_rectangle(gc, False, aX, aY, W, H) + for (x1, y1),(x2, y2) in self.lines_dict[self.get_rotation()]: + gc.set_foreground(border_color) + window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2) + + def rotate(self, rotation): + """ + Rotate all of the areas by 90 degrees. + @param rotation multiple of 90 degrees + """ + self.set_rotation((self.get_rotation() + rotation)%360) + + def clear(self): + """Empty the lines and areas.""" + self.areas_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-LINE_SELECT_SENSITIVITY, x2+LINE_SELECT_SENSITIVITY + if y1 == y2: y1, y2 = y1-LINE_SELECT_SENSITIVITY, y2+LINE_SELECT_SENSITIVITY + if in_between(x, x1, x2) and in_between(y, y1, y2): return self + return None + + def get_rotation(self): + """ + Get the rotation in degrees. + @return the rotation + """ + return self.rotation + + def set_rotation(self, rotation): + """ + Set the rotation in degrees. + @param rotation the rotation""" + if rotation not in POSSIBLE_ROTATIONS: + raise Exception('"%s" is not one of the possible rotations: (%s)'%(rotation, POSSIBLE_ROTATIONS)) + self.rotation = rotation + + def update(self): + """Do nothing for the update. Dummy method.""" + pass diff --git a/grc/gui/FileDialogs.py b/grc/gui/FileDialogs.py new file mode 100644 index 00000000..3b210c33 --- /dev/null +++ b/grc/gui/FileDialogs.py @@ -0,0 +1,175 @@ +""" +Copyright 2007 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import pygtk +pygtk.require('2.0') +import gtk +from Dialogs import MessageDialogHelper +from Constants import \ + DEFAULT_FILE_PATH, IMAGE_FILE_EXTENSION, \ + NEW_FLOGRAPH_TITLE +import Preferences +from os import path +import Utils + +################################################## +# Constants +################################################## +OPEN_FLOW_GRAPH = 'open flow graph' +SAVE_FLOW_GRAPH = 'save flow graph' +SAVE_IMAGE = 'save image' + +FILE_OVERWRITE_MARKUP_TMPL="""\ +File $encode($filename) Exists!\nWould you like to overwrite the existing file?""" + +FILE_DNE_MARKUP_TMPL="""\ +File $encode($filename) Does not Exist!""" + +################################################## +# File Filters +################################################## +##the filter for flow graph files +def get_flow_graph_files_filter(): + filter = gtk.FileFilter() + filter.set_name('Flow Graph Files') + filter.add_pattern('*'+Preferences.file_extension()) + return filter + +##the filter for image files +def get_image_files_filter(): + filter = gtk.FileFilter() + filter.set_name('Image Files') + filter.add_pattern('*'+IMAGE_FILE_EXTENSION) + return filter + +##the filter for all files +def get_all_files_filter(): + filter = gtk.FileFilter() + filter.set_name('All Files') + filter.add_pattern('*') + return filter + +################################################## +# File Dialogs +################################################## +class FileDialogHelper(gtk.FileChooserDialog): + """ + A wrapper class for the gtk file chooser dialog. + Implement a file chooser dialog with only necessary parameters. + """ + + def __init__(self, action, title): + """ + FileDialogHelper contructor. + Create a save or open dialog with cancel and ok buttons. + Use standard settings: no multiple selection, local files only, and the * filter. + @param action gtk.FILE_CHOOSER_ACTION_OPEN or gtk.FILE_CHOOSER_ACTION_SAVE + @param title the title of the dialog (string) + """ + ok_stock = {gtk.FILE_CHOOSER_ACTION_OPEN : 'gtk-open', gtk.FILE_CHOOSER_ACTION_SAVE : 'gtk-save'}[action] + gtk.FileChooserDialog.__init__(self, title, None, action, ('gtk-cancel', gtk.RESPONSE_CANCEL, ok_stock, gtk.RESPONSE_OK)) + self.set_select_multiple(False) + self.set_local_only(True) + self.add_filter(get_all_files_filter()) + +class FileDialog(FileDialogHelper): + """A dialog box to save or open flow graph files. This is a base class, do not use.""" + + def __init__(self, current_file_path=''): + """ + FileDialog constructor. + @param current_file_path the current directory or path to the open flow graph + """ + if not current_file_path: current_file_path = path.join(DEFAULT_FILE_PATH, NEW_FLOGRAPH_TITLE + Preferences.file_extension()) + if self.type == OPEN_FLOW_GRAPH: + FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_OPEN, 'Open a Flow Graph from a File...') + self.add_and_set_filter(get_flow_graph_files_filter()) + self.set_select_multiple(True) + elif self.type == SAVE_FLOW_GRAPH: + FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save a Flow Graph to a File...') + self.add_and_set_filter(get_flow_graph_files_filter()) + self.set_current_name(path.basename(current_file_path)) #show the current filename + elif self.type == SAVE_IMAGE: + FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save a Flow Graph Screen Shot...') + self.add_and_set_filter(get_image_files_filter()) + current_file_path = current_file_path + IMAGE_FILE_EXTENSION + self.set_current_name(path.basename(current_file_path)) #show the current filename + self.set_current_folder(path.dirname(current_file_path)) #current directory + + def add_and_set_filter(self, filter): + """ + Add the gtk file filter to the list of filters and set it as the default file filter. + @param filter a gtk file filter. + """ + self.add_filter(filter) + self.set_filter(filter) + + def get_rectified_filename(self): + """ + Run the dialog and get the filename. + If this is a save dialog and the file name is missing the extension, append the file extension. + If the file name with the extension already exists, show a overwrite dialog. + If this is an open dialog, return a list of filenames. + @return the complete file path + """ + if gtk.FileChooserDialog.run(self) != gtk.RESPONSE_OK: return None #response was cancel + ############################################# + # Handle Save Dialogs + ############################################# + if self.type in (SAVE_FLOW_GRAPH, SAVE_IMAGE): + filename = self.get_filename() + extension = { + SAVE_FLOW_GRAPH: Preferences.file_extension(), + SAVE_IMAGE: IMAGE_FILE_EXTENSION, + }[self.type] + #append the missing file extension if the filter matches + if path.splitext(filename)[1].lower() != extension: filename += extension + self.set_current_name(path.basename(filename)) #show the filename with extension + if path.exists(filename): #ask the user to confirm overwrite + if MessageDialogHelper( + gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, 'Confirm Overwrite!', + Utils.parse_template(FILE_OVERWRITE_MARKUP_TMPL, filename=filename), + ) == gtk.RESPONSE_NO: return self.get_rectified_filename() + return filename + ############################################# + # Handle Open Dialogs + ############################################# + elif self.type in (OPEN_FLOW_GRAPH,): + filenames = self.get_filenames() + for filename in filenames: + if not path.exists(filename): #show a warning and re-run + MessageDialogHelper( + gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, 'Cannot Open!', + Utils.parse_template(FILE_DNE_MARKUP_TMPL, filename=filename), + ) + return self.get_rectified_filename() + return filenames + + def run(self): + """ + Get the filename and destroy the dialog. + @return the filename or None if a close/cancel occured. + """ + filename = self.get_rectified_filename() + self.destroy() + return filename + +class OpenFlowGraphFileDialog(FileDialog): type = OPEN_FLOW_GRAPH +class SaveFlowGraphFileDialog(FileDialog): type = SAVE_FLOW_GRAPH +class SaveImageFileDialog(FileDialog): type = SAVE_IMAGE diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py new file mode 100644 index 00000000..26544faa --- /dev/null +++ b/grc/gui/FlowGraph.py @@ -0,0 +1,489 @@ +""" +Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from Constants import SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE +from Actions import \ + ELEMENT_CREATE, ELEMENT_SELECT, \ + BLOCK_PARAM_MODIFY, BLOCK_MOVE, \ + ELEMENT_DELETE +import Colors +import Utils +from Element import Element +from .. base import FlowGraph as _FlowGraph +import pygtk +pygtk.require('2.0') +import gtk +import random +import Messages + +class FlowGraph(Element): + """ + FlowGraph is the data structure to store graphical signal blocks, + graphical inputs and outputs, + and the connections between inputs and outputs. + """ + + def __init__(self, *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.press_coor = (0, 0) + #selected ports + self._old_selected_port = None + self._new_selected_port = None + + ########################################################################### + # Access Drawing Area + ########################################################################### + def get_drawing_area(self): return self.drawing_area + def queue_draw(self): self.get_drawing_area().queue_draw() + def get_size(self): return self.get_drawing_area().get_size_request() + def set_size(self, *args): self.get_drawing_area().set_size_request(*args) + def get_scroll_pane(self): return self.drawing_area.get_parent() + def get_ctrl_mask(self): return self.drawing_area.ctrl_mask + def new_pixmap(self, *args): return self.get_drawing_area().new_pixmap(*args) + + def add_new_block(self, key, coor=None): + """ + Add a block of the given key to this flow graph. + @param key the block key + @param coor an optional coordinate or None for random + """ + id = self._get_unique_id(key) + #calculate the position coordinate + h_adj = self.get_scroll_pane().get_hadjustment() + v_adj = self.get_scroll_pane().get_vadjustment() + if coor is None: coor = ( + int(random.uniform(.25, .75)*h_adj.page_size + h_adj.get_value()), + int(random.uniform(.25, .75)*v_adj.page_size + v_adj.get_value()), + ) + #get the new block + block = self.get_new_block(key) + block.set_coordinate(coor) + block.set_rotation(0) + block.get_param('id').set_value(id) + 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.find('key') + if block_key == 'options': continue + block = self.get_new_block(block_key) + selected.add(block) + #set params + params_n = block_n.findall('param') + for param_n in params_n: + param_key = param_n.find('key') + param_value = param_n.find('value') + #setup id parameter + if param_key == 'id': + old_id2block[param_value] = block + #if the block id is not unique, get a new block id + if param_value in [block.get_id() for block in self.get_blocks()]: + param_value = self._get_unique_id(param_value) + #set value to key + block.get_param(param_key).set_value(param_value) + #move block to offset coordinate + block.move((x_off, y_off)) + #update before creating connections + self.update() + #create connections + for connection_n in connections_n: + source = old_id2block[connection_n.find('source_block_id')].get_source(connection_n.find('source_key')) + sink = old_id2block[connection_n.find('sink_block_id')].get_sink(connection_n.find('sink_key')) + self.connect(source, sink) + #set all pasted elements selected + for block in selected: selected = selected.union(set(block.get_connections())) + self._selected_elements = list(selected) + + ########################################################################### + # Modify Selected + ########################################################################### + def type_controller_modify_selected(self, direction): + """ + Change the registered type controller for the selected signal blocks. + @param direction +1 or -1 + @return true for change + """ + return any([sb.type_controller_modify(direction) for sb in self.get_selected_blocks()]) + + def port_controller_modify_selected(self, direction): + """ + Change port controller for the selected signal blocks. + @param direction +1 or -1 + @return true for changed + """ + return any([sb.port_controller_modify(direction) for sb in self.get_selected_blocks()]) + + def enable_selected(self, enable): + """ + Enable/disable the selected blocks. + @param enable true to enable + @return true if changed + """ + changed = False + for selected_block in self.get_selected_blocks(): + if selected_block.get_enabled() != enable: + selected_block.set_enabled(enable) + changed = True + return changed + + def move_selected(self, delta_coordinate): + """ + Move the element and by the change in coordinates. + @param delta_coordinate the change in coordinates + """ + for selected_block in self.get_selected_blocks(): + selected_block.move(delta_coordinate) + self.element_moved = True + + def rotate_selected(self, rotation): + """ + Rotate the selected blocks by multiples of 90 degrees. + @param rotation the rotation in degrees + @return true if changed, otherwise false. + """ + if not self.get_selected_blocks(): return False + #initialize min and max coordinates + min_x, min_y = self.get_selected_block().get_coordinate() + max_x, max_y = self.get_selected_block().get_coordinate() + #rotate each selected block, and find min/max coordinate + for selected_block in self.get_selected_blocks(): + selected_block.rotate(rotation) + #update the min/max coordinate + x, y = selected_block.get_coordinate() + min_x, min_y = min(min_x, x), min(min_y, y) + max_x, max_y = max(max_x, x), max(max_y, y) + #calculate center point of slected blocks + ctr_x, ctr_y = (max_x + min_x)/2, (max_y + min_y)/2 + #rotate the blocks around the center point + for selected_block in self.get_selected_blocks(): + x, y = selected_block.get_coordinate() + x, y = Utils.get_rotated_coordinate((x - ctr_x, y - ctr_y), rotation) + selected_block.set_coordinate((x + ctr_x, y + ctr_y)) + return True + + def remove_selected(self): + """ + Remove selected elements + @return true if changed. + """ + changed = False + for selected_element in self.get_selected_elements(): + self.remove_element(selected_element) + changed = True + return changed + + def draw(self, gc, window): + """ + Draw the background and grid if enabled. + Draw all of the elements in this flow graph onto the pixmap. + Draw the pixmap to the drawable window of this flow graph. + """ + W,H = self.get_size() + #draw the background + gc.set_foreground(Colors.FLOWGRAPH_BACKGROUND_COLOR) + window.draw_rectangle(gc, True, 0, 0, W, H) + #draw multi select rectangle + if self.mouse_pressed and (not self.get_selected_elements() or self.get_ctrl_mask()): + #coordinates + x1, y1 = self.press_coor + x2, y2 = self.get_coordinate() + #calculate top-left coordinate and width/height + x, y = int(min(x1, x2)), int(min(y1, y2)) + w, h = int(abs(x1 - x2)), int(abs(y1 - y2)) + #draw + gc.set_foreground(Colors.HIGHLIGHT_COLOR) + window.draw_rectangle(gc, True, x, y, w, h) + gc.set_foreground(Colors.BORDER_COLOR) + window.draw_rectangle(gc, False, x, y, w, h) + #draw blocks on top of connections + for element in self.get_connections() + self.get_blocks(): + element.draw(gc, window) + #draw selected blocks on top of selected connections + for selected_element in self.get_selected_connections() + self.get_selected_blocks(): + selected_element.draw(gc, window) + + def update_selected(self): + """ + Remove deleted elements from the selected elements list. + Update highlighting so only the selected are highlighted. + """ + selected_elements = self.get_selected_elements() + elements = self.get_elements() + #remove deleted elements + for selected in selected_elements: + if selected in elements: continue + selected_elements.remove(selected) + #update highlighting + for element in elements: + element.set_highlighted(element in selected_elements) + + def update(self): + """ + Call update on all elements. + """ + self.validate() + for element in self.get_elements(): element.update() + + ########################################################################## + ## Get Selected + ########################################################################## + def unselect(self): + """ + Set selected elements to an empty set. + """ + self._selected_elements = [] + + def what_is_selected(self, coor, coor_m=None): + """ + What is selected? + At the given coordinate, return the elements found to be selected. + If coor_m is unspecified, return a list of only the first element found to be selected: + Iterate though the elements backwards since top elements are at the end of the list. + If an element is selected, place it at the end of the list so that is is drawn last, + and hence on top. Update the selected port information. + @param coor the coordinate of the mouse click + @param coor_m the coordinate for multi select + @return the selected blocks and connections or an empty list + """ + selected_port = None + selected = set() + #check the elements + for element in reversed(self.get_elements()): + selected_element = element.what_is_selected(coor, coor_m) + if not selected_element: continue + #update the selected port information + if selected_element.is_port(): + if not coor_m: selected_port = selected_element + selected_element = selected_element.get_parent() + selected.add(selected_element) + #place at the end of the list + self.get_elements().remove(element) + self.get_elements().append(element) + #single select mode, break + if not coor_m: break + #update selected ports + self._old_selected_port = self._new_selected_port + self._new_selected_port = selected_port + return list(selected) + + def get_selected_connections(self): + """ + Get a group of selected connections. + @return sub set of connections in this flow graph + """ + selected = set() + for selected_element in self.get_selected_elements(): + if selected_element.is_connection(): selected.add(selected_element) + return list(selected) + + def get_selected_blocks(self): + """ + Get a group of selected blocks. + @return sub set of blocks in this flow graph + """ + selected = set() + for selected_element in self.get_selected_elements(): + if selected_element.is_block(): selected.add(selected_element) + return list(selected) + + def get_selected_block(self): + """ + Get the selected block when a block or port is selected. + @return a block or None + """ + return self.get_selected_blocks() and self.get_selected_blocks()[0] or None + + def get_selected_elements(self): + """ + Get the group of selected elements. + @return sub set of elements in this flow graph + """ + return self._selected_elements + + def get_selected_element(self): + """ + Get the selected element. + @return a block, port, or connection or None + """ + return self.get_selected_elements() and self.get_selected_elements()[0] or None + + def update_selected_elements(self): + """ + Update the selected elements. + The update behavior depends on the state of the mouse button. + When the mouse button pressed the selection will change when + the control mask is set or the new selection is not in the current group. + When the mouse button is released the selection will change when + the mouse has moved and the control mask is set or the current group is empty. + Attempt to make a new connection if the old and ports are filled. + If the control mask is set, merge with the current elements. + """ + selected_elements = None + if self.mouse_pressed: + new_selections = self.what_is_selected(self.get_coordinate()) + #update the selections if the new selection is not in the current selections + #allows us to move entire selected groups of elements + if self.get_ctrl_mask() or not ( + new_selections and new_selections[0] in self.get_selected_elements() + ): selected_elements = new_selections + else: #called from a mouse release + if not self.element_moved and (not self.get_selected_elements() or self.get_ctrl_mask()): + selected_elements = self.what_is_selected(self.get_coordinate(), self.press_coor) + #this selection and the last were ports, try to connect them + if self._old_selected_port and self._new_selected_port and \ + self._old_selected_port is not self._new_selected_port: + try: + self.connect(self._old_selected_port, self._new_selected_port) + 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 + if double_click: self.unselect() + self.update_selected_elements() + #double click detected, bring up params dialog if possible + if double_click and self.get_selected_block(): + self.mouse_pressed = False + 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: + self.handle_states(BLOCK_MOVE) + self.element_moved = False + self.update_selected_elements() + + def handle_mouse_motion(self, coordinate): + """ + The mouse has moved, respond to mouse dragging. + Move a selected element to the new coordinate. + Auto-scroll the scroll bars at the boundaries. + """ + #to perform a movement, the mouse must be pressed, no pending events + if gtk.events_pending() or not self.mouse_pressed: return + #perform autoscrolling + width, height = self.get_size() + x, y = coordinate + h_adj = self.get_scroll_pane().get_hadjustment() + v_adj = self.get_scroll_pane().get_vadjustment() + for pos, length, adj, adj_val, adj_len in ( + (x, width, h_adj, h_adj.get_value(), h_adj.page_size), + (y, height, v_adj, v_adj.get_value(), v_adj.page_size), + ): + #scroll if we moved near the border + if pos-adj_val > adj_len-SCROLL_PROXIMITY_SENSITIVITY and adj_val+SCROLL_DISTANCE < length-adj_len: + adj.set_value(adj_val+SCROLL_DISTANCE) + adj.emit('changed') + elif pos-adj_val < SCROLL_PROXIMITY_SENSITIVITY: + adj.set_value(adj_val-SCROLL_DISTANCE) + adj.emit('changed') + #remove the connection if selected in drag event + if len(self.get_selected_elements()) == 1 and self.get_selected_element().is_connection(): + self.handle_states(ELEMENT_DELETE) + #move the selected elements and record the new coordinate + X, Y = self.get_coordinate() + if not self.get_ctrl_mask(): self.move_selected((int(x - X), int(y - Y))) + self.set_coordinate((x, y)) + #queue draw for animation + self.queue_draw() diff --git a/grc/gui/MainWindow.py b/grc/gui/MainWindow.py new file mode 100644 index 00000000..6d36f4cf --- /dev/null +++ b/grc/gui/MainWindow.py @@ -0,0 +1,324 @@ +""" +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 \ + NEW_FLOGRAPH_TITLE, DEFAULT_REPORTS_WINDOW_WIDTH +from Actions import \ + APPLICATION_QUIT, FLOW_GRAPH_KILL, \ + FLOW_GRAPH_SAVE, get_accel_group +import pygtk +pygtk.require('2.0') +import gtk +import Bars +from BlockTreeWindow import BlockTreeWindow +from Dialogs import TextDisplay, MessageDialogHelper +from NotebookPage import NotebookPage +import Preferences +import Messages +import Utils +import os + +MAIN_WINDOW_TITLE_TMPL = """\ +#if not $saved +*#slurp +#end if +#if $basename +$basename#slurp +#else +$new_flowgraph_title#slurp +#end if +#if $read_only + (read only)#slurp +#end if +#if $dirname + - $dirname#slurp +#end if + - $platform_name#slurp +""" + +PAGE_TITLE_MARKUP_TMPL = """\ +#set $foreground = $saved and 'black' or 'red' +$encode($title or $new_flowgraph_title)#slurp +#if $read_only + (ro)#slurp +#end if +""" + +############################################################ +# Main window +############################################################ + +class MainWindow(gtk.Window): + """The topmost window with menus, the tool bar, and other major windows.""" + + def __init__(self, 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() + self.hpaned = gtk.HPaned() + self.add(vbox) + #create the menu bar and toolbar + self.add_accel_group(get_accel_group()) + vbox.pack_start(Bars.MenuBar(), False) + vbox.pack_start(Bars.Toolbar(), False) + vbox.pack_start(self.hpaned) + #create the notebook + self.notebook = gtk.Notebook() + self.page_to_be_closed = None + self.current_page = None + self.notebook.set_show_border(False) + self.notebook.set_scrollable(True) #scroll arrows for page tabs + self.notebook.connect('switch-page', self._handle_page_change) + #setup containers + self.flow_graph_vpaned = gtk.VPaned() + #flow_graph_box.pack_start(self.scrolled_window) + self.flow_graph_vpaned.pack1(self.notebook) + self.hpaned.pack1(self.flow_graph_vpaned) + self.hpaned.pack2(BlockTreeWindow(platform, self.get_flow_graph), False) #dont allow resize + #create the reports window + self.text_display = TextDisplay() + #house the reports in a scrolled window + self.reports_scrolled_window = gtk.ScrolledWindow() + self.reports_scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.reports_scrolled_window.add_with_viewport(self.text_display) + self.reports_scrolled_window.set_size_request(-1, DEFAULT_REPORTS_WINDOW_WIDTH) + self.flow_graph_vpaned.pack2(self.reports_scrolled_window, False) #dont allow resize + #load preferences and show the main window + Preferences.load(platform) + self.resize(*Preferences.main_window_size()) + self.flow_graph_vpaned.set_position(Preferences.reports_window_position()) + self.hpaned.set_position(Preferences.blocks_window_position()) + self.show_all() + + ############################################################ + # Event Handlers + ############################################################ + + def _quit(self, window, event): + """ + Handle the delete event from the main window. + Generated by pressing X to close, alt+f4, or right click+close. + This method in turns calls the state handler to quit. + @return true + """ + 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') + + ############################################################ + # 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() + 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.main_window_size(self.get_size()) + Preferences.reports_window_position(self.flow_graph_vpaned.get_position()) + Preferences.blocks_window_position(self.hpaned.get_position()) + Preferences.save() + return True + + def close_page(self, ensure=True): + """ + Close the current page. + If the notebook becomes empty, and ensure is true, + call new page upon exit to ensure that at least one page exists. + @param ensure boolean + """ + if not self.page_to_be_closed: self.page_to_be_closed = self.get_page() + #show the page if it has an executing flow graph or is unsaved + if self.page_to_be_closed.get_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 + """ + gtk.Window.set_title(self, Utils.parse_template(MAIN_WINDOW_TITLE_TMPL, + basename=os.path.basename(self.get_page().get_file_path()), + dirname=os.path.dirname(self.get_page().get_file_path()), + new_flowgraph_title=NEW_FLOGRAPH_TITLE, + read_only=self.get_page().get_read_only(), + saved=self.get_page().get_saved(), + platform_name=self._platform.get_name(), + ) + ) + #set tab titles + for page in self._get_pages(): page.set_markup( + Utils.parse_template(PAGE_TITLE_MARKUP_TMPL, + #get filename and strip out file extension + title=os.path.splitext(os.path.basename(page.get_file_path()))[0], + read_only=page.get_read_only(), saved=page.get_saved(), + new_flowgraph_title=NEW_FLOGRAPH_TITLE, + ) + ) + #show/hide notebook tabs + self.notebook.set_show_tabs(len(self._get_pages()) > 1) + + def get_page(self): + """ + Get the selected page. + @return the selected page + """ + return self.current_page + + def get_flow_graph(self): + """ + Get the selected flow graph. + @return the selected flow graph + """ + return self.get_page().get_flow_graph() + + def get_focus_flag(self): + """ + Get the focus flag from the current page. + @return the focus flag + """ + return self.get_page().get_drawing_area().get_focus_flag() + + ############################################################ + # Helpers + ############################################################ + + def _set_page(self, page): + """ + Set the current page. + @param page the page widget + """ + self.current_page = page + self.notebook.set_current_page(self.notebook.page_num(self.current_page)) + + def _save_changes(self): + """ + Save changes to flow graph? + @return true if yes + """ + return MessageDialogHelper( + gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, 'Unsaved Changes!', + 'Would you like to save changes before closing?' + ) == gtk.RESPONSE_YES + + def _get_files(self): + """ + Get the file names for all the pages, in order. + @return list of file paths + """ + return map(lambda page: page.get_file_path(), self._get_pages()) + + def _get_pages(self): + """ + Get a list of all pages in the notebook. + @return list of pages + """ + return [self.notebook.get_nth_page(page_num) for page_num in range(self.notebook.get_n_pages())] diff --git a/grc/gui/Makefile.am b/grc/gui/Makefile.am new file mode 100644 index 00000000..c31bc5f6 --- /dev/null +++ b/grc/gui/Makefile.am @@ -0,0 +1,50 @@ +# +# Copyright 2008, 2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +ourpythondir = $(grc_src_prefix)/gui +ourpython_PYTHON = \ + Block.py \ + Colors.py \ + Constants.py \ + Connection.py \ + Element.py \ + FlowGraph.py \ + Param.py \ + Platform.py \ + Port.py \ + Utils.py \ + ActionHandler.py \ + Actions.py \ + Bars.py \ + BlockTreeWindow.py \ + 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/gui/Messages.py b/grc/gui/Messages.py new file mode 100644 index 00000000..80057e0b --- /dev/null +++ b/grc/gui/Messages.py @@ -0,0 +1,104 @@ +""" +Copyright 2007 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import traceback +import sys + +## A list of functions that can receive a message. +MESSENGERS_LIST = list() + +def register_messenger(messenger): + """ + Append the given messenger to the list of messengers. + @param messenger a method thats takes a string + """ + MESSENGERS_LIST.append(messenger) + +def send(message): + """ + Give the message to each of the messengers. + @param message a message string + """ + for messenger in MESSENGERS_LIST: messenger(message) + +#register stdout by default +register_messenger(sys.stdout.write) + +########################################################################### +# Special functions for specific program functionalities +########################################################################### +def send_init(platform): + send("""<<< Welcome to %s %s >>>\n"""%(platform.get_name(), platform.get_version())) + +def send_page_switch(file_path): + send('\nShowing: "%s"\n'%file_path) + +################# functions for loading flow graphs ######################################## +def send_start_load(file_path): + send('\nLoading: "%s"'%file_path + '\n') + +def send_error_load(error): + send('>>> Error: %s\n'%error) + traceback.print_exc() + +def send_end_load(): + send('>>> Done\n') + +def send_fail_load(error): + send('Error: %s\n'%error) + send('>>> 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('>>> Error: Cannot create connection.\n') + +################# functions for preferences ######################################## +def send_fail_load_preferences(prefs_file_path): + send('>>> Error: Cannot load preferences file: "%s"\n'%prefs_file_path) + +def send_fail_save_preferences(prefs_file_path): + send('>>> Error: Cannot save preferences file: "%s"\n'%prefs_file_path) + +################# functions for warning ######################################## +def send_warning(warning): + send('>>> Warning: %s\n'%warning) diff --git a/grc/gui/NotebookPage.py b/grc/gui/NotebookPage.py new file mode 100644 index 00000000..cb6b7ed3 --- /dev/null +++ b/grc/gui/NotebookPage.py @@ -0,0 +1,188 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from Actions import FLOW_GRAPH_CLOSE +import pygtk +pygtk.require('2.0') +import gtk +from StateCache import StateCache +from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT +from DrawingArea import DrawingArea +import os + +############################################################ +## Notebook Page +############################################################ + +class NotebookPage(gtk.HBox): + """A page in the notebook.""" + + def __init__(self, main_window, flow_graph, file_path=''): + """ + Page constructor. + @param main_window main window + @param file_path path to a flow graph file + """ + self._flow_graph = flow_graph + self.set_pid(None) + #import the file + self.main_window = main_window + self.set_file_path(file_path) + initial_state = flow_graph.get_parent().parse_flow_graph(file_path) + self.state_cache = StateCache(initial_state) + self.set_saved(True) + #import the data to the flow graph + self.get_flow_graph().import_data(initial_state) + #initialize page gui + gtk.HBox.__init__(self, False, 0) + self.show() + #tab box to hold label and close button + self.tab = gtk.HBox(False, 0) + #setup tab label + self.label = gtk.Label() + self.tab.pack_start(self.label, False) + #setup button image + image = gtk.Image() + image.set_from_stock('gtk-close', gtk.ICON_SIZE_MENU) + #setup image box + image_box = gtk.HBox(False, 0) + image_box.pack_start(image, True, False, 0) + #setup the button + button = gtk.Button() + button.connect("clicked", self._handle_button) + button.set_relief(gtk.RELIEF_NONE) + button.add(image_box) + #button size + w, h = gtk.icon_size_lookup_for_settings(button.get_settings(), gtk.ICON_SIZE_MENU) + button.set_size_request(w+6, h+6) + self.tab.pack_start(button, False) + self.tab.show_all() + #setup scroll window and drawing area + self.scrolled_window = gtk.ScrolledWindow() + self.scrolled_window.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) + self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.drawing_area = DrawingArea(self.get_flow_graph()) + self.scrolled_window.add_with_viewport(self.get_drawing_area()) + self.pack_start(self.scrolled_window) + #inject drawing area and handle states into flow graph + self.get_flow_graph().drawing_area = self.get_drawing_area() + self.get_flow_graph().handle_states = main_window.handle_states + self.show_all() + + def get_drawing_area(self): return self.drawing_area + + def get_generator(self): + """ + Get the generator object for this flow graph. + @return generator + """ + return self.get_flow_graph().get_parent().get_generator()( + self.get_flow_graph(), + self.get_file_path(), + ) + + def _handle_button(self, button): + """ + The button was clicked. + Make the current page selected, then close. + @param the button + """ + self.main_window.page_to_be_closed = self + self.main_window.handle_states(FLOW_GRAPH_CLOSE) + + def set_markup(self, markup): + """ + Set the markup in this label. + @param markup the new markup text + """ + self.label.set_markup(markup) + + def get_tab(self): + """ + Get the gtk widget for this page's tab. + @return gtk widget + """ + return self.tab + + def get_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_read_only(self): + """ + Get the read-only state of the file. + Always false for empty path. + @return true for read-only + """ + if not self.get_file_path(): return False + return os.path.exists(self.get_file_path()) and \ + not os.access(self.get_file_path(), os.W_OK) + + def get_file_path(self): + """ + Get the file path for the flow graph. + @return the file path or '' + """ + return self.file_path + + def set_file_path(self, file_path=''): + """ + Set the file path, '' for no file path. + @param file_path file path string + """ + if file_path: self.file_path = os.path.abspath(file_path) + else: self.file_path = '' + + def get_saved(self): + """ + Get the saved status for the flow graph. + @return true if saved + """ + return self.saved + + def set_saved(self, saved=True): + """ + Set the saved status. + @param saved boolean status + """ + self.saved = saved + + def get_state_cache(self): + """ + Get the state cache for the flow graph. + @return the state cache + """ + return self.state_cache diff --git a/grc/gui/Param.py b/grc/gui/Param.py new file mode 100644 index 00000000..3029569b --- /dev/null +++ b/grc/gui/Param.py @@ -0,0 +1,104 @@ +""" +Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import Utils +from Element import Element +import pygtk +pygtk.require('2.0') +import gtk + +PARAM_MARKUP_TMPL="""\ +#set $foreground = $param.is_valid() and 'black' or 'red' +#set $value = not $param.is_valid() and 'error' or repr($param) +$encode($param.get_name()): $encode($value)""" + +PARAM_LABEL_MARKUP_TMPL="""\ +#set $foreground = $param.is_valid() and 'black' or 'red' +#set $underline = $has_cb and 'low' or 'none' +$encode($param.get_name())""" + +TIP_MARKUP_TMPL="""\ +Key: $param.get_key() +Type: $param.get_type() +#if $param.is_valid() +Value: $param.get_evaluated() +#elif len($param.get_error_messages()) == 1 +Error: $(param.get_error_messages()[0]) +#else +Error: + #for $error_msg in $param.get_error_messages() + * $error_msg + #end for +#end if""" + +class Param(Element): + """The graphical parameter.""" + + def 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 object 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 + self._input = self.get_input_class()(self, self._handle_changed) + if not self._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. + """ + self.set_value(self._input.get_text()) + self.validate() + #is param is involved in a callback? #FIXME: messy + has_cb = \ + hasattr(self.get_parent(), 'get_callbacks') and \ + filter(lambda c: self.get_key() in c, self.get_parent()._callbacks) + self._input.set_markup(Utils.parse_template(PARAM_LABEL_MARKUP_TMPL, param=self, has_cb=has_cb)) + #hide/show + if self.get_hide() == 'all': self._input.hide_all() + else: self._input.show_all() + #set the color + self._input.set_color(self.get_color()) + #set the tooltip + if self._input.tp: self._input.tp.set_tip( + self._input.entry, + Utils.parse_template(TIP_MARKUP_TMPL, param=self).strip(), + ) + #execute the external callback + if self._callback: self._callback(self) + + 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(Utils.parse_template(PARAM_MARKUP_TMPL, param=self)) + return layout diff --git a/grc/gui/ParamsDialog.py b/grc/gui/ParamsDialog.py new file mode 100644 index 00000000..ccf19d1a --- /dev/null +++ b/grc/gui/ParamsDialog.py @@ -0,0 +1,145 @@ +""" +Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import pygtk +pygtk.require('2.0') +import gtk + +from Dialogs import TextDisplay +from Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT + +def get_title_label(title): + """ + Get a title label for the params window. + The title will be bold, underlined, and left justified. + @param title the text of the title + @return a gtk object + """ + label = gtk.Label() + label.set_markup('\n%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, + title='Properties: %s'%block.get_name(), + buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE), + ) + self.block = block + 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_box = gtk.VBox() + self._error_messages_text_display = TextDisplay() + self._error_box.pack_start(gtk.Label(), False, False, 7) #spacing + self._error_box.pack_start(get_title_label('Error Messages'), False) + self._error_box.pack_start(self._error_messages_text_display, False) + #Docs for the block + self._docs_box = err_box = gtk.VBox() + self._docs_text_display = TextDisplay() + self._docs_box.pack_start(gtk.Label(), False, False, 7) #spacing + self._docs_box.pack_start(get_title_label('Documentation'), False) + self._docs_box.pack_start(self._docs_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) + #Add the error and docs box + vbox.pack_start(self._error_box, False) + vbox.pack_start(self._docs_box, False) + #connect and show + 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() + + def _update(self): + """ + Update the error messages box. + Hide the box if there are no errors. + Update the documentation block. + Hide the box if there are no docs. + """ + self.block.validate() + #update the errors box + if self.block.is_valid(): self._error_box.hide() + else: self._error_box.show() + messages = '\n\n'.join(self.block.get_error_messages()) + self._error_messages_text_display.set_text(messages) + #update the docs box + if self.block.get_doc(): self._docs_box.show() + else: self._docs_box.hide() + self._docs_text_display.set_text(self.block.get_doc()) + + def _handle_key_press(self, widget, event): + """ + Handle key presses from the keyboard. + Call the ok response when enter is pressed. + @return false to forward the keypress + """ + 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 + """ + #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() + #update + self._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/gui/Platform.py b/grc/gui/Platform.py new file mode 100644 index 00000000..a32b0209 --- /dev/null +++ b/grc/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/gui/Port.py b/grc/gui/Port.py new file mode 100644 index 00000000..d1f36f8b --- /dev/null +++ b/grc/gui/Port.py @@ -0,0 +1,190 @@ +""" +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_SEPARATION, CONNECTOR_EXTENSION_MINIMAL, \ + CONNECTOR_EXTENSION_INCREMENT, \ + PORT_LABEL_PADDING, PORT_MIN_WIDTH +import Utils +import Colors +import pygtk +pygtk.require('2.0') +import gtk + +PORT_MARKUP_TMPL="""\ +$encode($port.get_name())""" + +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() + #get current rotation + rotation = self.get_rotation() + #get all sibling ports + if self.is_source(): ports = self.get_parent().get_sources() + elif self.is_sink(): ports = self.get_parent().get_sinks() + #get the max width + self.W = max([port.W for port in ports] + [PORT_MIN_WIDTH]) + #get a numeric index for this port relative to its sibling ports + index = ports.index(self) + length = len(ports) + #reverse the order of ports for these rotations + if rotation in (180, 270): index = length-index-1 + offset = (self.get_parent().H - length*self.H - (length-1)*PORT_SEPARATION)/2 + #create areas and connector coordinates + if (self.is_sink() and rotation == 0) or (self.is_source() and rotation == 180): + x = -1*self.W + y = (PORT_SEPARATION+self.H)*index+offset + self.add_area((x, y), (self.W, self.H)) + self._connector_coordinate = (x-1, y+self.H/2) + elif (self.is_source() and rotation == 0) or (self.is_sink() and rotation == 180): + x = self.get_parent().W + y = (PORT_SEPARATION+self.H)*index+offset + self.add_area((x, y), (self.W, self.H)) + self._connector_coordinate = (x+1+self.W, y+self.H/2) + elif (self.is_source() and rotation == 90) or (self.is_sink() and rotation == 270): + y = -1*self.W + x = (PORT_SEPARATION+self.H)*index+offset + self.add_area((x, y), (self.H, self.W)) + self._connector_coordinate = (x+self.H/2, y-1) + elif (self.is_sink() and rotation == 90) or (self.is_source() and rotation == 270): + y = self.get_parent().W + x = (PORT_SEPARATION+self.H)*index+offset + self.add_area((x, y), (self.H, self.W)) + self._connector_coordinate = (x+self.H/2, y+1+self.W) + #the connector length + self._connector_length = CONNECTOR_EXTENSION_MINIMAL + CONNECTOR_EXTENSION_INCREMENT*index + + def _create_labels(self): + """Create the labels for the socket.""" + self._bg_color = Colors.get_color(self.get_color()) + #create the layout + layout = gtk.DrawingArea().create_pango_layout('') + layout.set_markup(Utils.parse_template(PORT_MARKUP_TMPL, port=self)) + self.w, self.h = layout.get_pixel_size() + self.W, self.H = 2*PORT_LABEL_PADDING+self.w, 2*PORT_LABEL_PADDING+self.h + #create the pixmap + pixmap = self.get_parent().get_parent().new_pixmap(self.w, self.h) + gc = pixmap.new_gc() + gc.set_foreground(self._bg_color) + pixmap.draw_rectangle(gc, True, 0, 0, self.w, self.h) + pixmap.draw_layout(gc, 0, 0, layout) + #create the images + self.horizontal_label = image = pixmap.get_image(0, 0, self.w, self.h) + if self.is_vertical(): + self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), self.h, self.w) + for i in range(self.w): + for j in range(self.h): vimage.put_pixel(j, self.w-i-1, image.get_pixel(i, j)) + + def draw(self, gc, window): + """ + Draw the socket with a label. + @param gc the graphics context + @param window the gtk window to draw on + """ + Element.draw( + self, gc, window, bg_color=self._bg_color, + border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or Colors.BORDER_COLOR, + ) + X,Y = self.get_coordinate() + (x,y),(w,h) = self.areas_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+(self.W-self.w)/2, y+Y+(self.H-self.h)/2, -1, -1) + elif self.is_vertical(): + window.draw_image(gc, self.vertical_label, 0, 0, x+X+(self.H-self.h)/2, y+Y+(self.W-self.w)/2, -1, -1) + + def get_connector_coordinate(self): + """ + Get the coordinate where connections may attach to. + @return the connector coordinate (x, y) tuple + """ + x,y = self._connector_coordinate + X,Y = self.get_coordinate() + return (x+X, y+Y) + + def get_connector_direction(self): + """ + Get the direction that the socket points: 0,90,180,270. + This is the rotation degree if the socket is an output or + the rotation degree + 180 if the socket is an input. + @return the direction in degrees + """ + if self.is_source(): return self.get_rotation() + elif self.is_sink(): return (self.get_rotation() + 180)%360 + + def get_connector_length(self): + """ + Get the length of the connector. + The connector length increases as the port index changes. + @return the length in pixels + """ + return self._connector_length + + def get_rotation(self): + """ + Get the parent's rotation rather than self. + @return the parent's rotation + """ + return self.get_parent().get_rotation() + + def move(self, delta_coor): + """ + Move the parent rather than self. + @param delta_corr the (delta_x, delta_y) tuple + """ + self.get_parent().move(delta_coor) + + def rotate(self, direction): + """ + Rotate the parent rather than self. + @param direction degrees to rotate + """ + self.get_parent().rotate(direction) + + def get_coordinate(self): + """ + Get the parent's coordinate rather than self. + @return the parents coordinate + """ + return self.get_parent().get_coordinate() + + def set_highlighted(self, highlight): + """ + Set the parent highlight rather than self. + @param highlight true to enable highlighting + """ + self.get_parent().set_highlighted(highlight) + + def is_highlighted(self): + """ + Get the parent's is highlight rather than self. + @return the parent's highlighting status + """ + return self.get_parent().is_highlighted() diff --git a/grc/gui/Preferences.py b/grc/gui/Preferences.py new file mode 100644 index 00000000..1d89920d --- /dev/null +++ b/grc/gui/Preferences.py @@ -0,0 +1,86 @@ +""" +Copyright 2008 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import ConfigParser +import os + +_platform = None +_config_parser = ConfigParser.ConfigParser() + +def file_extension(): return '.'+_platform.get_key() +def _prefs_file(): return os.path.join(os.path.expanduser('~'), file_extension()) + +def load(platform): + global _platform + _platform = platform + #create sections + _config_parser.add_section('main') + _config_parser.add_section('files_open') + try: _config_parser.read(_prefs_file()) + except: pass +def save(): + try: _config_parser.write(open(_prefs_file(), 'w')) + except: pass + +########################################################################### +# Special methods for specific program functionalities +########################################################################### + +def main_window_size(size=None): + if size is not None: + _config_parser.set('main', 'main_window_width', size[0]) + _config_parser.set('main', 'main_window_height', size[1]) + else: + try: return ( + _config_parser.getint('main', 'main_window_width'), + _config_parser.getint('main', 'main_window_height'), + ) + except: return (1, 1) + +def file_open(file=None): + if file is not None: _config_parser.set('main', 'file_open', file) + else: + try: return _config_parser.get('main', 'file_open') + except: return '' + +def files_open(files=None): + if files is not None: + _config_parser.remove_section('files_open') #clear section + _config_parser.add_section('files_open') + for i, file in enumerate(files): + _config_parser.set('files_open', 'file_open_%d'%i, file) + else: + files = list() + i = 0 + while True: + try: files.append(_config_parser.get('files_open', 'file_open_%d'%i)) + except: return files + i = i + 1 + +def reports_window_position(pos=None): + if pos is not None: _config_parser.set('main', 'reports_window_position', pos) + else: + try: return _config_parser.getint('main', 'reports_window_position') or 1 #greater than 0 + except: return -1 + +def blocks_window_position(pos=None): + if pos is not None: _config_parser.set('main', 'blocks_window_position', pos) + else: + try: return _config_parser.getint('main', 'blocks_window_position') or 1 #greater than 0 + except: return -1 diff --git a/grc/gui/StateCache.py b/grc/gui/StateCache.py new file mode 100644 index 00000000..04b18b18 --- /dev/null +++ b/grc/gui/StateCache.py @@ -0,0 +1,92 @@ +""" +Copyright 2007 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +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/gui/Utils.py b/grc/gui/Utils.py new file mode 100644 index 00000000..ee6dc6cd --- /dev/null +++ b/grc/gui/Utils.py @@ -0,0 +1,82 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from Constants import POSSIBLE_ROTATIONS +from Cheetah.Template import Template + +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 + +def parse_template(tmpl_str, **kwargs): + """ + Parse the template string with the given args. + Pass in the xml encode method for pango escape chars. + @param tmpl_str the template as a string + @return a string of the parsed template + """ + kwargs['encode'] = xml_encode + return str(Template(tmpl_str, kwargs)) diff --git a/grc/gui/__init__.py b/grc/gui/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/grc/gui/__init__.py @@ -0,0 +1 @@ + diff --git a/grc/python/Block.py b/grc/python/Block.py new file mode 100644 index 00000000..a9e99949 --- /dev/null +++ b/grc/python/Block.py @@ -0,0 +1,153 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from .. base.Block import Block as _Block +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 + self._doc = n.find('doc') or '' + self._imports = map(lambda i: i.strip(), n.findall('import')) + self._make = n.find('make') + self._var_make = n.find('var_make') + self._checks = n.findall('check') + self._callbacks = n.findall('callback') + #build the block + _Block.__init__( + self, + flow_graph=flow_graph, + n=n, + ) + + 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) + #adjust nports + 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 port_controller_modify(self, direction): + """ + Change the port controller. + @param direction +1 or -1 + @return true for change + """ + changed = False + #concat the nports string from the private nports settings of both port0 + nports_str = \ + (self.get_sinks() and self.get_sinks()[0]._nports or '') + \ + (self.get_sources() and self.get_sources()[0]._nports or '') + #modify all params whose keys appear in the nports string + for param in self.get_params(): + if param.is_enum() or param.get_key() not in nports_str: continue + #try to increment the port controller by direction + try: + value = param.get_evaluated() + value = value + direction + assert 0 < value + param.set_value(value) + changed = True + except: pass + return changed + + def get_doc(self): + doc = self._doc.strip('\n').replace('\\\n', '') + #merge custom doc with doxygen docs + return '\n'.join([doc, extract_docs.extract(self.get_key())]).strip('\n') + + def get_imports(self): + """ + Resolve all import statements. + Split each import statement at newlines. + Combine all import statments into a list. + Filter empty imports. + @return a list of import statements + """ + return filter(lambda i: i, sum(map(lambda i: self.resolve_dependencies(i).split('\n'), self._imports), [])) + + def get_make(self): return self.resolve_dependencies(self._make) + def get_var_make(self): return self.resolve_dependencies(self._var_make) + + def get_callbacks(self): + """ + Get a list of function callbacks for this block. + @return a list of strings + """ + def make_callback(callback): + callback = self.resolve_dependencies(callback) + if callback.startswith('self.'): return callback + return 'self.%s.%s'%(self.get_id(), callback) + return map(make_callback, self._callbacks) diff --git a/grc/python/Connection.py b/grc/python/Connection.py new file mode 100644 index 00000000..d8a894bb --- /dev/null +++ b/grc/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/python/Constants.py b/grc/python/Constants.py new file mode 100644 index 00000000..5f203237 --- /dev/null +++ b/grc/python/Constants.py @@ -0,0 +1,63 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import os +import sys +import stat +from gnuradio import gr + +_gr_prefs = gr.prefs() + +PYEXEC = os.environ.get('PYTHONW', _gr_prefs.get_string('grc', 'pythonw', '')) + +#setup paths +PATH_SEP = ':' +DOCS_DIR = os.environ.get('GR_DOC_DIR', _gr_prefs.get_string('grc', 'doc_dir', '')) +HIER_BLOCKS_LIB_DIR = os.path.join(os.path.expanduser('~'), '.grc_gnuradio') +BLOCKS_DIRS = filter( #filter blank strings + lambda x: x, PATH_SEP.join([ + os.environ.get('GRC_BLOCKS_PATH', ''), + _gr_prefs.get_string('grc', 'local_blocks_path', ''), + _gr_prefs.get_string('grc', 'global_blocks_path', ''), + ]).split(PATH_SEP), +) + [HIER_BLOCKS_LIB_DIR] + +#file creation modes +TOP_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH +HIER_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH + +#data files +DATA_DIR = os.path.dirname(__file__) +FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl') +BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd') +DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc') + +#coloring +COMPLEX_COLOR_SPEC = '#3399FF' +FLOAT_COLOR_SPEC = '#FF8C69' +INT_COLOR_SPEC = '#00FF99' +SHORT_COLOR_SPEC = '#FFFF66' +BYTE_COLOR_SPEC = '#FF66FF' +COMPLEX_VECTOR_COLOR_SPEC = '#3399AA' +FLOAT_VECTOR_COLOR_SPEC = '#CC8C69' +INT_VECTOR_COLOR_SPEC = '#00CC99' +SHORT_VECTOR_COLOR_SPEC = '#CCCC33' +BYTE_VECTOR_COLOR_SPEC = '#CC66CC' +ID_COLOR_SPEC = '#DDDDDD' +WILDCARD_COLOR_SPEC = '#FFFFFF' diff --git a/grc/python/FlowGraph.py b/grc/python/FlowGraph.py new file mode 100644 index 00000000..47089a30 --- /dev/null +++ b/grc/python/FlowGraph.py @@ -0,0 +1,155 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import expr_utils +from .. base.FlowGraph import FlowGraph as _FlowGraph +from Block import Block +from Connection import Connection +import re + +_variable_matcher = re.compile('^(variable\w*)$') +_parameter_matcher = re.compile('^(parameter)$') + +class FlowGraph(_FlowGraph): + + _eval_cache = dict() + def _eval(self, code, namespace, namespace_hash): + """ + Evaluate the code with the given namespace. + @param code a string with python code + @param namespace a dict representing the namespace + @param namespace_hash a unique hash for the namespace + @return the resultant object + """ + my_hash = hash(code) ^ namespace_hash + #cache if does not exist + if not self._eval_cache.has_key(my_hash): + self._eval_cache[my_hash] = eval(code, namespace, namespace) + #return from cache + return self._eval_cache[my_hash] + + def _get_io_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').get_evaluated()), + 'type': str(pad.get_param('type').get_evaluated()), + 'vlen': str(pad.get_param('vlen').get_evaluated()), + 'size': pad.get_param('type').get_opt('size'), + } + + 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: _variable_matcher.match(b.get_key()), 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(), var.get_var_make()) 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: _parameter_matcher.match(b.get_key()), 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(variable.get_param('value').to_code(), n, n) + n[variable.get_id()] = e + except: pass + #make namespace public + self.n = n + self.n_hash = hash(str(n)) + #evaluate + e = self._eval(expr, self.n, self.n_hash) + return e diff --git a/grc/python/Generator.py b/grc/python/Generator.py new file mode 100644 index 00000000..cde7dc3d --- /dev/null +++ b/grc/python/Generator.py @@ -0,0 +1,125 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import os +import subprocess +from Cheetah.Template import Template +import expr_utils +from Constants import \ + TOP_BLOCK_FILE_MODE, HIER_BLOCK_FILE_MODE, \ + HIER_BLOCKS_LIB_DIR, PYEXEC, \ + FLOW_GRAPH_TEMPLATE +import convert_hier +from .. gui import Messages + +class Generator(object): + + def __init__(self, flow_graph, file_path): + """ + Initialize the generator object. + Determine the file to generate. + @param flow_graph the flow graph object + @param file_path the path to write the file to + """ + self._flow_graph = flow_graph + self._generate_options = self._flow_graph.get_option('generate_options') + if self._generate_options == 'hb': + self._mode = HIER_BLOCK_FILE_MODE + dirname = HIER_BLOCKS_LIB_DIR + else: + self._mode = TOP_BLOCK_FILE_MODE + dirname = os.path.dirname(file_path) + filename = self._flow_graph.get_option('id') + '.py' + self._file_path = os.path.join(dirname, filename) + + def get_file_path(self): return self._file_path + + def write(self): + #do throttle warning + all_keys = ' '.join(map(lambda b: b.get_key(), self._flow_graph.get_enabled_blocks())) + if ('usrp' not in all_keys) and ('audio' not in all_keys) and ('throttle' not in all_keys) and self._generate_options != 'hb': + Messages.send_warning('''\ +This flow graph may not have flow control: no audio or usrp blocks found. \ +Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''') + #generate + open(self.get_file_path(), 'w').write(str(self)) + if self._generate_options == 'hb': + #convert hier block to xml wrapper + convert_hier.convert_hier(self._flow_graph, self.get_file_path()) + os.chmod(self.get_file_path(), self._mode) + + def get_popen(self): + """ + Execute this python flow graph. + @return a popen object + """ + #execute + cmds = [PYEXEC, '-u', self.get_file_path()] #-u is unbuffered stdio + 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 + """ + title = self._flow_graph.get_option('title') or self._flow_graph.get_option('id').replace('_', ' ').title() + imports = self._flow_graph.get_imports() + variables = self._flow_graph.get_variables() + parameters = self._flow_graph.get_parameters() + #list of variables with controls + controls = filter(lambda v: v.get_make(), 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())) + probes = filter(lambda b: b.get_key().startswith('probe_'), blocks) #ensure probes are last in the block list + blocks = filter(lambda b: b not in (imports + parameters + variables + probes), blocks) + probes + #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] + #prepend self. + replace_dict = dict([(var_id, 'self.%s'%var_id) for var_id in var_ids]) + #list of callbacks + callbacks = [ + expr_utils.expr_replace(cb, replace_dict) + for cb in sum([block.get_callbacks() for block in self._flow_graph.get_enabled_blocks()], []) + ] + #map var id to callbacks + var_id2cbs = dict( + [(var_id, filter(lambda c: expr_utils.get_variable_dependencies(c, [var_id]), callbacks)) + for var_id in var_ids] + ) + #load the namespace + namespace = { + 'title': title, + 'imports': imports, + 'flow_graph': self._flow_graph, + 'variables': variables, + 'controls': controls, + 'parameters': parameters, + 'blocks': blocks, + 'connections': connections, + 'generate_options': self._generate_options, + 'var_id2cbs': var_id2cbs, + } + #build the template + t = Template(open(FLOW_GRAPH_TEMPLATE, 'r').read(), namespace) + return str(t) diff --git a/grc/python/Makefile.am b/grc/python/Makefile.am new file mode 100644 index 00000000..e6d253f5 --- /dev/null +++ b/grc/python/Makefile.am @@ -0,0 +1,43 @@ +# +# Copyright 2008, 2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +ourpythondir = $(grc_src_prefix)/python +ourpython_PYTHON = \ + convert_hier.py \ + expr_utils.py \ + extract_docs.py \ + Block.py \ + Connection.py \ + Constants.py \ + FlowGraph.py \ + Generator.py \ + Param.py \ + Platform.py \ + Port.py \ + __init__.py + +ourdatadir = $(grc_src_prefix)/python +dist_ourdata_DATA = \ + block.dtd \ + default_flow_graph.grc \ + flow_graph.tmpl diff --git a/grc/python/Param.py b/grc/python/Param.py new file mode 100644 index 00000000..8b5efc97 --- /dev/null +++ b/grc/python/Param.py @@ -0,0 +1,380 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import expr_utils +from .. base.Param import Param as _Param, EntryParam +import Constants +import numpy +import os +import pygtk +pygtk.require('2.0') +import gtk +from gnuradio import eng_notation +import re +from gnuradio import gr + +_check_id_matcher = re.compile('^[a-z|A-Z]\w*$') +_show_id_matcher = re.compile('^(variable\w*|parameter|options)$') + +class FileParam(EntryParam): + """Provide an entry box for filename and a button to browse for a file.""" + + def __init__(self, *args, **kwargs): + EntryParam.__init__(self, *args, **kwargs) + input = gtk.Button('...') + input.connect('clicked', self._handle_clicked) + self.pack_start(input, False) + + def _handle_clicked(self, widget=None): + """ + If the button was clicked, open a file dialog in open/save format. + Replace the text in the entry with the new filename from the file dialog. + """ + #get the paths + file_path = self.param.is_valid() and self.param.get_evaluated() or '' + (dirname, basename) = os.path.isfile(file_path) and os.path.split(file_path) or (file_path, '') + if not os.path.exists(dirname): dirname = os.getcwd() #fix bad paths + #build the dialog + if self.param.get_type() == 'file_open': + file_dialog = gtk.FileChooserDialog('Open a Data File...', None, + gtk.FILE_CHOOSER_ACTION_OPEN, ('gtk-cancel',gtk.RESPONSE_CANCEL,'gtk-open',gtk.RESPONSE_OK)) + elif self.param.get_type() == 'file_save': + file_dialog = gtk.FileChooserDialog('Save a Data File...', None, + gtk.FILE_CHOOSER_ACTION_SAVE, ('gtk-cancel',gtk.RESPONSE_CANCEL, 'gtk-save',gtk.RESPONSE_OK)) + file_dialog.set_do_overwrite_confirmation(True) + file_dialog.set_current_name(basename) #show the current filename + file_dialog.set_current_folder(dirname) #current directory + file_dialog.set_select_multiple(False) + file_dialog.set_local_only(True) + if gtk.RESPONSE_OK == file_dialog.run(): #run the dialog + file_path = file_dialog.get_filename() #get the file path + self.entry.set_text(file_path) + self._handle_changed() + file_dialog.destroy() #destroy the dialog + +#blacklist certain ids, its not complete, but should help +import __builtin__ +ID_BLACKLIST = ['self', 'options', 'gr', 'blks2', 'wxgui', 'wx', 'math', 'forms', 'firdes'] + \ + filter(lambda x: not x.startswith('_'), dir(gr.top_block())) + dir(__builtin__) +#define types, native python + numpy +VECTOR_TYPES = (tuple, list, set, numpy.ndarray) +COMPLEX_TYPES = [complex, numpy.complex, numpy.complex64, numpy.complex128] +REAL_TYPES = [float, numpy.float, numpy.float32, numpy.float64] +INT_TYPES = [int, long, numpy.int, numpy.int8, numpy.int16, numpy.int32, numpy.uint64, + numpy.uint, numpy.uint8, numpy.uint16, numpy.uint32, numpy.uint64] +#cast to tuple for isinstance, concat subtypes +COMPLEX_TYPES = tuple(COMPLEX_TYPES + REAL_TYPES + INT_TYPES) +REAL_TYPES = tuple(REAL_TYPES + INT_TYPES) +INT_TYPES = tuple(INT_TYPES) + +class Param(_Param): + + _init = False + _hostage_cells = list() + + ##possible param types + TYPES = _Param.TYPES + [ + 'complex', 'real', 'int', + 'complex_vector', 'real_vector', 'int_vector', + 'hex', 'string', 'bool', + 'file_open', 'file_save', + 'id', + 'grid_pos', 'import', + ] + + def __repr__(self): + """ + Get the repr (nice string format) for this param. + @return the string representation + """ + if self.get_value() in self.get_option_keys(): return self.get_option(self.get_value()).get_name() + ################################################## + # display logic for numbers + ################################################## + def num_to_str(num): + if isinstance(num, COMPLEX_TYPES): + num = complex(num) #cast to python complex + if num == 0: return '0' #value is zero + elif num.imag == 0: return '%s'%eng_notation.num_to_str(num.real) #value is real + elif num.real == 0: return '%sj'%eng_notation.num_to_str(num.imag) #value is imaginary + elif num.imag < 0: return '%s-%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(abs(num.imag))) + else: return '%s+%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(num.imag)) + else: return str(num) + ################################################## + # split up formatting by type + ################################################## + truncate = 0 #default center truncate + max_len = max(27 - len(self.get_name()), 3) + e = self.get_evaluated() + t = self.get_type() + if isinstance(e, bool): return str(e) + elif isinstance(e, COMPLEX_TYPES): dt_str = num_to_str(e) + elif isinstance(e, VECTOR_TYPES): #vector types + if len(e) > 8: + dt_str = self.get_value() #large vectors use code + truncate = 1 + else: dt_str = ', '.join(map(num_to_str, e)) #small vectors use eval + elif t in ('file_open', 'file_save'): + dt_str = self.get_value() + truncate = -1 + else: dt_str = str(e) #other types + ################################################## + # truncate + ################################################## + if len(dt_str) > max_len: + if truncate < 0: #front truncate + dt_str = '...' + dt_str[3-max_len:] + elif truncate == 0: #center truncate + dt_str = dt_str[:max_len/2 -3] + '...' + dt_str[-max_len/2:] + elif truncate > 0: #rear truncate + dt_str = dt_str[:max_len-3] + '...' + return dt_str + + def get_input_class(self): + if self.get_type() in ('file_open', 'file_save'): return FileParam + return _Param.get_input_class(self) + + def get_color(self): + """ + Get the color that represents this param's type. + @return a hex color code. + """ + try: + return { + #number types + 'complex': Constants.COMPLEX_COLOR_SPEC, + 'real': Constants.FLOAT_COLOR_SPEC, + 'int': Constants.INT_COLOR_SPEC, + #vector types + 'complex_vector': Constants.COMPLEX_VECTOR_COLOR_SPEC, + 'real_vector': Constants.FLOAT_VECTOR_COLOR_SPEC, + 'int_vector': Constants.INT_VECTOR_COLOR_SPEC, + #special + 'bool': Constants.INT_COLOR_SPEC, + 'hex': Constants.INT_COLOR_SPEC, + 'string': Constants.BYTE_VECTOR_COLOR_SPEC, + 'id': Constants.ID_COLOR_SPEC, + 'grid_pos': Constants.INT_VECTOR_COLOR_SPEC, + 'raw': Constants.WILDCARD_COLOR_SPEC, + }[self.get_type()] + except: return _Param.get_color(self) + + def get_hide(self): + """ + Get the hide value from the base class. + Hide the ID parameter for most blocks. Exceptions below. + If the parameter controls a port type, vlen, or nports, return part. + If the parameter is an empty grid position, return part. + These parameters are redundant to display in the flow graph view. + @return hide the hide property string + """ + hide = _Param.get_hide(self) + if hide: return hide + #hide ID in non variable blocks + if self.get_key() == 'id' and not _show_id_matcher.match(self.get_parent().get_key()): return 'part' + #hide port controllers for type and nports + if self.get_key() in ' '.join(map( + lambda p: ' '.join([p._type, p._nports]), self.get_parent().get_ports()) + ): return 'part' + #hide port controllers for vlen, when == 1 + if self.get_key() in ' '.join(map( + lambda p: p._vlen, self.get_parent().get_ports()) + ): + try: + assert int(self.get_evaluated()) == 1 + return 'part' + except: pass + #hide empty grid positions + if self.get_key() == 'grid_pos' and not self.get_value(): return 'part' + return hide + + def validate(self): + """ + Validate the param. + A test evaluation is performed + """ + _Param.validate(self) #checks type + self._evaluated = None + try: self._evaluated = self.evaluate() + except Exception, e: self.add_error_message(str(e)) + + def get_evaluated(self): return self._evaluated + + def evaluate(self): + """ + Evaluate the value. + @return evaluated type + """ + self._init = True + self._lisitify_flag = False + self._stringify_flag = False + self._hostage_cells = list() + def eval_string(v): + try: + e = self.get_parent().get_parent().evaluate(v) + 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 v + ######################### + # Numeric Types + ######################### + elif t in ('raw', 'complex', 'real', 'int', 'complex_vector', 'real_vector', 'int_vector', 'hex', 'bool'): + #raise exception if python cannot evaluate this value + try: e = self.get_parent().get_parent().evaluate(v) + except Exception, e: raise Exception, 'Value "%s" cannot be evaluated: %s'%(v, e) + #raise an exception if the data is invalid + if t == 'raw': return e + elif t == 'complex': + try: assert isinstance(e, COMPLEX_TYPES) + except AssertionError: raise Exception, 'Expression "%s" is invalid for type complex.'%str(e) + return e + elif t == 'real': + try: assert isinstance(e, REAL_TYPES) + except AssertionError: raise Exception, 'Expression "%s" is invalid for type real.'%str(e) + return e + elif t == 'int': + try: assert isinstance(e, INT_TYPES) + except AssertionError: raise Exception, 'Expression "%s" is invalid for type integer.'%str(e) + return e + ######################### + # Numeric Vector Types + ######################### + elif t == 'complex_vector': + if not isinstance(e, VECTOR_TYPES): + self._lisitify_flag = True + e = [e] + try: + for ei in e: assert isinstance(ei, COMPLEX_TYPES) + except AssertionError: raise Exception, 'Expression "%s" is invalid for type complex vector.'%str(e) + return e + elif t == 'real_vector': + if not isinstance(e, VECTOR_TYPES): + self._lisitify_flag = True + e = [e] + try: + for ei in e: assert isinstance(ei, REAL_TYPES) + except AssertionError: raise Exception, 'Expression "%s" is invalid for type real vector.'%str(e) + return e + elif t == 'int_vector': + if not isinstance(e, VECTOR_TYPES): + self._lisitify_flag = True + e = [e] + try: + for ei in e: assert isinstance(ei, INT_TYPES) + except AssertionError: raise Exception, 'Expression "%s" is invalid for type integer vector.'%str(e) + return e + elif t == 'hex': return hex(e) + elif t == 'bool': + try: assert isinstance(e, bool) + except AssertionError: raise Exception, 'Expression "%s" is invalid for type bool.'%str(e) + return 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 _check_id_matcher.match(v) + except AssertionError: raise Exception, 'ID "%s" must begin with a letter and may contain letters, numbers, and underscores.'%v + params = self.get_all_params('id') + keys = [param.get_value() for param in params] + try: assert keys.count(v) <= 1 #id should only appear once, or zero times if block is disabled + except: raise Exception, 'ID "%s" is not unique.'%v + try: assert v not in ID_BLACKLIST + except: raise Exception, 'ID "%s" is blacklisted.'%v + 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: raise Exception, 'A grid position must be a list of 4 integers.' + row, col, row_span, col_span = e + #check row, col + try: assert row >= 0 and col >= 0 + except AssertionError: raise Exception, 'Row and column must be non-negative.' + #check row span, col span + try: assert row_span > 0 and col_span > 0 + except AssertionError: raise Exception, 'Row and column span must be greater than zero.' + #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: raise Exception, 'Another graphical element is using cell "%s".'%str(cell) + return e + ######################### + # Import Type + ######################### + elif t == 'import': + n = dict() #new namespace + try: exec v in n + except ImportError: raise Exception, 'Import "%s" failed.'%v + except Exception: raise Exception, 'Bad import syntax: "%s".'%v + return filter(lambda k: str(k) != '__builtins__', n.keys()) + ######################### + else: raise TypeError, 'Type "%s" not handled'%t + + def to_code(self): + """ + Convert the value to code. + @return a string representing the code + """ + #run init tasks in evaluate + #such as setting flags + if not self._init: self.evaluate() + 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_enabled_blocks()], []) diff --git a/grc/python/Platform.py b/grc/python/Platform.py new file mode 100644 index 00000000..8718fe95 --- /dev/null +++ b/grc/python/Platform.py @@ -0,0 +1,81 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +import os +from .. import VERSION #TEMP: until gnuradio has __version__ +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, \ + DEFAULT_FLOW_GRAPH, BLOCKS_DIRS +import Constants + +COLORS = (#title, #color spec + ('Complex', Constants.COMPLEX_COLOR_SPEC), + ('Float', Constants.FLOAT_COLOR_SPEC), + ('Integer', Constants.INT_COLOR_SPEC), + ('Short', Constants.SHORT_COLOR_SPEC), + ('Byte', Constants.BYTE_COLOR_SPEC), + ('Complex Vector', Constants.COMPLEX_VECTOR_COLOR_SPEC), + ('Float Vector', Constants.FLOAT_VECTOR_COLOR_SPEC), + ('Integer Vector', Constants.INT_VECTOR_COLOR_SPEC), + ('Short Vector', Constants.SHORT_VECTOR_COLOR_SPEC), + ('Byte Vector', Constants.BYTE_VECTOR_COLOR_SPEC), + ('Wildcard Type', Constants.WILDCARD_COLOR_SPEC), +) + +class Platform(_Platform): + + def __init__(self): + """ + Make a platform for gnuradio. + """ + #ensure hier dir + if not os.path.exists(HIER_BLOCKS_LIB_DIR): os.mkdir(HIER_BLOCKS_LIB_DIR) + #convert block paths to absolute paths + block_paths = set(map(os.path.abspath, BLOCKS_DIRS)) + #init + _Platform.__init__( + self, + name='GNU Radio Companion', + version=VERSION, + key='grc', + license=__doc__.strip(), + website='http://gnuradio.org/trac/wiki/GNURadioCompanion', + block_paths=block_paths, + block_dtd=BLOCK_DTD, + default_flow_graph=DEFAULT_FLOW_GRAPH, + generator=Generator, + colors=COLORS, + ) + + ############################################## + # Constructors + ############################################## + FlowGraph = _FlowGraph + Connection = _Connection + Block = _Block + Source = Source + Sink = Sink + Param = _Param diff --git a/grc/python/Port.py b/grc/python/Port.py new file mode 100644 index 00000000..5a2b047f --- /dev/null +++ b/grc/python/Port.py @@ -0,0 +1,129 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from .. base.Port import Port as _Port +import Constants + +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 = n.find('vlen') or '1' + nports = n.find('nports') or '' + optional = n.find('optional') or '' + #build the port + _Port.__init__( + self, + block=block, + n=n, + ) + self._nports = nports + self._vlen = vlen + self._optional = bool(optional) + + def validate(self): + _Port.validate(self) + try: assert self.get_enabled_connections() or self.get_optional() + except AssertionError: self.add_error_message('Port is not connected.') + try: assert self.is_source() or len(self.get_enabled_connections()) <= 1 + except AssertionError: self.add_error_message('Port has too many connections.') + + 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': Constants.COMPLEX_COLOR_SPEC, + 'float': Constants.FLOAT_COLOR_SPEC, + 'int': Constants.INT_COLOR_SPEC, + 'short': Constants.SHORT_COLOR_SPEC, + 'byte': Constants.BYTE_COLOR_SPEC, + }[self.get_type()] + return {#vlen is non 1 + 'complex': Constants.COMPLEX_VECTOR_COLOR_SPEC, + 'float': Constants.FLOAT_VECTOR_COLOR_SPEC, + 'int': Constants.INT_VECTOR_COLOR_SPEC, + 'short': Constants.SHORT_VECTOR_COLOR_SPEC, + 'byte': Constants.BYTE_VECTOR_COLOR_SPEC, + }[self.get_type()] + except: return _Port.get_color(self) + +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/python/__init__.py b/grc/python/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/grc/python/__init__.py @@ -0,0 +1 @@ + diff --git a/grc/python/block.dtd b/grc/python/block.dtd new file mode 100644 index 00000000..7c6c3981 --- /dev/null +++ b/grc/python/block.dtd @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/grc/python/convert_hier.py b/grc/python/convert_hier.py new file mode 100644 index 00000000..bdafbcbc --- /dev/null +++ b/grc/python/convert_hier.py @@ -0,0 +1,79 @@ +""" +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 .. base import ParseXML +from .. base 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 + if parameters: block_n['make'] = '%s(\n\t%s,\n)'%( + block_key, + ',\n\t'.join(['%s=$%s'%(param.get_id(), param.get_id()) for param in parameters]), + ) + else: block_n['make'] = '%s()'%block_key + #callback data + block_n['callback'] = ['set_%s($%s)'%(param.get_id(), param.get_id()) for param in parameters] + #param data + params_n = list() + for param in parameters: + param_n = odict() + param_n['name'] = param.get_param('label').get_value() or param.get_id() + param_n['key'] = param.get_id() + param_n['value'] = param.get_param('value').get_value() + param_n['type'] = 'raw' + params_n.append(param_n) + block_n['param'] = params_n + #sink data + 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/python/default_flow_graph.grc b/grc/python/default_flow_graph.grc new file mode 100644 index 00000000..dea26f3a --- /dev/null +++ b/grc/python/default_flow_graph.grc @@ -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/python/expr_utils.py b/grc/python/expr_utils.py new file mode 100644 index 00000000..1880c8f9 --- /dev/null +++ b/grc/python/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_replace(expr, replace_dict): + """ + Search for vars in the expression and add the prepend. + @param expr an expression string + @param replace_dict a dict of find:replace + @return a new expression with the prepend + """ + expr_splits = expr_split(expr) + for i, es in enumerate(expr_splits): + if es in replace_dict.keys(): + expr_splits[i] = replace_dict[es] + return ''.join(expr_splits) + +def get_variable_dependencies(expr, vars): + """ + Return a set of variables used in this expression. + @param expr an expression string + @param vars a list of variable names + @return a subset of vars used in the expression + """ + expr_toks = expr_split(expr) + return set(filter(lambda v: v in expr_toks, vars)) + +def get_graph(exprs): + """ + Get a graph representing the variable dependencies + @param exprs a mapping of variable name to expression + @return a graph of variable deps + """ + vars = exprs.keys() + #get dependencies for each expression, load into graph + var_graph = graph() + for var in vars: var_graph.add_node(var) + for var, expr in exprs.iteritems(): + for dep in get_variable_dependencies(expr, vars): + if dep != var: var_graph.add_edge(dep, var) + return var_graph + +def sort_variables(exprs): + """ + Get a list of variables in order of dependencies. + @param exprs a mapping of variable name to expression + @return a list of variable names + @throws 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/python/extract_docs.py b/grc/python/extract_docs.py new file mode 100644 index 00000000..fa9140bd --- /dev/null +++ b/grc/python/extract_docs.py @@ -0,0 +1,90 @@ +""" +Copyright 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +GNU Radio Companion is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from Constants import DOCS_DIR +from lxml import etree +import os +import re + +DOXYGEN_NAME_XPATH = '/doxygen/compounddef/compoundname' +DOXYGEN_BRIEFDESC_GR_XPATH = '/doxygen/compounddef/briefdescription' +DOXYGEN_DETAILDESC_GR_XPATH = '/doxygen/compounddef/detaileddescription' + +def extract_txt(xml): + """ + Recursivly pull the text out of an xml tree. + @param xml the xml tree + @return a string + """ + text = (xml.text or '').replace('\n', '') + tail = (xml.tail or '').replace('\n', '') + if xml.tag == 'para': tail += '\n\n' + if xml.tag == 'linebreak': text += '\n' + if xml.tag == 'parametername': text += ': ' + return text + ''.join( + map(lambda x: extract_txt(x), xml) + ) + tail + +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 + """ + docs_dir = os.path.join(DOCS_DIR, 'xml') + if not os.path.exists(docs_dir): return '' + #extract matches + pattern = key.replace('_', '_*').replace('x', '\w') + prog = re.compile('^class%s\..*$'%pattern) + matches = filter(lambda f: prog.match(f), os.listdir(docs_dir)) + #combine all matches + doc_strs = list() + for match in matches: + try: + xml_file = os.path.join(docs_dir, match) + xml = etree.parse(xml_file) + #extract descriptions + comp_name = extract_txt(xml.xpath(DOXYGEN_NAME_XPATH)[0]).strip() + comp_name = ' --- ' + comp_name + ' --- ' + if re.match('(gr|usrp2|trellis)_.*', key): + brief_desc = extract_txt(xml.xpath(DOXYGEN_BRIEFDESC_GR_XPATH)[0]).strip() + detailed_desc = extract_txt(xml.xpath(DOXYGEN_DETAILDESC_GR_XPATH)[0]).strip() + else: + brief_desc = '' + detailed_desc = '' + #combine + doc_strs.append('\n\n'.join([comp_name, brief_desc, detailed_desc]).strip()) + except IndexError: pass #bad format + return '\n\n'.join(doc_strs) + +_docs_cache = dict() +def extract(key): + """ + Call the private extract and cache the result. + @param key the block key + @return a string with documentation + """ + try: assert _docs_cache.has_key(key) + except: _docs_cache[key] = _extract(key) + return _docs_cache[key] + +if __name__ == '__main__': + import sys + print extract(sys.argv[1]) diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl new file mode 100644 index 00000000..a45a918d --- /dev/null +++ b/grc/python/flow_graph.tmpl @@ -0,0 +1,205 @@ +#!/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_id2cbs variable id map to callback strings +######################################################## +#def indent($code) +#set $code = '\n\t\t'.join(str($code).splitlines()) +$code#slurp +#end def +#import time +#set $DIVIDER = '#'*50 +$DIVIDER +# Gnuradio Python Flow Graph +# Title: $title +#if $flow_graph.get_option('author') +# Author: $flow_graph.get_option('author') +#end if +#if $flow_graph.get_option('description') +# Description: $flow_graph.get_option('description') +#end if +# Generated: $time.ctime() +$DIVIDER + +######################################################## +##Create Imports +######################################################## +#for $imp in $imports +$imp +#end for + +######################################################## +##Create Class +## Write the class declaration for a top or hier block. +## The parameter names are the arguments to __init__. +## Determine the absolute icon path (wx gui only). +## Setup the IO signature (hier block only). +######################################################## +#set $class_name = $flow_graph.get_option('id') +#set $param_str = ', '.join(['self'] + ['%s=%s'%(param.get_id(), param.get_make()) for param in $parameters]) +#if $generate_options == 'wx_gui' + #import gtk + #set $icon = gtk.IconTheme().lookup_icon('gnuradio-grc', 32, 0) +class $(class_name)(grc_wxgui.top_block_gui): + + def __init__($param_str): + grc_wxgui.top_block_gui.__init__( + self, + title="$title", + #if $icon + icon="$icon.get_filename()", + #end if + ) +#elif $generate_options == 'no_gui' +class $(class_name)(gr.top_block): + + def __init__($param_str): + gr.top_block.__init__(self, "$title") +#elif $generate_options == 'hb' + #set $in_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, + "$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 + $indent($param.get_var_make()) +#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 + $indent($var.get_var_make()) +#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 + $indent($ctrl.get_make()) +#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) + self.$blk.get_id() = $indent($blk.get_make()) +#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(($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 $callback in $var_id2cbs[$id] + $indent($callback) + #end for + +#end for +######################################################## +##Create Main +## For top block code, generate a main routine. +## Instantiate the top block and run as gui or cli. +######################################################## +#if $generate_options != 'hb' +if __name__ == '__main__': + parser = OptionParser(option_class=eng_option, usage="%prog: [options]") + #set $params_eq_list = list() + #for $param in $parameters + #set $type = $param.get_param('type').get_value() + #if $type + #silent $params_eq_list.append('%s=options.%s'%($param.get_id(), $param.get_id())) + parser.add_option("--$param.get_id()", dest="$param.get_id()", type="$type", default=$param.get_make()) + #end if + #end for + (options, args) = parser.parse_args() + #if $flow_graph.get_option('realtime_scheduling') + if gr.enable_realtime_scheduling() != gr.RT_OK: + print "Error: failed to enable realtime scheduling." + #end if + tb = $(class_name)($(', '.join($params_eq_list))) + #if $generate_options == 'wx_gui' + tb.Run($flow_graph.get_option('autostart')) + #elif $generate_options == 'no_gui' + tb.start() + raw_input('Press Enter to quit: ') + tb.stop() + #end if +#end if + diff --git a/grc/scripts/grc b/grc/scripts/grc index a2e3bc28..8a6cc0af 100755 --- a/grc/scripts/grc +++ b/grc/scripts/grc @@ -18,8 +18,6 @@ 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 pygtk pygtk.require('2.0') import gtk @@ -32,7 +30,7 @@ Cannot import gnuradio. Are your PYTHONPATH and LD_LIBRARY_PATH set correctly?"" d.run() exit(-1) -from gnuradio.grc.platforms.base.Constants import VERSION +from gnuradio.grc import VERSION from optparse import OptionParser if __name__ == "__main__": @@ -47,13 +45,10 @@ and you are welcome to redistribute it. """%VERSION parser = OptionParser(usage=usage, version=version) (options, args) = parser.parse_args() - from gnuradio.grc.platforms.python.Platform import Platform + from gnuradio.grc.python.Platform import Platform from gnuradio.grc.gui.ActionHandler import ActionHandler #setup icon using icon theme try: gtk.window_set_default_icon(gtk.IconTheme().load_icon('gnuradio-grc', 256, 0)) except: pass - #extract extra block paths from environment variable, separated by semicolon - try: extra_blocks = os.environ['GRC_BLOCKS_PATH'].split(';') - except: extra_blocks = list() - ActionHandler(args, Platform(extra_blocks=extra_blocks)) + ActionHandler(args, Platform()) diff --git a/grc/scripts/usrp2_probe b/grc/scripts/usrp2_probe index fac2427d..00d4366d 100755 --- a/grc/scripts/usrp2_probe +++ b/grc/scripts/usrp2_probe @@ -29,10 +29,10 @@ import gobject from gnuradio.grc.gui.Dialogs import TextDisplay -from gnuradio.grc.platforms.python.Platform import Platform -platform = Platform(critical_only=True) +from gnuradio.grc.python.Platform import Platform +platform = Platform() -from gnuradio.grc.platforms.gui.Platform import Platform +from gnuradio.grc.gui.Platform import Platform platform = Platform(platform) flow_graph = platform.get_new_flow_graph() diff --git a/grc/scripts/usrp_probe b/grc/scripts/usrp_probe index 3eb3de58..6565612c 100755 --- a/grc/scripts/usrp_probe +++ b/grc/scripts/usrp_probe @@ -27,10 +27,10 @@ import gtk from gnuradio.grc.gui.Dialogs import TextDisplay -from gnuradio.grc.platforms.python.Platform import Platform -platform = Platform(critical_only=True) +from gnuradio.grc.python.Platform import Platform +platform = Platform() -from gnuradio.grc.platforms.gui.Platform import Platform +from gnuradio.grc.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 deleted file mode 100644 index a726d493..00000000 --- a/grc/src/Makefile.am +++ /dev/null @@ -1,32 +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 = \ - 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 deleted file mode 100644 index 8b137891..00000000 --- a/grc/src/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/grc/src/grc_gnuradio/Makefile.am b/grc/src/grc_gnuradio/Makefile.am deleted file mode 100644 index 767e8f67..00000000 --- a/grc/src/grc_gnuradio/Makefile.am +++ /dev/null @@ -1,31 +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 = \ - blks2 \ - usrp \ - wxgui - -ourpythondir = $(grc_gnuradio_prefix) - -ourpython_PYTHON = __init__.py diff --git a/grc/src/grc_gnuradio/__init__.py b/grc/src/grc_gnuradio/__init__.py deleted file mode 100644 index 8b137891..00000000 --- a/grc/src/grc_gnuradio/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/grc/src/grc_gnuradio/blks2/Makefile.am b/grc/src/grc_gnuradio/blks2/Makefile.am deleted file mode 100644 index 89889605..00000000 --- a/grc/src/grc_gnuradio/blks2/Makefile.am +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright 2008, 2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/grc/Makefile.inc - -ourpythondir = $(grc_gnuradio_prefix)/blks2 - -ourpython_PYTHON = \ - __init__.py \ - error_rate.py \ - packet.py \ - probe.py \ - selector.py \ - tcp.py \ - variable_sink.py diff --git a/grc/src/grc_gnuradio/blks2/__init__.py b/grc/src/grc_gnuradio/blks2/__init__.py deleted file mode 100644 index cb1196f2..00000000 --- a/grc/src/grc_gnuradio/blks2/__init__.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2008, 2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from selector import selector, valve -from packet import options, packet_encoder, packet_decoder, \ - packet_mod_b, packet_mod_s, packet_mod_i, packet_mod_f, packet_mod_c, \ - packet_demod_b, packet_demod_s, packet_demod_i, packet_demod_f, packet_demod_c -from error_rate import error_rate -from probe import probe_function, probe_avg_mag_sqrd_c, probe_avg_mag_sqrd_f, probe_density_b, probe_mpsk_snr_c -from variable_sink import variable_sink_b, variable_sink_s, variable_sink_i, variable_sink_f, variable_sink_c -from tcp import tcp_source, tcp_sink diff --git a/grc/src/grc_gnuradio/blks2/error_rate.py b/grc/src/grc_gnuradio/blks2/error_rate.py deleted file mode 100644 index 9b2df58e..00000000 --- a/grc/src/grc_gnuradio/blks2/error_rate.py +++ /dev/null @@ -1,137 +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. -# - -default_win_size = 1000 - -from gnuradio import gr -import gnuradio.gr.gr_threading as _threading -import numpy - -#generate 1s counts array -_1s_counts = [sum([1&(i>>j) for j in range(8)]) for i in range(2**8)] - -class input_watcher(_threading.Thread): - """ - Read samples from the message queue and hand them to the callback. - """ - - def __init__(self, msgq, callback): - self._msgq = msgq - self._callback = callback - _threading.Thread.__init__(self) - self.setDaemon(1) - self.keep_running = True - self.start() - - def run(self): - r = '' - while True: - msg = self._msgq.delete_head() - itemsize = int(msg.arg1()) - nitems = int(msg.arg2()) - s = r + msg.to_string() - i = (nitems-nitems%2)*itemsize - r = s[i:] - s = s[:i] - samples = numpy.fromstring(s, numpy.int8) - self._callback(samples) - -class error_rate(gr.hier_block2): - """ - Sample the incoming data streams (byte) and calculate the bit or symbol error rate. - Write the running rate to the output data stream (float). - """ - - def __init__(self, type='BER', win_size=default_win_size, bits_per_symbol=2): - """ - Error rate constructor. - @param type a string 'BER' or 'SER' - @param win_size the number of samples to calculate over - @param bits_per_symbol the number of information bits per symbol (BER only) - """ - #init - gr.hier_block2.__init__( - self, 'error_rate', - gr.io_signature(2, 2, gr.sizeof_char), - gr.io_signature(1, 1, gr.sizeof_float), - ) - assert type in ('BER', 'SER') - self._max_samples = win_size - self._bits_per_symbol = bits_per_symbol - #setup message queue - msg_source = gr.message_source(gr.sizeof_float, 1) - self._msgq_source = msg_source.msgq() - msgq_sink = gr.msg_queue(2) - msg_sink = gr.message_sink(gr.sizeof_char, msgq_sink, False) #False -> blocking - inter = gr.interleave(gr.sizeof_char) - #start thread - self._num_errs = 0 - self._err_index = 0 - self._num_samps = 0 - self._err_array = numpy.zeros(self._max_samples, numpy.int8) - if type == 'BER': - input_watcher(msgq_sink, self._handler_ber) - elif type == 'SER': - input_watcher(msgq_sink, self._handler_ser) - #connect - self.connect(msg_source, self) - self.connect((self, 0), (inter, 0)) - self.connect((self, 1), (inter, 1)) - self.connect(inter, msg_sink) - - def _handler_ber(self, samples): - num = len(samples)/2 - arr = numpy.zeros(num, numpy.float32) - for i in range(num): - old_err = self._err_array[self._err_index] - #record error - self._err_array[self._err_index] = _1s_counts[samples[i*2] ^ samples[i*2 + 1]] - self._num_errs = self._num_errs + self._err_array[self._err_index] - old_err - #increment index - self._err_index = (self._err_index + 1)%self._max_samples - self._num_samps = min(self._num_samps + 1, self._max_samples) - #write sample - arr[i] = float(self._num_errs)/float(self._num_samps*self._bits_per_symbol) - #write message - msg = gr.message_from_string(arr.tostring(), 0, gr.sizeof_float, num) - self._msgq_source.insert_tail(msg) - - def _handler_ser(self, samples): - num = len(samples)/2 - arr = numpy.zeros(num, numpy.float32) - for i in range(num): - old_err = self._err_array[self._err_index] - #record error - ref = samples[i*2] - res = samples[i*2 + 1] - if ref == res: - self._err_array[self._err_index] = 0 - else: - self._err_array[self._err_index] = 1 - #update number of errors - self._num_errs = self._num_errs + self._err_array[self._err_index] - old_err - #increment index - self._err_index = (self._err_index + 1)%self._max_samples - self._num_samps = min(self._num_samps + 1, self._max_samples) - #write sample - arr[i] = float(self._num_errs)/float(self._num_samps) - #write message - msg = gr.message_from_string(arr.tostring(), 0, gr.sizeof_float, num) - self._msgq_source.insert_tail(msg) diff --git a/grc/src/grc_gnuradio/blks2/packet.py b/grc/src/grc_gnuradio/blks2/packet.py deleted file mode 100644 index 50de99ac..00000000 --- a/grc/src/grc_gnuradio/blks2/packet.py +++ /dev/null @@ -1,241 +0,0 @@ -# Copyright 2008, 2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, packet_utils -import gnuradio.gr.gr_threading as _threading - -##payload length in bytes -DEFAULT_PAYLOAD_LEN = 512 - -##how many messages in a queue -DEFAULT_MSGQ_LIMIT = 2 - -##threshold for unmaking packets -DEFAULT_THRESHOLD = 12 - -################################################## -## Options Class for OFDM -################################################## -class options(object): - def __init__(self, **kwargs): - for key, value in kwargs.iteritems(): setattr(self, key, value) - -################################################## -## Packet Encoder -################################################## -class _packet_encoder_thread(_threading.Thread): - - def __init__(self, msgq, payload_length, send): - self._msgq = msgq - self._payload_length = payload_length - self._send = send - _threading.Thread.__init__(self) - self.setDaemon(1) - self.keep_running = True - self.start() - - def run(self): - sample = '' #residual sample - while self.keep_running: - msg = self._msgq.delete_head() #blocking read of message queue - sample = sample + msg.to_string() #get the body of the msg as a string - while len(sample) >= self._payload_length: - payload = sample[:self._payload_length] - sample = sample[self._payload_length:] - self._send(payload) - -class packet_encoder(gr.hier_block2): - """ - Hierarchical block for wrapping packet-based modulators. - """ - - def __init__(self, samples_per_symbol, bits_per_symbol, access_code='', pad_for_usrp=True): - """ - packet_mod constructor. - @param samples_per_symbol number of samples per symbol - @param bits_per_symbol number of bits per symbol - @param access_code AKA sync vector - @param pad_for_usrp If true, packets are padded such that they end up a multiple of 128 samples - @param payload_length number of bytes in a data-stream slice - """ - #setup parameters - self._samples_per_symbol = samples_per_symbol - self._bits_per_symbol = bits_per_symbol - self._pad_for_usrp = pad_for_usrp - if not access_code: #get access code - access_code = packet_utils.default_access_code - if not packet_utils.is_1_0_string(access_code): - raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) - self._access_code = access_code - self._pad_for_usrp = pad_for_usrp - #create blocks - msg_source = gr.message_source(gr.sizeof_char, DEFAULT_MSGQ_LIMIT) - self._msgq_out = msg_source.msgq() - #initialize hier2 - gr.hier_block2.__init__( - self, - "packet_encoder", - gr.io_signature(0, 0, 0), # Input signature - gr.io_signature(1, 1, gr.sizeof_char) # Output signature - ) - #connect - self.connect(msg_source, self) - - def send_pkt(self, payload): - """ - Wrap the payload in a packet and push onto the message queue. - @param payload string, data to send - """ - packet = packet_utils.make_packet( - payload, - self._samples_per_symbol, - self._bits_per_symbol, - self._access_code, - self._pad_for_usrp - ) - msg = gr.message_from_string(packet) - self._msgq_out.insert_tail(msg) - -################################################## -## Packet Decoder -################################################## -class _packet_decoder_thread(_threading.Thread): - - def __init__(self, msgq, callback): - _threading.Thread.__init__(self) - self.setDaemon(1) - self._msgq = msgq - self.callback = callback - self.keep_running = True - self.start() - - def run(self): - while self.keep_running: - msg = self._msgq.delete_head() - ok, payload = packet_utils.unmake_packet(msg.to_string(), int(msg.arg1())) - if self.callback: - self.callback(ok, payload) - -class packet_decoder(gr.hier_block2): - """ - Hierarchical block for wrapping packet-based demodulators. - """ - - def __init__(self, access_code='', threshold=-1, callback=None): - """ - packet_demod constructor. - @param access_code AKA sync vector - @param threshold detect access_code with up to threshold bits wrong (0 -> use default) - @param callback a function of args: ok, payload - """ - #access code - if not access_code: #get access code - access_code = packet_utils.default_access_code - if not packet_utils.is_1_0_string(access_code): - raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) - self._access_code = access_code - #threshold - if threshold < 0: threshold = DEFAULT_THRESHOLD - self._threshold = threshold - #blocks - msgq = gr.msg_queue(DEFAULT_MSGQ_LIMIT) #holds packets from the PHY - correlator = gr.correlate_access_code_bb(self._access_code, self._threshold) - framer_sink = gr.framer_sink_1(msgq) - #initialize hier2 - gr.hier_block2.__init__( - self, - "packet_decoder", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(0, 0, 0) # Output signature - ) - #connect - self.connect(self, correlator, framer_sink) - #start thread - _packet_decoder_thread(msgq, callback) - -################################################## -## Packet Mod for OFDM Mod and Packet Encoder -################################################## -class packet_mod_base(gr.hier_block2): - """ - Hierarchical block for wrapping packet source block. - """ - - def __init__(self, packet_source=None, payload_length=0): - if not payload_length: #get payload length - payload_length = DEFAULT_PAYLOAD_LEN - if payload_length%self._item_size_in != 0: #verify that packet length is a multiple of the stream size - raise ValueError, 'The payload length: "%d" is not a mutiple of the stream size: "%d".'%(payload_length, self._item_size_in) - #initialize hier2 - gr.hier_block2.__init__( - self, - "ofdm_mod", - gr.io_signature(1, 1, self._item_size_in), # Input signature - gr.io_signature(1, 1, packet_source._hb.output_signature().sizeof_stream_item(0)) # Output signature - ) - #create blocks - msgq = gr.msg_queue(DEFAULT_MSGQ_LIMIT) - msg_sink = gr.message_sink(self._item_size_in, msgq, False) #False -> blocking - #connect - self.connect(self, msg_sink) - self.connect(packet_source, self) - #start thread - _packet_encoder_thread(msgq, payload_length, packet_source.send_pkt) - -class packet_mod_b(packet_mod_base): _item_size_in = gr.sizeof_char -class packet_mod_s(packet_mod_base): _item_size_in = gr.sizeof_short -class packet_mod_i(packet_mod_base): _item_size_in = gr.sizeof_int -class packet_mod_f(packet_mod_base): _item_size_in = gr.sizeof_float -class packet_mod_c(packet_mod_base): _item_size_in = gr.sizeof_gr_complex - -################################################## -## Packet Demod for OFDM Demod and Packet Decoder -################################################## -class packet_demod_base(gr.hier_block2): - """ - Hierarchical block for wrapping packet sink block. - """ - - def __init__(self, packet_sink=None): - #initialize hier2 - gr.hier_block2.__init__( - self, - "ofdm_mod", - gr.io_signature(1, 1, packet_sink._hb.input_signature().sizeof_stream_item(0)), # Input signature - gr.io_signature(1, 1, self._item_size_out) # Output signature - ) - #create blocks - msg_source = gr.message_source(self._item_size_out, DEFAULT_MSGQ_LIMIT) - self._msgq_out = msg_source.msgq() - #connect - self.connect(self, packet_sink) - self.connect(msg_source, self) - if packet_sink._hb.output_signature().sizeof_stream_item(0): - self.connect(packet_sink, gr.null_sink(packet_sink._hb.output_signature().sizeof_stream_item(0))) - - def recv_pkt(self, ok, payload): - msg = gr.message_from_string(payload, 0, self._item_size_out, len(payload)/self._item_size_out) - if ok: self._msgq_out.insert_tail(msg) - -class packet_demod_b(packet_demod_base): _item_size_out = gr.sizeof_char -class packet_demod_s(packet_demod_base): _item_size_out = gr.sizeof_short -class packet_demod_i(packet_demod_base): _item_size_out = gr.sizeof_int -class packet_demod_f(packet_demod_base): _item_size_out = gr.sizeof_float -class packet_demod_c(packet_demod_base): _item_size_out = gr.sizeof_gr_complex diff --git a/grc/src/grc_gnuradio/blks2/probe.py b/grc/src/grc_gnuradio/blks2/probe.py deleted file mode 100644 index 8db81f05..00000000 --- a/grc/src/grc_gnuradio/blks2/probe.py +++ /dev/null @@ -1,123 +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. -# - -from gnuradio import gr -import threading -import numpy -import time - -####################################################################################### -## Probe: Function -####################################################################################### -class probe_function(gr.hier_block2, threading.Thread): - """ - The thread polls the function for values and writes to a message source. - """ - - def __init__(self, probe_callback, probe_rate): - #init hier block - gr.hier_block2.__init__( - self, 'probe_function', - gr.io_signature(0, 0, 0), - gr.io_signature(1, 1, gr.sizeof_float), - ) - self._probe_callback = probe_callback - self.set_probe_rate(probe_rate) - #create message source - message_source = gr.message_source(gr.sizeof_float, 1) - self._msgq = message_source.msgq() - #connect - self.connect(message_source, self) - #setup thread - threading.Thread.__init__(self) - self.setDaemon(True) - self.start() - - def run(self): - """ - Infinite polling loop. - """ - while True: - time.sleep(1.0/self._probe_rate) - arr = numpy.array(self._probe_callback(), numpy.float32) - msg = gr.message_from_string(arr.tostring(), 0, gr.sizeof_float, 1) - self._msgq.insert_tail(msg) - - def set_probe_rate(self, probe_rate): - self._probe_rate = probe_rate - -class _probe_base(gr.hier_block2): - def __init__(self, probe_block, probe_callback, probe_rate): - #init hier block - gr.hier_block2.__init__( - self, 'probe', - gr.io_signature(1, 1, probe_block.input_signature().sizeof_stream_items()[0]), - gr.io_signature(1, 1, gr.sizeof_float), - ) - probe_function_block = probe_function(probe_callback, probe_rate) - #forward callbacks - self.set_probe_rate = probe_function_block.set_probe_rate - #connect - self.connect(self, probe_block) - self.connect(probe_function_block, self) - -####################################################################################### -## Probe: Average Magnitude Squared -####################################################################################### -class _probe_avg_mag_sqrd_base(_probe_base): - def __init__(self, threshold, alpha, probe_rate): - #create block - probe_block = self._probe_block_contructor[0](threshold, alpha) - #forward callbacks - self.set_alpha = probe_block.set_alpha - self.set_threshold = probe_block.set_threshold - #init - _probe_base.__init__(self, probe_block, probe_block.level, probe_rate) - -class probe_avg_mag_sqrd_c(_probe_avg_mag_sqrd_base): _probe_block_contructor = (gr.probe_avg_mag_sqrd_c,) -class probe_avg_mag_sqrd_f(_probe_avg_mag_sqrd_base): _probe_block_contructor = (gr.probe_avg_mag_sqrd_f,) - -####################################################################################### -## Probe: Density -####################################################################################### -class probe_density_b(_probe_base): - def __init__(self, alpha, probe_rate): - #create block - probe_block = gr.probe_density_b(alpha) - #forward callbacks - self.set_alpha = probe_block.set_alpha - #init - _probe_base.__init__(self, probe_block, probe_block.density, probe_rate) - -####################################################################################### -## Probe: MPSK SNR -####################################################################################### -class probe_mpsk_snr_c(_probe_base): - def __init__(self, type, alpha, probe_rate): - """ - Type can be "snr", "signal_mean", or "noise_variance" - """ - #create block - probe_block = gr.probe_mpsk_snr_c(alpha) - #forward callbacks - self.set_alpha = probe_block.set_alpha - #init - _probe_base.__init__(self, probe_block, getattr(probe_block, type), probe_rate) diff --git a/grc/src/grc_gnuradio/blks2/selector.py b/grc/src/grc_gnuradio/blks2/selector.py deleted file mode 100644 index f0f6d5dd..00000000 --- a/grc/src/grc_gnuradio/blks2/selector.py +++ /dev/null @@ -1,128 +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. -# - -from gnuradio import gr - -class selector(gr.hier_block2): - """A hier2 block with N inputs and M outputs, where data is only forwarded through input n to output m.""" - def __init__(self, item_size, num_inputs, num_outputs, input_index, output_index): - """ - Selector constructor. - @param item_size the size of the gr data stream in bytes - @param num_inputs the number of inputs (integer) - @param num_outputs the number of outputs (integer) - @param input_index the index for the source data - @param output_index the index for the destination data - """ - gr.hier_block2.__init__( - self, 'selector', - gr.io_signature(num_inputs, num_inputs, item_size), - gr.io_signature(num_outputs, num_outputs, item_size), - ) - #terminator blocks for unused inputs and outputs - self.input_terminators = [gr.null_sink(item_size) for i in range(num_inputs)] - self.output_terminators = [gr.head(item_size, 0) for i in range(num_outputs)] - self.copy = gr.kludge_copy(item_size) - #connections - for i in range(num_inputs): self.connect((self, i), self.input_terminators[i]) - for i in range(num_outputs): self.connect(gr.null_source(item_size), self.output_terminators[i], (self, i)) - self.item_size = item_size - self.input_index = input_index - self.output_index = output_index - self.num_inputs = num_inputs - self.num_outputs = num_outputs - self._connect_current() - - def _indexes_valid(self): - """ - Are the input and output indexes within range of the number of inputs and outputs? - @return true if input index and output index are in range - """ - return self.input_index in range(self.num_inputs) and self.output_index in range(self.num_outputs) - - def _connect_current(self): - """If the input and output indexes are valid: - disconnect the blocks at the input and output index from their terminators, - and connect them to one another. Then connect the terminators to one another.""" - if self._indexes_valid(): - self.disconnect((self, self.input_index), self.input_terminators[self.input_index]) - self.disconnect(self.output_terminators[self.output_index], (self, self.output_index)) - self.connect((self, self.input_index), self.copy) - self.connect(self.copy, (self, self.output_index)) - self.connect(self.output_terminators[self.output_index], self.input_terminators[self.input_index]) - - def _disconnect_current(self): - """If the input and output indexes are valid: - disconnect the blocks at the input and output index from one another, - and the terminators at the input and output index from one another. - Reconnect the blocks to the terminators.""" - if self._indexes_valid(): - self.disconnect((self, self.input_index), self.copy) - self.disconnect(self.copy, (self, self.output_index)) - self.disconnect(self.output_terminators[self.output_index], self.input_terminators[self.input_index]) - self.connect((self, self.input_index), self.input_terminators[self.input_index]) - self.connect(self.output_terminators[self.output_index], (self, self.output_index)) - - def set_input_index(self, input_index): - """ - Change the block to the new input index if the index changed. - @param input_index the new input index - """ - if self.input_index != input_index: - self.lock() - self._disconnect_current() - self.input_index = input_index - self._connect_current() - self.unlock() - - def set_output_index(self, output_index): - """ - Change the block to the new output index if the index changed. - @param output_index the new output index - """ - if self.output_index != output_index: - self.lock() - self._disconnect_current() - self.output_index = output_index - self._connect_current() - self.unlock() - -class valve(selector): - """Wrapper for selector with 1 input and 1 output.""" - - def __init__(self, item_size, open): - """ - Constructor for valve. - @param item_size the size of the gr data stream in bytes - @param open true if initial valve state is open - """ - if open: output_index = -1 - else: output_index = 0 - selector.__init__(self, item_size, 1, 1, 0, output_index) - - def set_open(self, open): - """ - Callback to set open state. - @param open true to set valve state to open - """ - if open: output_index = -1 - else: output_index = 0 - self.set_output_index(output_index) diff --git a/grc/src/grc_gnuradio/blks2/tcp.py b/grc/src/grc_gnuradio/blks2/tcp.py deleted file mode 100644 index c6739b71..00000000 --- a/grc/src/grc_gnuradio/blks2/tcp.py +++ /dev/null @@ -1,66 +0,0 @@ -# -# Copyright 2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr -import socket -import os - -def _get_sock_fd(addr, port, server): - """ - Get the file descriptor for the socket. - As a client, block on connect, dup the socket descriptor. - As a server, block on accept, dup the client descriptor. - @param addr the ip address string - @param port the tcp port number - @param server true for server mode, false for client mode - @return the file descriptor number - """ - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - if server: - sock.bind((addr, port)) - sock.listen(1) - clientsock, address = sock.accept() - return os.dup(clientsock.fileno()) - else: - sock.connect((addr, port)) - return os.dup(sock.fileno()) - -class tcp_source(gr.hier_block2): - def __init__(self, itemsize, addr, port, server=True): - #init hier block - gr.hier_block2.__init__( - self, 'tcp_source', - gr.io_signature(0, 0, 0), - gr.io_signature(1, 1, itemsize), - ) - fd = _get_sock_fd(addr, port, server) - self.connect(gr.file_descriptor_source(itemsize, fd), self) - -class tcp_sink(gr.hier_block2): - def __init__(self, itemsize, addr, port, server=False): - #init hier block - gr.hier_block2.__init__( - self, 'tcp_sink', - gr.io_signature(1, 1, itemsize), - gr.io_signature(0, 0, 0), - ) - fd = _get_sock_fd(addr, port, server) - self.connect(self, gr.file_descriptor_sink(itemsize, fd)) diff --git a/grc/src/grc_gnuradio/blks2/variable_sink.py b/grc/src/grc_gnuradio/blks2/variable_sink.py deleted file mode 100644 index cad3b8b0..00000000 --- a/grc/src/grc_gnuradio/blks2/variable_sink.py +++ /dev/null @@ -1,64 +0,0 @@ -# -# Copyright 2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr -import threading -import numpy - -class _variable_sink_base(gr.hier_block2, threading.Thread): - """ - The thread polls the message queue for values and writes to a callback. - """ - - def __init__(self, vlen, decim, callback): - self._vlen = vlen - self._callback = callback - self._item_size = self._size*self._vlen - #init hier block - gr.hier_block2.__init__( - self, 'variable_sink', - gr.io_signature(1, 1, self._item_size), - gr.io_signature(0, 0, 0), - ) - #create blocks - self._decimator = gr.keep_one_in_n(self._item_size, decim) - self._msgq = gr.msg_queue(2) - message_sink = gr.message_sink(self._item_size, self._msgq, False) - #connect - self.connect(self, self._decimator, message_sink) - #setup thread - threading.Thread.__init__(self) - self.setDaemon(True) - self.start() - - def set_decim(self, decim): self._decimator.set_n(decim) - - def run(self): - while True: #truncate to item size, convert to array, callback - msg = self._msgq.delete_head().to_string()[-self._item_size:] - arr = map(self._cast, numpy.fromstring(msg, self._numpy)) - self._callback(self._vlen > 1 and arr or arr[0]) - -class variable_sink_b(_variable_sink_base): _numpy, _size, _cast = numpy.int8, gr.sizeof_char, int -class variable_sink_s(_variable_sink_base): _numpy, _size, _cast = numpy.int16, gr.sizeof_short, int -class variable_sink_i(_variable_sink_base): _numpy, _size, _cast = numpy.int32, gr.sizeof_int, int -class variable_sink_f(_variable_sink_base): _numpy, _size, _cast = numpy.float32, gr.sizeof_float, float -class variable_sink_c(_variable_sink_base): _numpy, _size, _cast = numpy.complex64, gr.sizeof_gr_complex, complex diff --git a/grc/src/grc_gnuradio/usrp/Makefile.am b/grc/src/grc_gnuradio/usrp/Makefile.am deleted file mode 100644 index 136a5dac..00000000 --- a/grc/src/grc_gnuradio/usrp/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)/grc/Makefile.inc - -ourpythondir = $(grc_gnuradio_prefix)/usrp - -ourpython_PYTHON = \ - __init__.py \ - common.py \ - dual_usrp.py \ - simple_usrp.py diff --git a/grc/src/grc_gnuradio/usrp/__init__.py b/grc/src/grc_gnuradio/usrp/__init__.py deleted file mode 100644 index 1956bbd5..00000000 --- a/grc/src/grc_gnuradio/usrp/__init__.py +++ /dev/null @@ -1,26 +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. -# - -from simple_usrp import \ - simple_source_c, simple_source_s, \ - simple_sink_c, simple_sink_s -from dual_usrp import \ - dual_source_c, dual_source_s, \ - dual_sink_c, dual_sink_s diff --git a/grc/src/grc_gnuradio/usrp/common.py b/grc/src/grc_gnuradio/usrp/common.py deleted file mode 100644 index 65c1e7e2..00000000 --- a/grc/src/grc_gnuradio/usrp/common.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright 2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import sys -from gnuradio import usrp, gr - -################################################## -# USRP base class with common methods -################################################## -class usrp_helper(object): - def _make_usrp(self, *args, **kwargs): self._u = self._usrp_args[0](*args, **kwargs) - def _get_u(self): return self._u - def _get_io_size(self): return self._usrp_args[1] - def _set_frequency(self, chan, subdev, frequency, verbose=False): - """ - Set the carrier frequency for the given subdevice. - @param chan specifies the DDC/DUC number - @param frequency the carrier frequency in Hz - @param verbose if true, print usrp tuning information - """ - r = self._get_u().tune(chan, subdev, frequency) - if not verbose: return - print subdev.side_and_name() - if r: - print "\tr.baseband_frequency =", r.baseband_freq - print "\tr.dxc_frequency =", r.dxc_freq - print "\tr.residual_frequency =", r.residual_freq - print "\tr.inverted =", r.inverted, "\n" - else: print >> sys.stderr, 'Error calling tune on subdevice.' - def set_format(self, width, shift): self._get_u().set_format(self._get_u().make_format(width, shift)) - -################################################## -# Classes to associate usrp constructor w/ io size -################################################## -class usrp_source_c(usrp_helper): _usrp_args = (usrp.source_c, gr.sizeof_gr_complex) -class usrp_source_s(usrp_helper): _usrp_args = (usrp.source_s, gr.sizeof_short) -class usrp_sink_c(usrp_helper): _usrp_args = (usrp.sink_c, gr.sizeof_gr_complex) -class usrp_sink_s(usrp_helper): _usrp_args = (usrp.sink_s, gr.sizeof_short) - -################################################## -# Side spec and antenna spec functions -################################################## -def is_flex(rx_ant): return rx_ant.upper() in ('TX/RX', 'RX2') -def to_spec(side, rx_ant='RXA'): - """ - Convert the side to a spec number. - @param side A or B - @param rx_ant antenna type - @return the spec (0/1, 0/1/2) - """ - #determine the side spec - try: side_spec = {'A': 0, 'B': 1}[side.upper()] - except: raise ValueError, 'Side A or B expected.' - #determine the subdevice spec - if rx_ant.upper() == 'RXB': subdev_spec = 1 - elif rx_ant.upper() == 'RXAB': subdev_spec = 2 - else: subdev_spec = 0 - return (side_spec, subdev_spec) diff --git a/grc/src/grc_gnuradio/usrp/dual_usrp.py b/grc/src/grc_gnuradio/usrp/dual_usrp.py deleted file mode 100644 index 1ecf7c47..00000000 --- a/grc/src/grc_gnuradio/usrp/dual_usrp.py +++ /dev/null @@ -1,132 +0,0 @@ -# Copyright 2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import common -from gnuradio import gr, usrp - -#################################################################### -# Dual USRP Source -#################################################################### -class _dual_source(gr.hier_block2): - """A dual usrp source of IO type short or complex.""" - - def __init__(self, which, rx_ant_a='RXA', rx_ant_b='RXA'): - """ - USRP dual source contructor. - @param which the unit number - @param rx_ant_a the antenna choice - @param rx_ant_b the antenna choice - """ - #initialize hier2 block - gr.hier_block2.__init__( - self, 'usrp_dual_source', - gr.io_signature(0, 0, 0), - gr.io_signature(2, 2, self._get_io_size()), - ) - #create usrp object - self._make_usrp(which=which, nchan=2) - subdev_spec_a = common.to_spec('A', rx_ant_a) - subdev_spec_b = common.to_spec('B', rx_ant_b) - self._get_u().set_mux(self._get_u().determine_rx_mux_value(subdev_spec_a, subdev_spec_b)) - self._subdev_a = self._get_u().selected_subdev(subdev_spec_a) - self._subdev_b = self._get_u().selected_subdev(subdev_spec_b) - #connect - deinter = gr.deinterleave(self._get_io_size()) - self.connect(self._get_u(), deinter) - for i in range(2): self.connect((deinter, i), (self, i)) - - def set_decim_rate(self, decim): self._get_u().set_decim_rate(int(decim)) - def set_frequency_a(self, frequency, verbose=False): - self._set_frequency( - chan=0, #ddc0 - subdev=self._subdev_a, - frequency=frequency, - verbose=verbose, - ) - def set_frequency_b(self, frequency, verbose=False): - self._set_frequency( - chan=1, #ddc1 - subdev=self._subdev_b, - frequency=frequency, - verbose=verbose, - ) - def set_lo_offset_a(self, lo_offset): self._subdev_a.set_lo_offset(lo_offset) - def set_lo_offset_b(self, lo_offset): self._subdev_b.set_lo_offset(lo_offset) - def set_gain_a(self, gain): self._subdev_a.set_gain(gain) - def set_gain_b(self, gain): self._subdev_b.set_gain(gain) - -class dual_source_c(_dual_source, common.usrp_source_c): pass -class dual_source_s(_dual_source, common.usrp_source_s): pass - -#################################################################### -# Dual USRP Sink -#################################################################### -class _dual_sink(gr.hier_block2): - """A dual usrp sink of IO type short or complex.""" - - def __init__(self, which): - """ - USRP simple sink contructor. - @param which the unit number - """ - #initialize hier2 block - gr.hier_block2.__init__( - self, 'usrp_dual_sink', - gr.io_signature(2, 2, self._get_io_size()), - gr.io_signature(0, 0, 0), - ) - #create usrp object - self._make_usrp(which=which, nchan=2) - subdev_spec_a = common.to_spec('A') - subdev_spec_b = common.to_spec('B') - self._get_u().set_mux(self._get_u().determine_tx_mux_value(subdev_spec_a, subdev_spec_b)) - self._subdev_a = self._get_u().selected_subdev(subdev_spec_a) - self._subdev_b = self._get_u().selected_subdev(subdev_spec_b) - #connect - inter = gr.interleave(self._get_io_size()) - self.connect(inter, self._get_u()) - for i in range(2): self.connect((self, i), (inter, i)) - - def set_interp_rate(self, interp): self._get_u().set_interp_rate(int(interp)) - def set_frequency_a(self, frequency, verbose=False): - self._set_frequency( - chan=self._subdev_a.which(), - subdev=self._subdev_a, - frequency=frequency, - verbose=verbose, - ) - def set_frequency_b(self, frequency, verbose=False): - self._set_frequency( - chan=self._subdev_b.which(), - subdev=self._subdev_b, - frequency=frequency, - verbose=verbose, - ) - def set_lo_offset_a(self, lo_offset): self._subdev_a.set_lo_offset(lo_offset) - def set_lo_offset_b(self, lo_offset): self._subdev_b.set_lo_offset(lo_offset) - def set_gain_a(self, gain): self._subdev_a.set_gain(gain) - def set_gain_b(self, gain): self._subdev_b.set_gain(gain) - def set_enable_a(self, enable): self._subdev_a.set_enable(enable) - def set_enable_b(self, enable): self._subdev_b.set_enable(enable) - def set_auto_tr_a(self, auto_tr): self._subdev_a.set_auto_tr(auto_tr) - def set_auto_tr_b(self, auto_tr): self._subdev_b.set_auto_tr(auto_tr) - -class dual_sink_c(_dual_sink, common.usrp_sink_c): pass -class dual_sink_s(_dual_sink, common.usrp_sink_s): pass diff --git a/grc/src/grc_gnuradio/usrp/simple_usrp.py b/grc/src/grc_gnuradio/usrp/simple_usrp.py deleted file mode 100644 index 9065c7fe..00000000 --- a/grc/src/grc_gnuradio/usrp/simple_usrp.py +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright 2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import common -from gnuradio import gr, usrp - -#################################################################### -# Simple USRP Source -#################################################################### -class _simple_source(gr.hier_block2): - """A single usrp source of IO type short or complex.""" - - def __init__(self, which, side='A', rx_ant='RXA', no_hb=False): - """ - USRP simple source contructor. - @param which the unit number - @param side the usrp side A or B - @param rx_ant the antenna choice - @param no_hb disable half band filters - """ - self._no_hb = no_hb - #initialize hier2 block - gr.hier_block2.__init__( - self, 'usrp_simple_source', - gr.io_signature(0, 0, 0), - gr.io_signature(1, 1, self._get_io_size()), - ) - #create usrp object - if self._no_hb: self._make_usrp(which=which, nchan=1, fpga_filename="std_4rx_0tx.rbf") - else: self._make_usrp(which=which, nchan=1) - subdev_spec = common.to_spec(side, rx_ant) - self._get_u().set_mux(self._get_u().determine_rx_mux_value(subdev_spec)) - self._subdev = self._get_u().selected_subdev(subdev_spec) - if common.is_flex(rx_ant): self._subdev.select_rx_antenna(rx_ant) - #connect - self.connect(self._get_u(), self) - - def set_decim_rate(self, decim): - self._get_u().set_decim_rate(int(decim)) - if self._no_hb: #set the BW to half the sample rate - self._subdev.set_bw(self._get_u().converter_rate()/decim/2) - def set_lo_offset(self, lo_offset): self._subdev.set_lo_offset(lo_offset) - def set_frequency(self, frequency, verbose=False): - self._set_frequency( - chan=0, #ddc0 - subdev=self._subdev, - frequency=frequency, - verbose=verbose, - ) - def set_gain(self, gain): self._subdev.set_gain(gain) - -class simple_source_c(_simple_source, common.usrp_source_c): pass -class simple_source_s(_simple_source, common.usrp_source_s): pass - -#################################################################### -# Simple USRP Sink -#################################################################### -class _simple_sink(gr.hier_block2): - """A single usrp sink of IO type short or complex.""" - - def __init__(self, which, side='A'): - """ - USRP simple sink contructor. - @param which the unit number - @param side the usrp side A or B - """ - #initialize hier2 block - gr.hier_block2.__init__( - self, 'usrp_simple_sink', - gr.io_signature(1, 1, self._get_io_size()), - gr.io_signature(0, 0, 0), - ) - #create usrp object - self._make_usrp(which=which, nchan=1) - subdev_spec = common.to_spec(side) - self._get_u().set_mux(self._get_u().determine_tx_mux_value(subdev_spec)) - self._subdev = self._get_u().selected_subdev(subdev_spec) - #connect - self.connect(self, self._get_u()) - - def set_interp_rate(self, interp): self._get_u().set_interp_rate(int(interp)) - def set_frequency(self, frequency, verbose=False): - self._set_frequency( - chan=self._subdev.which(), - subdev=self._subdev, - frequency=frequency, - verbose=verbose, - ) - def set_lo_offset(self, lo_offset): self._subdev.set_lo_offset(lo_offset) - def set_gain(self, gain): self._subdev.set_gain(gain) - def set_enable(self, enable): self._subdev.set_enable(enable) - def set_auto_tr(self, auto_tr): self._subdev.set_auto_tr(auto_tr) - -class simple_sink_c(_simple_sink, common.usrp_sink_c): pass -class simple_sink_s(_simple_sink, common.usrp_sink_s): pass - diff --git a/grc/src/grc_gnuradio/wxgui/Makefile.am b/grc/src/grc_gnuradio/wxgui/Makefile.am deleted file mode 100644 index 2e5e7ebd..00000000 --- a/grc/src/grc_gnuradio/wxgui/Makefile.am +++ /dev/null @@ -1,27 +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 - -ourpythondir = $(grc_gnuradio_prefix)/wxgui -ourpython_PYTHON = \ - __init__.py \ - top_block_gui.py diff --git a/grc/src/grc_gnuradio/wxgui/__init__.py b/grc/src/grc_gnuradio/wxgui/__init__.py deleted file mode 100644 index 94a0adb8..00000000 --- a/grc/src/grc_gnuradio/wxgui/__init__.py +++ /dev/null @@ -1,21 +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. -# - -from top_block_gui import top_block_gui diff --git a/grc/src/grc_gnuradio/wxgui/top_block_gui.py b/grc/src/grc_gnuradio/wxgui/top_block_gui.py deleted file mode 100644 index f3305d7c..00000000 --- a/grc/src/grc_gnuradio/wxgui/top_block_gui.py +++ /dev/null @@ -1,100 +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. -# - -import wx -import sys, os -from gnuradio import gr -from gnuradio.gr.pubsub import pubsub - -default_gui_size = (200, 100) - -class top_block_gui(gr.top_block, pubsub): - """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 - @param size the main window size tuple in pixels - @param icon the file path to an icon or None - """ - #initialize - gr.top_block.__init__(self) - pubsub.__init__(self) - self._size = size - #set the icon - if icon and os.path.isfile(icon): self._icon = icon - else: self._icon = None - #create gui elements - self._wx_app = wx.App() - self._wx_frame = wx.Frame(None , -1, title) - self._wx_grid = wx.GridBagSizer(5, 5) - 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) - @param col the column specification (integer >= 0) - @param row_span the row span specification (integer >= 1) - @param col_span the column span specification (integer >= 1) - """ - 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. - """ - #set wx app icon - if self._icon: self._wx_frame.SetIcon(wx.Icon(self._icon, wx.BITMAP_TYPE_ANY)) - #set minimal window size - self._wx_frame.SetSizeHints(*self._size) - #create callback for quit - def _quit(event): - gr.top_block.stop(self) - self._wx_frame.Destroy() - #setup app - self._wx_vbox.Add(self._wx_grid, 0, wx.EXPAND) - self._wx_frame.Bind(wx.EVT_CLOSE, _quit) - self._wx_frame.SetSizerAndFit(self._wx_vbox) - self._wx_frame.Show() - self._wx_app.SetTopWindow(self._wx_frame) - #start flow graph - 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 deleted file mode 100644 index 06e998b3..00000000 --- a/grc/src/gui/ActionHandler.py +++ /dev/null @@ -1,408 +0,0 @@ -""" -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import os -import signal -from Constants import IMAGE_FILE_EXTENSION -import Actions -import pygtk -pygtk.require('2.0') -import gtk -import gobject -import Preferences -from threading import Thread -import Messages -from .. utils import ParseXML -import random -from .. platforms.gui.Platform import Platform -from MainWindow import MainWindow -from ParamsDialog import ParamsDialog -import Dialogs -from FileDialogs import OpenFlowGraphFileDialog, SaveFlowGraphFileDialog, SaveImageFileDialog - -gobject.threads_init() - -class ActionHandler: - """ - The action handler will setup all the major window components, - and handle button presses and flow graph operations from the GUI. - """ - - def __init__(self, file_paths, platform): - """ - ActionHandler constructor. - Create the main window, setup the message handler, import the preferences, - and connect all of the action handlers. Finally, enter the gtk main loop and block. - @param file_paths a list of flow graph file passed from command line - @param platform platform module - """ - self.clipboard = None - platform = Platform(platform) - for action in Actions.get_all_actions(): 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.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.main() - - def _handle_key_press(self, widget, event): - """ - Handle key presses from the keyboard and translate key combinations into actions. - This key press handler is called prior to the gtk key press handler. - This handler bypasses built in accelerator key handling when in focus because - * some keys are ignored by the accelerators like the direction keys, - * some keys are not registered to any accelerators but are still used. - When not in focus, gtk and the accelerators handle the the key press. - @return false to let gtk handle the key action - """ - #dont allow key presses to queue up - if gtk.events_pending(): return True - #extract action name from this key press - key_name = gtk.gdk.keyval_name(event.keyval) - mod_mask = event.state - action_name = Actions.get_action_name_from_key_name(key_name, mod_mask) - #handle the action if flow graph is in focus - if action_name and self.get_focus_flag(): - self.handle_states(action_name) - return True #handled by this method - return False #let gtk handle the key press - - 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.get_all_actions(): action.set_sensitive(False) #set all actions disabled - # enable a select few actions - for action in ( - Actions.APPLICATION_QUIT, Actions.FLOW_GRAPH_NEW, - Actions.FLOW_GRAPH_OPEN, Actions.FLOW_GRAPH_SAVE_AS, - Actions.FLOW_GRAPH_CLOSE, Actions.ABOUT_WINDOW_DISPLAY, - Actions.FLOW_GRAPH_SCREEN_CAPTURE, Actions.HELP_WINDOW_DISPLAY, - ): Actions.get_action_from_name(action).set_sensitive(True) - if not self.init_file_paths: - self.init_file_paths = Preferences.files_open() - if not self.init_file_paths: self.init_file_paths = [''] - for file_path in self.init_file_paths: - if file_path: self.main_window.new_page(file_path) #load pages from file paths - if Preferences.file_open() in self.init_file_paths: - self.main_window.new_page(Preferences.file_open(), show=True) - if not self.get_page(): self.main_window.new_page() #ensure that at least a blank page exists - elif state == Actions.APPLICATION_QUIT: - if self.main_window.close_pages(): - gtk.main_quit() - exit(0) - ################################################## - # Selections - ################################################## - elif state == Actions.ELEMENT_SELECT: - pass #do nothing, update routines below - elif state == Actions.NOTHING_SELECT: - self.get_flow_graph().unselect() - ################################################## - # 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(Actions.BLOCK_COPY) - self.handle_states(Actions.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_CCW: - if self.get_flow_graph().rotate_selected(90): - self.get_flow_graph().update() - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - elif state == Actions.BLOCK_ROTATE_CW: - if self.get_flow_graph().rotate_selected(-90): - self.get_flow_graph().update() - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - elif state == Actions.ELEMENT_DELETE: - if self.get_flow_graph().remove_selected(): - self.get_flow_graph().update() - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.handle_states(Actions.NOTHING_SELECT) - self.get_page().set_saved(False) - elif state == Actions.ELEMENT_CREATE: - self.get_flow_graph().update() - 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.ABOUT_WINDOW_DISPLAY: - Dialogs.AboutDialog() - elif state == Actions.HELP_WINDOW_DISPLAY: - Dialogs.HelpDialog() - ################################################## - # Param Modifications - ################################################## - elif state == Actions.BLOCK_PARAM_MODIFY: - selected_block = self.get_flow_graph().get_selected_block() - if selected_block and ParamsDialog(selected_block).run(): - 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: - #read-only or undefined file path, do save-as - if self.get_page().get_read_only() or not self.get_page().get_file_path(): - self.handle_states(Actions.FLOW_GRAPH_SAVE_AS) - #otherwise try to save - else: - try: - ParseXML.to_file(self.get_flow_graph().export_data(), self.get_page().get_file_path()) - self.get_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 is not 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 is not None: - pixmap = self.get_flow_graph().get_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_CCW).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) - Actions.get_action_from_name(Actions.BLOCK_ROTATE_CW).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() - try: #set the size of the flow graph area (if changed) - new_size = self.get_flow_graph().get_option('window_size') - if self.get_flow_graph().get_size() != tuple(new_size): - self.get_flow_graph().set_size(*new_size) - except: pass - #draw the flow graph - self.get_flow_graph().update_selected() - self.get_flow_graph().queue_draw() - - 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 executing process by reading from its stdout. - Use gobject.idle_add when calling functions that modify gtk objects. - """ - #handle completion - r = "\n" - while(r): - gobject.idle_add(Messages.send_verbose_exec, r) - r = os.read(self.p.stdout.fileno(), 1024) - gobject.idle_add(self.done) - - def done(self): - """Perform end of execution tasks.""" - Messages.send_end_exec() - self.page.set_pid(None) - self.update_exec_stop() diff --git a/grc/src/gui/Actions.py b/grc/src/gui/Actions.py deleted file mode 100644 index 9b687df7..00000000 --- a/grc/src/gui/Actions.py +++ /dev/null @@ -1,167 +0,0 @@ -""" -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import pygtk -pygtk.require('2.0') -import gtk - -###################################################################################################### -# Action Names -###################################################################################################### -APPLICATION_INITIALIZE = 'app init' -APPLICATION_QUIT = 'app quit' -PARAM_MODIFY = 'param modify' -BLOCK_MOVE = 'block move' -BLOCK_ROTATE_CCW = 'block rotate ccw' -BLOCK_ROTATE_CW = 'block rotate cw' -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' -HELP_WINDOW_DISPLAY = 'help window display' - -###################################################################################################### -# Action Key Map -###################################################################################################### -_actions_key_list = ( - #action name, key name, mod mask - (FLOW_GRAPH_NEW, 'n', gtk.gdk.CONTROL_MASK), - (FLOW_GRAPH_OPEN, 'o', gtk.gdk.CONTROL_MASK), - (FLOW_GRAPH_SAVE, 's', gtk.gdk.CONTROL_MASK), - (FLOW_GRAPH_SAVE_AS, 's', gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK), - (FLOW_GRAPH_CLOSE, 'w', gtk.gdk.CONTROL_MASK), - (APPLICATION_QUIT, 'q', gtk.gdk.CONTROL_MASK), - (FLOW_GRAPH_UNDO, 'z', gtk.gdk.CONTROL_MASK), - (FLOW_GRAPH_REDO, 'y', gtk.gdk.CONTROL_MASK), - (ELEMENT_DELETE, 'Delete', 0), - (BLOCK_ROTATE_CCW, 'Left', 0), - (BLOCK_ROTATE_CW, 'Right', 0), - (BLOCK_DEC_TYPE, 'Up', 0), - (BLOCK_INC_TYPE, 'Down', 0), - (BLOCK_PARAM_MODIFY, 'Return', 0), - (BLOCK_ENABLE, 'e', 0), - (BLOCK_DISABLE, 'd', 0), - (BLOCK_CUT, 'x', gtk.gdk.CONTROL_MASK), - (BLOCK_COPY, 'c', gtk.gdk.CONTROL_MASK), - (BLOCK_PASTE, 'v', gtk.gdk.CONTROL_MASK), - (FLOW_GRAPH_GEN, 'F5', 0), - (FLOW_GRAPH_EXEC, 'F6', 0), - (FLOW_GRAPH_KILL, 'F7', 0), - (FLOW_GRAPH_SCREEN_CAPTURE, 'Print', 0), - (HELP_WINDOW_DISPLAY, 'F1', 0), - #the following have no associated gtk.Action - (PORT_CONTROLLER_INC, 'equal', 0), - (PORT_CONTROLLER_INC, 'plus', 0), - (PORT_CONTROLLER_INC, 'KP_Add', 0), - (PORT_CONTROLLER_DEC, 'minus', 0), - (PORT_CONTROLLER_DEC, 'KP_Subtract', 0), -) - -_actions_key_dict = dict(((key_name, mod_mask), action_name) for action_name, key_name, mod_mask in _actions_key_list) -def get_action_name_from_key_name(key_name, mod_mask=0): - """ - Get the action name associated with the key name and mask. - Both keyname and mask have to match. - @param key_name the name of the key - @param mod_mask the key press mask (shift, ctrl) 0 for none - @return the action name or blank string - """ - key_name_mod_mask = (key_name, mod_mask) - if key_name_mod_mask in _actions_key_dict: return _actions_key_dict[key_name_mod_mask] - return '' - -###################################################################################################### -# Actions -###################################################################################################### -_actions_list = ( - gtk.Action(FLOW_GRAPH_NEW, '_New', 'Create a new flow graph', gtk.STOCK_NEW), - gtk.Action(FLOW_GRAPH_OPEN, '_Open', 'Open an existing flow graph', gtk.STOCK_OPEN), - gtk.Action(FLOW_GRAPH_SAVE, '_Save', 'Save the current flow graph', gtk.STOCK_SAVE), - gtk.Action(FLOW_GRAPH_SAVE_AS, 'Save _As', 'Save the current flow graph as...', gtk.STOCK_SAVE_AS), - gtk.Action(FLOW_GRAPH_CLOSE, '_Close', 'Close the current flow graph', gtk.STOCK_CLOSE), - gtk.Action(APPLICATION_QUIT, '_Quit', 'Quit program', gtk.STOCK_QUIT), - gtk.Action(FLOW_GRAPH_UNDO, '_Undo', 'Undo a change to the flow graph', gtk.STOCK_UNDO), - gtk.Action(FLOW_GRAPH_REDO, '_Redo', 'Redo a change to the flow graph', gtk.STOCK_REDO), - gtk.Action(ELEMENT_DELETE, '_Delete', 'Delete the selected blocks', gtk.STOCK_DELETE), - gtk.Action(BLOCK_ROTATE_CCW, 'Rotate Counterclockwise', 'Rotate the selected blocks 90 degrees to the left', gtk.STOCK_GO_BACK), - gtk.Action(BLOCK_ROTATE_CW, 'Rotate Clockwise', 'Rotate the selected blocks 90 degrees to the right', gtk.STOCK_GO_FORWARD), - gtk.Action(BLOCK_PARAM_MODIFY, '_Properties', 'Modify params for the selected block', gtk.STOCK_PROPERTIES), - gtk.Action(BLOCK_ENABLE, 'E_nable', 'Enable the selected blocks', gtk.STOCK_CONNECT), - gtk.Action(BLOCK_DISABLE, 'D_isable', 'Disable the selected blocks', gtk.STOCK_DISCONNECT), - gtk.Action(BLOCK_CUT, 'Cu_t', 'Cut', gtk.STOCK_CUT), - gtk.Action(BLOCK_COPY, '_Copy', 'Copy', gtk.STOCK_COPY), - gtk.Action(BLOCK_PASTE, '_Paste', 'Paste', gtk.STOCK_PASTE), - gtk.Action(ABOUT_WINDOW_DISPLAY, '_About', 'About this program', gtk.STOCK_ABOUT), - gtk.Action(HELP_WINDOW_DISPLAY, '_Help', 'Usage Tips', gtk.STOCK_HELP), - gtk.Action(FLOW_GRAPH_GEN, '_Generate', 'Generate the flow graph', gtk.STOCK_CONVERT), - gtk.Action(FLOW_GRAPH_EXEC, '_Execute', 'Execute the flow graph', gtk.STOCK_EXECUTE), - gtk.Action(FLOW_GRAPH_KILL, '_Kill', 'Kill the flow graph', gtk.STOCK_STOP), - gtk.Action(FLOW_GRAPH_SCREEN_CAPTURE, 'S_creen Capture', 'Create a screen capture of the flow graph', gtk.STOCK_PRINT), -) -def get_all_actions(): return _actions_list - -_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 action_name in _actions_dict: return _actions_dict[action_name] - raise KeyError('Action Name: "%s" does not exist'%action_name) - -###################################################################################################### -# Accelerators -###################################################################################################### -_accel_group = gtk.AccelGroup() -def get_accel_group(): return _accel_group - -#set the accelerator group, and accelerator path -#register the key name and mod mask with the accelerator path -for action_name, key_name, mod_mask in _actions_key_list: - try: - accel_path = '
/'+action_name - get_action_from_name(action_name).set_accel_group(get_accel_group()) - get_action_from_name(action_name).set_accel_path(accel_path) - gtk.accel_map_add_entry(accel_path, gtk.gdk.keyval_from_name(key_name), mod_mask) - except KeyError: pass #no action was created for this action name diff --git a/grc/src/gui/Bars.py b/grc/src/gui/Bars.py deleted file mode 100644 index 52e7ba1f..00000000 --- a/grc/src/gui/Bars.py +++ /dev/null @@ -1,137 +0,0 @@ -""" -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import Actions -import pygtk -pygtk.require('2.0') -import gtk - -##The list of actions for the toolbar. -TOOLBAR_LIST = ( - Actions.FLOW_GRAPH_NEW, - Actions.FLOW_GRAPH_OPEN, - Actions.FLOW_GRAPH_SAVE, - Actions.FLOW_GRAPH_CLOSE, - None, - Actions.FLOW_GRAPH_SCREEN_CAPTURE, - None, - Actions.BLOCK_CUT, - Actions.BLOCK_COPY, - Actions.BLOCK_PASTE, - Actions.ELEMENT_DELETE, - None, - Actions.FLOW_GRAPH_UNDO, - Actions.FLOW_GRAPH_REDO, - None, - Actions.FLOW_GRAPH_GEN, - Actions.FLOW_GRAPH_EXEC, - Actions.FLOW_GRAPH_KILL, - None, - Actions.BLOCK_ROTATE_CCW, - Actions.BLOCK_ROTATE_CW, - None, - Actions.BLOCK_ENABLE, - Actions.BLOCK_DISABLE, -) - -##The list of actions and categories for the menu bar. -MENU_BAR_LIST = ( - (gtk.Action('File', '_File', None, None), [ - Actions.FLOW_GRAPH_NEW, - Actions.FLOW_GRAPH_OPEN, - None, - Actions.FLOW_GRAPH_SAVE, - Actions.FLOW_GRAPH_SAVE_AS, - None, - Actions.FLOW_GRAPH_SCREEN_CAPTURE, - None, - Actions.FLOW_GRAPH_CLOSE, - Actions.APPLICATION_QUIT, - ]), - (gtk.Action('Edit', '_Edit', None, None), [ - Actions.FLOW_GRAPH_UNDO, - Actions.FLOW_GRAPH_REDO, - None, - Actions.BLOCK_CUT, - Actions.BLOCK_COPY, - Actions.BLOCK_PASTE, - Actions.ELEMENT_DELETE, - None, - Actions.BLOCK_ROTATE_CCW, - Actions.BLOCK_ROTATE_CW, - None, - Actions.BLOCK_ENABLE, - Actions.BLOCK_DISABLE, - None, - Actions.BLOCK_PARAM_MODIFY, - ]), - (gtk.Action('Build', '_Build', None, None), [ - Actions.FLOW_GRAPH_GEN, - Actions.FLOW_GRAPH_EXEC, - Actions.FLOW_GRAPH_KILL, - ]), - (gtk.Action('Help', '_Help', None, None), [ - Actions.HELP_WINDOW_DISPLAY, - None, - Actions.ABOUT_WINDOW_DISPLAY, - ]), -) - -class Toolbar(gtk.Toolbar): - """The gtk toolbar with actions added from the toolbar list.""" - - def __init__(self): - """ - Parse the list of action names in the toolbar list. - Look up the action for each name in the action list and add it to the toolbar. - """ - gtk.Toolbar.__init__(self) - self.set_style(gtk.TOOLBAR_ICONS) - for action_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 deleted file mode 100644 index 99056252..00000000 --- a/grc/src/gui/BlockTreeWindow.py +++ /dev/null @@ -1,168 +0,0 @@ -""" -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from Constants import DEFAULT_BLOCKS_WINDOW_WIDTH, DND_TARGETS -from .. platforms.gui import Utils -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -NAME_INDEX = 0 -KEY_INDEX = 1 -DOC_INDEX = 2 - -class BlockTreeWindow(gtk.VBox): - """The block selection panel.""" - - def __init__(self, platform, get_flow_graph): - """ - BlockTreeWindow constructor. - Create a tree view of the possible blocks in the platform. - The tree view nodes will be category names, the leaves will be block names. - A mouse double click or button press action will trigger the add block event. - @param platform the particular platform will all block prototypes - @param get_flow_graph get the selected flow graph - """ - gtk.VBox.__init__(self) - self.platform = platform - self.get_flow_graph = get_flow_graph - #make the tree model for holding blocks - self.treestore = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) - self.treeview = gtk.TreeView(self.treestore) - self.treeview.set_enable_search(False) #disable pop up search box - self.treeview.add_events(gtk.gdk.BUTTON_PRESS_MASK) - self.treeview.connect('button_press_event', self._handle_mouse_button_press) - selection = self.treeview.get_selection() - selection.set_mode('single') - selection.connect('changed', self._handle_selection_change) - renderer = gtk.CellRendererText() - column = gtk.TreeViewColumn('Blocks', renderer, text=NAME_INDEX) - self.treeview.append_column(column) - #try to enable the tooltips (available in pygtk 2.12 and above) - try: self.treeview.set_tooltip_column(DOC_INDEX) - except: pass - #setup drag and drop - self.treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, DND_TARGETS, gtk.gdk.ACTION_COPY) - self.treeview.connect('drag-data-get', self._handle_drag_get_data) - #make the scrolled window to hold the tree view - scrolled_window = gtk.ScrolledWindow() - scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scrolled_window.add_with_viewport(self.treeview) - scrolled_window.set_size_request(DEFAULT_BLOCKS_WINDOW_WIDTH, -1) - self.pack_start(scrolled_window) - #add button - self.add_button = gtk.Button(None, gtk.STOCK_ADD) - self.add_button.connect('clicked', self._handle_add_button) - self.pack_start(self.add_button, False) - #map categories to iters, automatic mapping for root - self._categories = {tuple(): None} - #add blocks and categories - self.platform.load_block_tree(self) - #initialize - self._update_add_button() - - ############################################################ - ## Block Tree Methods - ############################################################ - def add_block(self, category, block=None): - """ - Add a block with category to this selection window. - Add only the category when block is None. - @param category the category list or path string - @param block the block object or None - """ - if isinstance(category, str): category = category.split('/') - category = tuple(filter(lambda x: x, category)) #tuple is hashable - #add category and all sub categories - for i, cat_name in enumerate(category): - sub_category = category[:i+1] - if sub_category not in self._categories: - iter = self.treestore.insert_before(self._categories[sub_category[:-1]], None) - self.treestore.set_value(iter, NAME_INDEX, '[ %s ]'%cat_name) - self.treestore.set_value(iter, KEY_INDEX, '') - self.treestore.set_value(iter, DOC_INDEX, Utils.xml_encode('Category: %s'%cat_name)) - self._categories[sub_category] = iter - #add block - if block is None: return - iter = self.treestore.insert_before(self._categories[category], None) - self.treestore.set_value(iter, NAME_INDEX, block.get_name()) - self.treestore.set_value(iter, KEY_INDEX, block.get_key()) - self.treestore.set_value(iter, DOC_INDEX, Utils.xml_encode(block.get_doc() or 'undocumented')) - - ############################################################ - ## 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_drag_get_data(self, widget, drag_context, selection_data, info, time): - """ - Handle a drag and drop by setting the key to the selection object. - This will call the destination handler for drag and drop. - Only call set when the key is valid to ignore DND from categories. - """ - key = self._get_selected_block_key() - if key: selection_data.set(selection_data.target, 8, key) - - def _handle_mouse_button_press(self, widget, event): - """ - Handle the mouse button press. - If a left double click is detected, call add selected block. - """ - if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS: - self._add_selected_block() - - def _handle_selection_change(self, selection): - """ - Handle a selection change in the tree view. - If a selection changes, set the add button sensitive. - """ - self._update_add_button() - - def _handle_add_button(self, widget): - """ - Handle the add button clicked signal. - Call add selected block. - """ - self._add_selected_block() diff --git a/grc/src/gui/Constants.py b/grc/src/gui/Constants.py deleted file mode 100644 index f23ab8b1..00000000 --- a/grc/src/gui/Constants.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import pygtk -pygtk.require('2.0') -import gtk -import os - -##default path for the open/save dialogs -DEFAULT_FILE_PATH = os.getcwd() - -##file extensions -IMAGE_FILE_EXTENSION = '.png' - -##name for new/unsaved flow graphs -NEW_FLOGRAPH_TITLE = 'untitled' - -##main window constraints -MIN_WINDOW_WIDTH = 600 -MIN_WINDOW_HEIGHT = 400 -##dialog constraints -MIN_DIALOG_WIDTH = 500 -MIN_DIALOG_HEIGHT = 500 -##default sizes -DEFAULT_BLOCKS_WINDOW_WIDTH = 100 -DEFAULT_REPORTS_WINDOW_WIDTH = 100 - -##The size of the state saving cache in the flow graph (for undo/redo functionality) -STATE_CACHE_SIZE = 42 - -##Shared targets for drag and drop of blocks -DND_TARGETS = [('STRING', gtk.TARGET_SAME_APP, 0)] diff --git a/grc/src/gui/Dialogs.py b/grc/src/gui/Dialogs.py deleted file mode 100644 index d526b97b..00000000 --- a/grc/src/gui/Dialogs.py +++ /dev/null @@ -1,100 +0,0 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import pygtk -pygtk.require('2.0') -import gtk -from .. platforms.base.Constants import PACKAGE, 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) - -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_name(PACKAGE) - self.set_version(VERSION) - self.set_license(__doc__) - self.set_copyright(__doc__.strip().splitlines()[0]) - 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 -Patrick Mulligan -> 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() - -def HelpDialog(): - MessageDialogHelper( - type=gtk.MESSAGE_INFO, - buttons=gtk.BUTTONS_CLOSE, - title='Help', - markup="""\ -Usage Tips - -Add block: drag and drop or double click a block in the block selection window. -Rotate block: Select a block, press left/right on the keyboard. -Change type: Select a block, press up/down on the keyboard. -Edit parameters: double click on a block in the flow graph. -Make connection: click on the source port of one block, then click on the sink port of another block. -Remove connection: select the connection and press delete, or drag the connection. - -* See the menu for other keyboard shortcuts.""") diff --git a/grc/src/gui/DrawingArea.py b/grc/src/gui/DrawingArea.py deleted file mode 100644 index 6f90049c..00000000 --- a/grc/src/gui/DrawingArea.py +++ /dev/null @@ -1,126 +0,0 @@ -""" -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import pygtk -pygtk.require('2.0') -import gtk -from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT, DND_TARGETS - -class DrawingArea(gtk.DrawingArea): - """ - DrawingArea is the gtk pixel map that graphical elements may draw themselves on. - The drawing area also responds to mouse and key events. - """ - - def __init__(self, flow_graph): - """ - DrawingArea contructor. - Connect event handlers. - @param main_window the main_window containing all flow graphs - """ - self.ctrl_mask = False - self._flow_graph = flow_graph - gtk.DrawingArea.__init__(self) - self.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) - self.connect('realize', self._handle_window_realize) - self.connect('configure-event', self._handle_window_configure) - self.connect('expose-event', self._handle_window_expose) - self.connect('motion-notify-event', self._handle_mouse_motion) - self.connect('button-press-event', self._handle_mouse_button_press) - self.connect('button-release-event', self._handle_mouse_button_release) - self.add_events( - gtk.gdk.BUTTON_PRESS_MASK | \ - gtk.gdk.POINTER_MOTION_MASK | \ - gtk.gdk.BUTTON_RELEASE_MASK | \ - gtk.gdk.LEAVE_NOTIFY_MASK | \ - gtk.gdk.ENTER_NOTIFY_MASK - ) - #setup drag and drop - self.drag_dest_set(gtk.DEST_DEFAULT_ALL, DND_TARGETS, gtk.gdk.ACTION_COPY) - self.connect('drag-data-received', self._handle_drag_data_received) - #setup the focus flag - self._focus_flag = False - self.get_focus_flag = lambda: self._focus_flag - def _handle_focus_event(widget, event, focus_flag): self._focus_flag = focus_flag - self.connect('leave-notify-event', _handle_focus_event, False) - self.connect('enter-notify-event', _handle_focus_event, True) - - def new_pixmap(self, width, height): return gtk.gdk.Pixmap(self.window, width, height, -1) - - ########################################################################## - ## Handlers - ########################################################################## - def _handle_drag_data_received(self, widget, drag_context, x, y, selection_data, info, time): - """ - Handle a drag and drop by adding a block at the given coordinate. - """ - self._flow_graph.add_new_block(selection_data.data, (x, y)) - - def _handle_mouse_button_press(self, widget, event): - """ - Forward button click information to the flow graph. - """ - self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK - self._flow_graph.handle_mouse_button_press( - left_click=(event.button == 1), - double_click=(event.type == gtk.gdk._2BUTTON_PRESS), - coordinate=(event.x, event.y), - ) - - 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._flow_graph.handle_mouse_button_release( - left_click=(event.button == 1), - coordinate=(event.x, event.y), - ) - - def _handle_mouse_motion(self, widget, event): - """ - Forward mouse motion information to the flow graph. - """ - self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK - self._flow_graph.handle_mouse_motion( - coordinate=(event.x, event.y), - ) - - def _handle_window_realize(self, widget): - """ - Called when the window is realized. - Update the flowgraph, which calls new pixmap. - """ - self._flow_graph.update() - - def _handle_window_configure(self, widget, event): - """ - Called when the window is resized. - Create a new pixmap for background buffer. - """ - self._pixmap = self.new_pixmap(*self.get_size_request()) - - def _handle_window_expose(self, widget, event): - """ - Called when window is exposed, or queue_draw is called. - Double buffering: draw to pixmap, then draw pixmap to window. - """ - gc = self.window.new_gc() - self._flow_graph.draw(gc, self._pixmap) - self.window.draw_drawable(gc, self._pixmap, 0, 0, 0, 0, -1, -1) diff --git a/grc/src/gui/FileDialogs.py b/grc/src/gui/FileDialogs.py deleted file mode 100644 index 7c10d984..00000000 --- a/grc/src/gui/FileDialogs.py +++ /dev/null @@ -1,160 +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 -""" - -import pygtk -pygtk.require('2.0') -import gtk -from Dialogs import MessageDialogHelper -from Constants import \ - DEFAULT_FILE_PATH, IMAGE_FILE_EXTENSION, \ - NEW_FLOGRAPH_TITLE -import Preferences -from os import path - -OPEN_FLOW_GRAPH = 'open flow graph' -SAVE_FLOW_GRAPH = 'save flow graph' -SAVE_IMAGE = 'save image' - -##the filter for flow graph files -def get_flow_graph_files_filter(): - filter = gtk.FileFilter() - filter.set_name('Flow Graph Files') - filter.add_pattern('*'+Preferences.file_extension()) - filter.add_pattern('*.xml') #TEMP - return filter - -##the filter for image files -def get_image_files_filter(): - filter = gtk.FileFilter() - filter.set_name('Image Files') - filter.add_pattern('*'+IMAGE_FILE_EXTENSION) - return filter - -##the filter for all files -def get_all_files_filter(): - filter = gtk.FileFilter() - filter.set_name('All Files') - filter.add_pattern('*') - return filter - -class FileDialogHelper(gtk.FileChooserDialog): - """ - A wrapper class for the gtk file chooser dialog. - Implement a file chooser dialog with only necessary parameters. - """ - - def __init__(self, action, title): - """ - FileDialogHelper contructor. - Create a save or open dialog with cancel and ok buttons. - Use standard settings: no multiple selection, local files only, and the * filter. - @param action gtk.FILE_CHOOSER_ACTION_OPEN or gtk.FILE_CHOOSER_ACTION_SAVE - @param title the title of the dialog (string) - """ - ok_stock = {gtk.FILE_CHOOSER_ACTION_OPEN : 'gtk-open', gtk.FILE_CHOOSER_ACTION_SAVE : 'gtk-save'}[action] - gtk.FileChooserDialog.__init__(self, title, None, action, ('gtk-cancel', gtk.RESPONSE_CANCEL, ok_stock, gtk.RESPONSE_OK)) - self.set_select_multiple(False) - self.set_local_only(True) - self.add_filter(get_all_files_filter()) - -class FileDialog(FileDialogHelper): - """A dialog box to save or open flow graph files. This is a base class, do not use.""" - - def __init__(self, current_file_path=''): - """ - FileDialog constructor. - @param current_file_path the current directory or path to the open flow graph - """ - if not current_file_path: current_file_path = path.join(DEFAULT_FILE_PATH, NEW_FLOGRAPH_TITLE + Preferences.file_extension()) - if self.type == OPEN_FLOW_GRAPH: - FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_OPEN, 'Open a Flow Graph from a File...') - self.add_and_set_filter(get_flow_graph_files_filter()) - self.set_select_multiple(True) - elif self.type == SAVE_FLOW_GRAPH: - FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save a Flow Graph to a File...') - self.add_and_set_filter(get_flow_graph_files_filter()) - self.set_current_name(path.basename(current_file_path)) #show the current filename - elif self.type == SAVE_IMAGE: - FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save a Flow Graph Screen Shot...') - self.add_and_set_filter(get_image_files_filter()) - current_file_path = current_file_path + IMAGE_FILE_EXTENSION - self.set_current_name(path.basename(current_file_path)) #show the current filename - self.set_current_folder(path.dirname(current_file_path)) #current directory - - def add_and_set_filter(self, filter): - """ - Add the gtk file filter to the list of filters and set it as the default file filter. - @param filter a gtk file filter. - """ - self.add_filter(filter) - self.set_filter(filter) - - def get_rectified_filename(self): - """ - Run the dialog and get the filename. - If this is a save dialog and the file name is missing the extension, append the file extension. - If the file name with the extension already exists, show a overwrite dialog. - If this is an open dialog, return a list of filenames. - @return the complete file path - """ - if gtk.FileChooserDialog.run(self) != gtk.RESPONSE_OK: return None #response was cancel - ############################################# - # Handle Save Dialogs - ############################################# - if self.type in (SAVE_FLOW_GRAPH, SAVE_IMAGE): - filename = self.get_filename() - extension = { - SAVE_FLOW_GRAPH: Preferences.file_extension(), - SAVE_IMAGE: IMAGE_FILE_EXTENSION, - }[self.type] - #append the missing file extension if the filter matches - if path.splitext(filename)[1].lower() != extension: filename += extension - self.set_current_name(path.basename(filename)) #show the filename with extension - if path.exists(filename): #ask the user to confirm overwrite - if MessageDialogHelper( - gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, 'Confirm Overwrite!', - '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 deleted file mode 100644 index bd5f73a8..00000000 --- a/grc/src/gui/MainWindow.py +++ /dev/null @@ -1,299 +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 -""" - -from Constants import \ - NEW_FLOGRAPH_TITLE, DEFAULT_REPORTS_WINDOW_WIDTH -from Actions import \ - APPLICATION_QUIT, FLOW_GRAPH_KILL, \ - FLOW_GRAPH_SAVE, get_accel_group -import pygtk -pygtk.require('2.0') -import gtk -import Bars -from BlockTreeWindow import BlockTreeWindow -from Dialogs import TextDisplay, MessageDialogHelper -from NotebookPage import NotebookPage -import Preferences -import Messages -import 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() - self.hpaned = gtk.HPaned() - self.add(vbox) - #create the menu bar and toolbar - self.add_accel_group(get_accel_group()) - vbox.pack_start(Bars.MenuBar(), False) - vbox.pack_start(Bars.Toolbar(), False) - vbox.pack_start(self.hpaned) - #create the notebook - self.notebook = gtk.Notebook() - self.page_to_be_closed = None - self.current_page = None - self.notebook.set_show_border(False) - self.notebook.set_scrollable(True) #scroll arrows for page tabs - self.notebook.connect('switch-page', self._handle_page_change) - #setup containers - self.flow_graph_vpaned = gtk.VPaned() - #flow_graph_box.pack_start(self.scrolled_window) - self.flow_graph_vpaned.pack1(self.notebook) - self.hpaned.pack1(self.flow_graph_vpaned) - self.hpaned.pack2(BlockTreeWindow(platform, self.get_flow_graph), False) #dont allow resize - #create the reports window - self.text_display = TextDisplay() - #house the reports in a scrolled window - self.reports_scrolled_window = gtk.ScrolledWindow() - self.reports_scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.reports_scrolled_window.add_with_viewport(self.text_display) - self.reports_scrolled_window.set_size_request(-1, DEFAULT_REPORTS_WINDOW_WIDTH) - self.flow_graph_vpaned.pack2(self.reports_scrolled_window, False) #dont allow resize - #load preferences and show the main window - Preferences.load(platform) - self.resize(*Preferences.main_window_size()) - self.flow_graph_vpaned.set_position(Preferences.reports_window_position()) - self.hpaned.set_position(Preferences.blocks_window_position()) - self.show_all() - - ############################################################ - # Event Handlers - ############################################################ - - def _quit(self, window, event): - """ - Handle the delete event from the main window. - Generated by pressing X to close, alt+f4, or right click+close. - This method in turns calls the state handler to quit. - @return true - """ - 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') - - ############################################################ - # 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() - 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.main_window_size(self.get_size()) - Preferences.reports_window_position(self.flow_graph_vpaned.get_position()) - Preferences.blocks_window_position(self.hpaned.get_position()) - Preferences.save() - return True - - def close_page(self, ensure=True): - """ - Close the current page. - If the notebook becomes empty, and ensure is true, - call new page upon exit to ensure that at least one page exists. - @param ensure boolean - """ - if not self.page_to_be_closed: self.page_to_be_closed = self.get_page() - #show the page if it has an executing flow graph or is unsaved - if self.page_to_be_closed.get_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 - """ - title = ''.join(( - self._platform.get_name(), - ' - Editing: ', - (self.get_page().get_file_path() or NEW_FLOGRAPH_TITLE), - (self.get_page().get_saved() and ' ' or '*'), #blank must be non empty - (self.get_page().get_read_only() and ' (read-only)' or ''), - ) - ) - gtk.Window.set_title(self, title) - #set tab titles - for page in self._get_pages(): - #get filename and strip out file extension - title = os.path.splitext(os.path.basename(page.get_file_path()))[0] - page.set_text(''.join(( - (title or NEW_FLOGRAPH_TITLE), - (page.get_saved() and ' ' or '*'), #blank must be non empty - (page.get_read_only() and ' (ro)' or ''), - ) - ) - ) - #show/hide notebook tabs - self.notebook.set_show_tabs(len(self._get_pages()) > 1) - - def get_page(self): - """ - Get the selected page. - @return the selected page - """ - return self.current_page - - def get_flow_graph(self): - """ - Get the selected flow graph. - @return the selected flow graph - """ - return self.get_page().get_flow_graph() - - def get_focus_flag(self): - """ - Get the focus flag from the current page. - @return the focus flag - """ - return self.get_page().get_drawing_area().get_focus_flag() - - ############################################################ - # Helpers - ############################################################ - - def _set_page(self, page): - """ - Set the current page. - @param page the page widget - """ - self.current_page = page - self.notebook.set_current_page(self.notebook.page_num(self.current_page)) - - def _save_changes(self): - """ - Save changes to flow graph? - @return true if yes - """ - return MessageDialogHelper( - gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, 'Unsaved Changes!', - 'Would you like to save changes before closing?' - ) == gtk.RESPONSE_YES - - def _get_files(self): - """ - Get the file names for all the pages, in order. - @return list of file paths - """ - return map(lambda page: page.get_file_path(), self._get_pages()) - - def _get_pages(self): - """ - Get a list of all pages in the notebook. - @return list of pages - """ - return [self.notebook.get_nth_page(page_num) for page_num in range(self.notebook.get_n_pages())] diff --git a/grc/src/gui/Makefile.am b/grc/src/gui/Makefile.am deleted file mode 100644 index a6639af4..00000000 --- a/grc/src/gui/Makefile.am +++ /dev/null @@ -1,41 +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 - -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 deleted file mode 100644 index e8939402..00000000 --- a/grc/src/gui/Messages.py +++ /dev/null @@ -1,105 +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 -""" - -from .. platforms.base.Constants import PACKAGE, 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 %s %s >>>\n"""%(PACKAGE, VERSION)) - -def send_page_switch(file_path): - send('\nShowing: "%s"\n'%file_path) - -################# functions for loading flow graphs ######################################## -def send_start_load(file_path): - send('\nLoading: "%s"'%file_path + '\n') - -def send_error_load(error): - send('>>> Error: %s\n'%error) - traceback.print_exc() - -def send_end_load(): - send('>>> Done\n') - -def send_fail_load(error): - send('Error: %s\n'%error) - send('>>> 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('>>> Error: Cannot create connection.\n') - -################# functions for preferences ######################################## -def send_fail_load_preferences(prefs_file_path): - send('>>> Error: Cannot load preferences file: "%s"\n'%prefs_file_path) - -def send_fail_save_preferences(prefs_file_path): - send('>>> Error: Cannot save preferences file: "%s"\n'%prefs_file_path) - -################# functions for warning ######################################## -def send_warning(warning): - send('>>> Warning: %s\n'%warning) diff --git a/grc/src/gui/NotebookPage.py b/grc/src/gui/NotebookPage.py deleted file mode 100644 index a3ec5b4e..00000000 --- a/grc/src/gui/NotebookPage.py +++ /dev/null @@ -1,197 +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 -""" - -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 -from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT -from DrawingArea import DrawingArea -import os - -############################################################ -## Notebook Page -############################################################ - -class NotebookPage(gtk.HBox): - """A page in the notebook.""" - - def __init__(self, main_window, flow_graph, file_path=''): - """ - Page constructor. - @param main_window main window - @param file_path path to a flow graph file - """ - self._flow_graph = flow_graph - self.set_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() - open(file_path, 'r') #test open - ############################################################ - 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) - #initialize page gui - gtk.HBox.__init__(self, False, 0) - self.show() - #tab box to hold label and close button - self.tab = gtk.HBox(False, 0) - #setup tab label - self.label = gtk.Label() - self.tab.pack_start(self.label, False) - #setup button image - image = gtk.Image() - image.set_from_stock('gtk-close', gtk.ICON_SIZE_MENU) - #setup image box - image_box = gtk.HBox(False, 0) - image_box.pack_start(image, True, False, 0) - #setup the button - button = gtk.Button() - button.connect("clicked", self._handle_button) - button.set_relief(gtk.RELIEF_NONE) - button.add(image_box) - #button size - w, h = gtk.icon_size_lookup_for_settings(button.get_settings(), gtk.ICON_SIZE_MENU) - button.set_size_request(w+6, h+6) - self.tab.pack_start(button, False) - self.tab.show_all() - #setup scroll window and drawing area - self.scrolled_window = gtk.ScrolledWindow() - self.scrolled_window.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) - self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.drawing_area = DrawingArea(self.get_flow_graph()) - self.scrolled_window.add_with_viewport(self.get_drawing_area()) - self.pack_start(self.scrolled_window) - #inject drawing area and handle states into flow graph - self.get_flow_graph().drawing_area = self.get_drawing_area() - self.get_flow_graph().handle_states = main_window.handle_states - self.show_all() - - def get_drawing_area(self): return self.drawing_area - - def get_generator(self): - """ - Get the generator object for this flow graph. - @return generator - """ - return self.get_flow_graph().get_parent().get_generator()( - self.get_flow_graph(), - self.get_file_path(), - ) - - def _handle_button(self, button): - """ - The button was clicked. - Make the current page selected, then close. - @param the button - """ - self.main_window.page_to_be_closed = self - 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_read_only(self): - """ - Get the read-only state of the file. - Always false for empty path. - @return true for read-only - """ - if not self.get_file_path(): return False - return os.path.exists(self.get_file_path()) and \ - not os.access(self.get_file_path(), os.W_OK) - - def get_file_path(self): - """ - Get the file path for the flow graph. - @return the file path or '' - """ - return self.file_path - - def set_file_path(self, file_path=''): - """ - Set the file path, '' for no file path. - @param file_path file path string - """ - if file_path: self.file_path = os.path.abspath(file_path) - else: self.file_path = '' - - def get_saved(self): - """ - Get the saved status for the flow graph. - @return true if saved - """ - return self.saved - - def set_saved(self, saved=True): - """ - Set the saved status. - @param saved boolean status - """ - self.saved = saved - - def get_state_cache(self): - """ - Get the state cache for the flow graph. - @return the state cache - """ - return self.state_cache diff --git a/grc/src/gui/ParamsDialog.py b/grc/src/gui/ParamsDialog.py deleted file mode 100644 index 6cc42e8f..00000000 --- a/grc/src/gui/ParamsDialog.py +++ /dev/null @@ -1,144 +0,0 @@ -""" -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import pygtk -pygtk.require('2.0') -import gtk - -from Dialogs import TextDisplay -from Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT - -def get_title_label(title): - """ - Get a title label for the params window. - The title will be bold, underlined, and left justified. - @param title the text of the title - @return a gtk object - """ - label = gtk.Label() - label.set_markup('\n%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, - title='Properties: %s'%block.get_name(), - buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE), - ) - self.block = block - 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_box = gtk.VBox() - self._error_messages_text_display = TextDisplay() - self._error_box.pack_start(gtk.Label(), False, False, 7) #spacing - self._error_box.pack_start(get_title_label('Error Messages'), False) - self._error_box.pack_start(self._error_messages_text_display, False) - #Docs for the block - self._docs_box = err_box = gtk.VBox() - self._docs_text_display = TextDisplay() - self._docs_box.pack_start(gtk.Label(), False, False, 7) #spacing - self._docs_box.pack_start(get_title_label('Documentation'), False) - self._docs_box.pack_start(self._docs_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) - #Add the error and docs box - vbox.pack_start(self._error_box, False) - vbox.pack_start(self._docs_box, False) - #connect and show - 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() - - def _update(self): - """ - Update the error messages box. - Hide the box if there are no errors. - Update the documentation block. - Hide the box if there are no docs. - """ - #update the errors box - if self.block.is_valid(): self._error_box.hide() - else: self._error_box.show() - messages = '\n\n'.join(self.block.get_error_messages()) - self._error_messages_text_display.set_text(messages) - #update the docs box - if self.block.get_doc(): self._docs_box.show() - else: self._docs_box.hide() - self._docs_text_display.set_text(self.block.get_doc()) - - def _handle_key_press(self, widget, event): - """ - Handle key presses from the keyboard. - Call the ok response when enter is pressed. - @return false to forward the keypress - """ - 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 - """ - #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() - #update - self._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 deleted file mode 100644 index 1d89920d..00000000 --- a/grc/src/gui/Preferences.py +++ /dev/null @@ -1,86 +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 -""" - -import ConfigParser -import os - -_platform = None -_config_parser = ConfigParser.ConfigParser() - -def file_extension(): return '.'+_platform.get_key() -def _prefs_file(): return os.path.join(os.path.expanduser('~'), file_extension()) - -def load(platform): - global _platform - _platform = platform - #create sections - _config_parser.add_section('main') - _config_parser.add_section('files_open') - try: _config_parser.read(_prefs_file()) - except: pass -def save(): - try: _config_parser.write(open(_prefs_file(), 'w')) - except: pass - -########################################################################### -# Special methods for specific program functionalities -########################################################################### - -def main_window_size(size=None): - if size is not None: - _config_parser.set('main', 'main_window_width', size[0]) - _config_parser.set('main', 'main_window_height', size[1]) - else: - try: return ( - _config_parser.getint('main', 'main_window_width'), - _config_parser.getint('main', 'main_window_height'), - ) - except: return (1, 1) - -def file_open(file=None): - if file is not None: _config_parser.set('main', 'file_open', file) - else: - try: return _config_parser.get('main', 'file_open') - except: return '' - -def files_open(files=None): - if files is not None: - _config_parser.remove_section('files_open') #clear section - _config_parser.add_section('files_open') - for i, file in enumerate(files): - _config_parser.set('files_open', 'file_open_%d'%i, file) - else: - files = list() - i = 0 - while True: - try: files.append(_config_parser.get('files_open', 'file_open_%d'%i)) - except: return files - i = i + 1 - -def reports_window_position(pos=None): - if pos is not None: _config_parser.set('main', 'reports_window_position', pos) - else: - try: return _config_parser.getint('main', 'reports_window_position') or 1 #greater than 0 - except: return -1 - -def blocks_window_position(pos=None): - if pos is not None: _config_parser.set('main', 'blocks_window_position', pos) - else: - try: return _config_parser.getint('main', 'blocks_window_position') or 1 #greater than 0 - except: return -1 diff --git a/grc/src/gui/StateCache.py b/grc/src/gui/StateCache.py deleted file mode 100644 index 04b18b18..00000000 --- a/grc/src/gui/StateCache.py +++ /dev/null @@ -1,92 +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 -""" - -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 deleted file mode 100644 index 8b137891..00000000 --- a/grc/src/gui/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/grc/src/platforms/Makefile.am b/grc/src/platforms/Makefile.am deleted file mode 100644 index 1d3c385c..00000000 --- a/grc/src/platforms/Makefile.am +++ /dev/null @@ -1,31 +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 = \ - 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 deleted file mode 100644 index 8b137891..00000000 --- a/grc/src/platforms/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/grc/src/platforms/base/Block.py b/grc/src/platforms/base/Block.py deleted file mode 100644 index 25688472..00000000 --- a/grc/src/platforms/base/Block.py +++ /dev/null @@ -1,259 +0,0 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from ... 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 __call__ or () method can return the param evaluated to a raw python data type. - """ - - def __init__(self, param): - UserDict.__init__(self) - self._param = param - if param.is_enum(): - for key in param.get_opt_keys(): - self[key] = str(param.get_opt(key)) - - def __str__(self): - return str(self._param.to_code()) - - def __call__(self): - return self._param.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 - """ - #build the block - Element.__init__(self, flow_graph) - #grab the data - params = n.findall('param') - sources = n.findall('source') - sinks = n.findall('sink') - self._name = n.find('name') - self._key = n.find('key') - self._category = n.find('category') or '' - self._block_wrapper_path = n.find('block_wrapper_path') - #create the param objects - self._params = odict() - #add the id param - self._params['id'] = self.get_parent().get_parent().Param( - self, - odict({ - 'name': 'ID', - 'key': 'id', - 'type': 'id', - }) - ) - self._params['_enabled'] = self.get_parent().get_parent().Param( - self, - odict({ - '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. - """ - for c in self.get_params() + self.get_ports() + self.get_connections(): - try: assert(c.is_valid()) - except AssertionError: - for msg in c.get_error_messages(): - self._add_error_message('>>> %s:\n\t%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_name(self): return self._name - def get_key(self): return self._key - def get_category(self): return self._category - def get_doc(self): return '' - def get_ports(self): return self.get_sources() + self.get_sinks() - def get_block_wrapper_path(self): return self._block_wrapper_path - - ############################################## - # 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) - - ############################################## - # Controller Modify - ############################################## - def type_controller_modify(self, direction): - """ - Change the type controller. - @param direction +1 or -1 - @return true for change - """ - changed = False - type_param = None - for param in filter(lambda p: p.is_enum(), self.get_params()): - children = self.get_ports() + self.get_params() - #priority to the type controller - if param.get_key() in ' '.join(map(lambda p: p._type, children)): type_param = param - #use param if type param is unset - if not type_param: type_param = param - if type_param: - #try to increment the enum by direction - try: - keys = type_param.get_option_keys() - old_index = keys.index(type_param.get_value()) - new_index = (old_index + direction + len(keys))%len(keys) - type_param.set_value(keys[new_index]) - changed = True - except: pass - return changed - - def port_controller_modify(self, direction): - """ - Change the port controller. - @param direction +1 or -1 - @return true for change - """ - return False - - ############################################## - ## Import/Export Methods - ############################################## - def export_data(self): - """ - Export this block's params to nested data. - @return a nested data odict - """ - n = odict() - n['key'] = self.get_key() - n['param'] = map(lambda p: p.export_data(), self.get_params()) - return n - - def import_data(self, n): - """ - Import this block's params from nested data. - Any param keys that do not exist will be ignored. - @param n the nested data odict - """ - params_n = n.findall('param') - for param_n in params_n: - key = param_n.find('key') - value = param_n.find('value') - #the key must exist in this block's params - if key in self.get_param_keys(): - self.get_param(key).set_value(value) - self.validate() diff --git a/grc/src/platforms/base/Connection.py b/grc/src/platforms/base/Connection.py deleted file mode 100644 index b8b75ac1..00000000 --- a/grc/src/platforms/base/Connection.py +++ /dev/null @@ -1,94 +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 -""" - -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 - assert(source and sink) - #ensure that this connection (source -> sink) is unique - for connection in self.get_parent().get_connections(): - assert not (connection.get_source() is source and connection.get_sink() is sink) - self._source = source - self._sink = sink - - def __str__(self): - return 'Connection (\n\t%s\n\t\t%s\n\t%s\n\t\t%s\n)'%( - self.get_source().get_parent(), - self.get_source(), - self.get_sink().get_parent(), - self.get_sink(), - ) - - def is_connection(self): return True - - def validate(self): - """ - Validate the connections. - The ports must match in type. - """ - 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 deleted file mode 100644 index da958a6f..00000000 --- a/grc/src/platforms/base/Constants.py.in +++ /dev/null @@ -1,30 +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 -""" - -import os - -#package and version constants -PACKAGE = '@PACKAGE@' -VERSION = '@VERSION@' - -#setup paths -PKG_DIR = os.environ.get('GR_DATADIR', '@pkgdatadir@') -DATA_DIR = os.path.join(PKG_DIR, '@reldatadir@') -FLOW_GRAPH_DTD = os.path.join(DATA_DIR, 'flow_graph.dtd') -BLOCK_TREE_DTD = os.path.join(DATA_DIR, 'block_tree.dtd') diff --git a/grc/src/platforms/base/Element.py b/grc/src/platforms/base/Element.py deleted file mode 100644 index a16be912..00000000 --- a/grc/src/platforms/base/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 -""" - -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 - if self.get_enabled(): - try: self.validate() - except: pass - return not self.get_error_messages() - - def get_enabled(self): return True - - 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 deleted file mode 100644 index 6aeef2fa..00000000 --- a/grc/src/platforms/base/FlowGraph.py +++ /dev/null @@ -1,224 +0,0 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from ... 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 - """ - #initialize - Element.__init__(self, platform) - #inital blank import - self.import_data() - - def _get_unique_id(self, base_id=''): - """ - Get a unique id starting with the base id. - @param base_id the id starts with this and appends a count - @return a unique id - """ - index = 0 - while True: - id = '%s_%d'%(base_id, index) - index = index + 1 - #make sure that the id is not used by another block - if not filter(lambda b: b.get_id() == id, self.get_blocks()): return id - - def __str__(self): return 'FlowGraph - %s(%s)'%(self.get_option('title'), self.get_option('id')) - - def get_option(self, key): - """ - Get the option for a given key. - The option comes from the special options block. - @param key the param key for the options block - @return the value held by that param - """ - return self._options_block.get_param(key).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 (only once). - @return the element list - """ - options_block_count = self._elements.count(self._options_block) - if not options_block_count: - self._elements.append(self._options_block) - for i in range(options_block_count-1): - self._elements.remove(self._options_block) - return self._elements - - def get_enabled_blocks(self): - """ - Get a list of all blocks that are enabled. - @return a list of blocks - """ - return filter(lambda b: b.get_enabled(), self.get_blocks()) - - def get_enabled_connections(self): - """ - Get a list of all connections that are enabled. - @return a list of connections - """ - return filter(lambda c: c.get_enabled(), self.get_connections()) - - def get_new_block(self, key): - """ - Get a new block of the specified key. - Add the block to the list of elements. - @param key the block key - @return the new block or None if not found - """ - 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(self.remove_element, port.get_connections()) - self.get_elements().remove(element) - - def evaluate(self, expr): - """ - Evaluate the expression. - @param expr the string expression - @throw NotImplementedError - """ - raise NotImplementedError - - 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 odict({'flow_graph': n}) - - def import_data(self, n=None): - """ - Import blocks and connections into this flow graph. - Clear this flowgraph of all previous blocks and connections. - Any blocks or connections in error will be ignored. - @param n the nested data odict - """ - #remove previous elements - self._elements = list() - #use blank data if none provided - fg_n = n and n.find('flow_graph') or odict() - blocks_n = fg_n.findall('block') - connections_n = fg_n.findall('connection') - #create option block - self._options_block = self.get_parent().get_new_block(self, 'options') - #build the blocks - for block_n in blocks_n: - key = block_n.find('key') - if key == 'options': block = self._options_block - else: block = self.get_new_block(key) - #only load the block when the block key was valid - if block: block.import_data(block_n) - else: Messages.send_error_load('Block key "%s" not found in %s'%(key, self.get_parent())) - #build the connections - for connection_n in connections_n: - #try to make the connection - try: - #get the block ids - source_block_id = connection_n.find('source_block_id') - sink_block_id = connection_n.find('sink_block_id') - #get the port keys - source_key = connection_n.find('source_key') - sink_key = connection_n.find('sink_key') - #verify the blocks - block_ids = map(lambda b: b.get_id(), self.get_blocks()) - 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 deleted file mode 100644 index 805c7b2b..00000000 --- a/grc/src/platforms/base/Makefile.am +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2008,2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -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 - -Constants.py: $(srcdir)/Constants.py.in Makefile - sed \ - -e 's|@PACKAGE[@]|$(PACKAGE)|g' \ - -e 's|@VERSION[@]|$(VERSION)|g' \ - -e 's|@pkgdatadir[@]|$(pkgdatadir)|g' \ - -e 's|@reldatadir[@]|$(grc_base_data_reldir)|g' \ - $< > $@ - -EXTRA_DIST = $(srcdir)/Constants.py.in -BUILT_SOURCES = Constants.py diff --git a/grc/src/platforms/base/Param.py b/grc/src/platforms/base/Param.py deleted file mode 100644 index 81783c79..00000000 --- a/grc/src/platforms/base/Param.py +++ /dev/null @@ -1,271 +0,0 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from ... utils import odict -from Element import Element -import pygtk -pygtk.require('2.0') -import gtk - -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 - def set_color(self, color): pass - -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() - def set_color(self, color): self.entry.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color)) - -class EnumParam(InputParam): - """Provide an entry box for Enum types with a drop down menu.""" - - def __init__(self, *args, **kwargs): - InputParam.__init__(self, *args, **kwargs) - self._input = gtk.combo_box_new_text() - for option in self.param.get_options(): self._input.append_text(option.get_name()) - self._input.set_active(self.param.get_option_keys().index(self.param.get_value())) - self._input.connect('changed', self._handle_changed) - self.pack_start(self._input, False) - def get_text(self): return self.param.get_option_keys()[self._input.get_active()] - -class EnumEntryParam(InputParam): - """Provide an entry box and drop down menu for Raw Enum types.""" - - def __init__(self, *args, **kwargs): - InputParam.__init__(self, *args, **kwargs) - self._input = gtk.combo_box_entry_new_text() - for option in self.param.get_options(): self._input.append_text(option.get_name()) - try: self._input.set_active(self.param.get_option_keys().index(self.param.get_value())) - except: - self._input.set_active(-1) - self._input.get_child().set_text(self.param.get_value()) - self._input.connect('changed', self._handle_changed) - self._input.get_child().connect('changed', self._handle_changed) - self.pack_start(self._input, False) - def get_text(self): - if self._input.get_active() == -1: return self._input.get_child().get_text() - return self.param.get_option_keys()[self._input.get_active()] - def set_color(self, color): - if self._input.get_active() == -1: #custom entry, use color - self._input.get_child().modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color)) - else: #from enum, make white background - self._input.get_child().modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse('#ffffff')) - -class Option(Element): - - def __init__(self, param, n): - Element.__init__(self, param) - self._name = n.find('name') - self._key = n.find('key') - self._opts = dict() - opts = n.findall('opt') - #test against opts when non enum - try: assert self.get_parent().is_enum() or not opts - except AssertionError: self._exit_with_error('Options for non-enum types cannot have sub-options') - #extract opts - for opt in opts: - #separate the key:value - try: key, value = opt.split(':') - except: 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() - -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 - self._name = n.find('name') - self._key = n.find('key') - value = n.find('value') or '' - self._type = n.find('type') - self._hide = n.find('hide') or '' - #build the param - Element.__init__(self, block) - #create the Option objects from the n data - self._options = odict() - for option in map(lambda o: Option(self, o), n.findall('option')): - 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.is_enum(): - #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 get_color(self): return '#FFFFFF' - def __str__(self): return 'Param - %s(%s)'%(self.get_name(), self.get_key()) - def is_param(self): return True - def get_name(self): return self._name - def get_key(self): return self._key - def get_hide(self): return self.get_parent().resolve_dependencies(self._hide) - - 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 __repr__(self): - """ - Get the repr (nice string format) for this param. - Just return the value (special case enum). - Derived classes can handle complex formatting. - @return the string representation - """ - if self.is_enum(): return self.get_option(self.get_value()).get_name() - return self.get_value() - - def get_input_class(self): - """ - Get the graphical gtk class to represent this parameter. - An enum requires and combo parameter. - A non-enum with options gets a combined entry/combo parameter. - All others get a standard entry parameter. - @return gtk input class - """ - if self.is_enum(): return EnumParam - if self.get_options(): return EnumEntryParam - return EntryParam - - ############################################## - # 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 deleted file mode 100644 index 35227d99..00000000 --- a/grc/src/platforms/base/Platform.py +++ /dev/null @@ -1,143 +0,0 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import os -from ... utils import ParseXML -from Element import Element as _Element -from FlowGraph import FlowGraph as _FlowGraph -from Connection import Connection as _Connection -from Block import Block as _Block -from Port import Port as _Port -from Param import Param as _Param -from Constants import BLOCK_TREE_DTD - -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_blocks(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_blocks(os.path.join(dirpath, filename)) - - def _load_blocks(self, f): - """ - Load the block wrappers from the file path. - The block wrapper must pass validation. - 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).find('block') - #inject block wrapper path - n['block_wrapper_path'] = f - 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 = parent + [cat_n.find('name')] - block_tree.add_block(parent) - #recursive call to load sub categories - map(lambda c: load_category(c, parent), cat_n.findall('cat')) - #add blocks in this category - for block_key in cat_n.findall('block'): - block_tree.add_block(parent, self.get_block(block_key)) - #load the block tree - f = self._block_tree - try: ParseXML.validate_dtd(f, 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).find('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 deleted file mode 100644 index f46a8119..00000000 --- a/grc/src/platforms/base/Port.py +++ /dev/null @@ -1,80 +0,0 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from Element import Element - -class 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(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 get_enabled_connections(self): - """ - Get all enabled connections that use this port. - @return a list of connection objects - """ - return filter(lambda c: c.get_enabled(), self.get_connections()) diff --git a/grc/src/platforms/base/__init__.py b/grc/src/platforms/base/__init__.py deleted file mode 100644 index 8b137891..00000000 --- a/grc/src/platforms/base/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/grc/src/platforms/gui/Block.py b/grc/src/platforms/gui/Block.py deleted file mode 100644 index 862a5939..00000000 --- a/grc/src/platforms/gui/Block.py +++ /dev/null @@ -1,199 +0,0 @@ -""" -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from Element import Element -import Utils -import Colors -from ... utils import odict -from Constants import BORDER_PROXIMITY_SENSITIVITY -from Constants import \ - BLOCK_LABEL_PADDING, \ - PORT_SEPARATION, LABEL_SEPARATION, \ - PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS -import pygtk -pygtk.require('2.0') -import gtk - -BLOCK_MARKUP_TMPL="""\ -#set $foreground = $block.is_valid() and 'black' or 'red' -$encode($block.get_name())""" - -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, - odict({ - 'name': 'GUI Coordinate', - 'key': '_coordinate', - 'type': 'raw', - 'value': '(0, 0)', - 'hide': 'all', - }) - ) - self._params['_rotation'] = self.get_parent().get_parent().Param( - self, - odict({ - 'name': 'GUI Rotation', - 'key': '_rotation', - 'type': 'raw', - 'value': '0', - 'hide': 'all', - }) - ) - Element.__init__(self) - - def get_coordinate(self): - """ - Get the coordinate from the position param. - @return the coordinate tuple (x, y) or (0, 0) if failure - """ - try: #should evaluate to tuple - coor = eval(self.get_param('_coordinate').get_value()) - x, y = map(int, coor) - fgW,fgH = self.get_parent().get_size() - if x <= 0: - x = 0 - elif x >= fgW - BORDER_PROXIMITY_SENSITIVITY: - x = fgW - BORDER_PROXIMITY_SENSITIVITY - if y <= 0: - y = 0 - elif y >= fgH - BORDER_PROXIMITY_SENSITIVITY: - y = fgH - BORDER_PROXIMITY_SENSITIVITY - return (x, y) - except: - self.set_coordinate((0, 0)) - return (0, 0) - - def set_coordinate(self, coor): - """ - Set the coordinate into the position param. - @param coor the coordinate tuple (x, y) - """ - self.get_param('_coordinate').set_value(str(coor)) - - def get_rotation(self): - """ - Get the rotation from the position param. - @return the rotation in degrees or 0 if failure - """ - try: #should evaluate to dict - rotation = eval(self.get_param('_rotation').get_value()) - return int(rotation) - except: - self.set_rotation(POSSIBLE_ROTATIONS[0]) - return POSSIBLE_ROTATIONS[0] - - def set_rotation(self, rot): - """ - Set the rotation into the position param. - @param rot the rotation in degrees - """ - self.get_param('_rotation').set_value(str(rot)) - - def update(self): - """Update the block, parameters, and ports when a change occurs.""" - self._bg_color = self.get_enabled() and Colors.BLOCK_ENABLED_COLOR or Colors.BLOCK_DISABLED_COLOR - self.clear() - self._create_labels() - self.W = self.label_width + 2*BLOCK_LABEL_PADDING - self.H = max(*( - [self.label_height+2*BLOCK_LABEL_PADDING] + [2*PORT_BORDER_SEPARATION + \ - sum([port.H + PORT_SEPARATION for port in ports]) - PORT_SEPARATION - for ports in (self.get_sources(), self.get_sinks())] - )) - 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_ports()) - - 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) - layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self)) - self.label_width, self.label_height = layout.get_pixel_size() - #display the params - for param in filter(lambda p: p.get_hide() not in ('all', 'part'), self.get_params()): - 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 = self.get_parent().new_pixmap(width, height) - gc = pixmap.new_gc() - gc.set_foreground(self._bg_color) - pixmap.draw_rectangle(gc, True, 0, 0, width, height) - #draw the layouts - h_off = 0 - for i,layout in enumerate(layouts): - w,h = layout.get_pixel_size() - if i == 0: w_off = (width-w)/2 - else: w_off = 0 - pixmap.draw_layout(gc, w_off, h_off, layout) - h_off = h + h_off + LABEL_SEPARATION - #create vertical and horizontal 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)) - map(lambda p: p._create_labels(), self.get_ports()) - - def draw(self, gc, window): - """ - Draw the signal block with label and inputs/outputs. - @param gc the graphics context - @param window the gtk window to draw on - """ - x, y = self.get_coordinate() - #draw main block - Element.draw( - self, gc, window, bg_color=self._bg_color, - border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or Colors.BORDER_COLOR, - ) - #draw label image - if self.is_horizontal(): - window.draw_image(gc, self.horizontal_label, 0, 0, x+BLOCK_LABEL_PADDING, y+(self.H-self.label_height)/2, -1, -1) - elif self.is_vertical(): - window.draw_image(gc, self.vertical_label, 0, 0, x+(self.H-self.label_height)/2, y+BLOCK_LABEL_PADDING, -1, -1) - #draw ports - for port in self.get_ports(): port.draw(gc, window) - - def what_is_selected(self, coor, coor_m=None): - """ - Get the element that is selected. - @param coor the (x,y) tuple - @param coor_m the (x_m, y_m) tuple - @return this block, a port, or None - """ - for port in self.get_ports(): - port_selected = port.what_is_selected(coor, coor_m) - if port_selected: return port_selected - return Element.what_is_selected(self, coor, coor_m) diff --git a/grc/src/platforms/gui/Colors.py b/grc/src/platforms/gui/Colors.py deleted file mode 100644 index f0b989b3..00000000 --- a/grc/src/platforms/gui/Colors.py +++ /dev/null @@ -1,37 +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 -""" - -import pygtk -pygtk.require('2.0') -import gtk - -_COLORMAP = gtk.gdk.colormap_get_system() #create all of the colors -def get_color(color_code): return _COLORMAP.alloc_color(color_code, True, True) - -HIGHLIGHT_COLOR = get_color('#00FFFF') -BORDER_COLOR = get_color('black') -#flow graph color constants -FLOWGRAPH_BACKGROUND_COLOR = get_color('#FFF9FF') -#block color constants -BLOCK_ENABLED_COLOR = get_color('#F1ECFF') -BLOCK_DISABLED_COLOR = get_color('#CCCCCC') -#connection color constants -CONNECTION_ENABLED_COLOR = get_color('black') -CONNECTION_DISABLED_COLOR = get_color('#999999') -CONNECTION_ERROR_COLOR = get_color('red') diff --git a/grc/src/platforms/gui/Connection.py b/grc/src/platforms/gui/Connection.py deleted file mode 100644 index 013bcb00..00000000 --- a/grc/src/platforms/gui/Connection.py +++ /dev/null @@ -1,140 +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 -""" - -import Utils -from Element import Element -import Colors -from Constants import CONNECTOR_ARROW_BASE, CONNECTOR_ARROW_HEIGHT - -class Connection(Element): - """ - A graphical connection for ports. - The connection has 2 parts, the arrow and the wire. - The coloring of the arrow and wire exposes the status of 3 states: - enabled/disabled, valid/invalid, highlighted/non-highlighted. - The wire coloring exposes the enabled and highlighted states. - The arrow coloring exposes the enabled and valid states. - """ - - def 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() - if not self.get_enabled(): self._arrow_color = Colors.CONNECTION_DISABLED_COLOR - elif not self.is_valid(): self._arrow_color = Colors.CONNECTION_ERROR_COLOR - else: self._arrow_color = Colors.CONNECTION_ENABLED_COLOR - - def _update_after_move(self): - """Calculate coordinates.""" - self.clear() - #source connector - source = self.get_source() - X, Y = source.get_connector_coordinate() - x1, y1 = self.x1 + X, self.y1 + Y - self.add_line((x1, y1), (X, Y)) - #sink connector - sink = self.get_sink() - X, Y = sink.get_connector_coordinate() - x2, y2 = self.x2 + X, self.y2 + Y - self.add_line((x2, y2), (X, Y)) - #adjust arrow - self._arrow = [(x+X, y+Y) for x,y in self.arrow] - #add the horizontal and vertical lines in this connection - if abs(source.get_connector_direction() - sink.get_connector_direction()) == 180: - #2 possible point sets to create a 3-line connector - mid_x, mid_y = (x1 + x2)/2.0, (y1 + y2)/2.0 - points = [((mid_x, y1), (mid_x, y2)), ((x1, mid_y), (x2, mid_y))] - #source connector -> points[0][0] should be in the direction of source (if possible) - if Utils.get_angle_from_coordinates((x1, y1), points[0][0]) != source.get_connector_direction(): points.reverse() - #points[0][0] -> sink connector should not be in the direction of sink - if Utils.get_angle_from_coordinates(points[0][0], (x2, y2)) == sink.get_connector_direction(): points.reverse() - #points[0][0] -> source connector should not be in the direction of source - if Utils.get_angle_from_coordinates(points[0][0], (x1, y1)) == source.get_connector_direction(): points.reverse() - #create 3-line connector - p1, p2 = map(int, points[0][0]), map(int, points[0][1]) - self.add_line((x1, y1), p1) - self.add_line(p1, p2) - self.add_line((x2, y2), p2) - else: - #2 possible points to create a right-angled connector - points = [(x1, y2), (x2, y1)] - #source connector -> points[0] should be in the direction of source (if possible) - if Utils.get_angle_from_coordinates((x1, y1), points[0]) != source.get_connector_direction(): points.reverse() - #points[0] -> sink connector should not be in the direction of sink - if Utils.get_angle_from_coordinates(points[0], (x2, y2)) == sink.get_connector_direction(): points.reverse() - #points[0] -> source connector should not be in the direction of source - if Utils.get_angle_from_coordinates(points[0], (x1, y1)) == source.get_connector_direction(): points.reverse() - #create right-angled connector - self.add_line((x1, y1), points[0]) - self.add_line((x2, y2), points[0]) - - def draw(self, gc, window): - """ - Draw the connection. - @param gc the graphics context - @param window the gtk window to draw on - """ - sink = self.get_sink() - source = self.get_source() - #check for changes - if self._sink_rot != sink.get_rotation() or self._source_rot != source.get_rotation(): self.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 - if self.is_highlighted(): border_color = Colors.HIGHLIGHT_COLOR - elif self.get_enabled(): border_color = Colors.CONNECTION_ENABLED_COLOR - else: border_color = Colors.CONNECTION_DISABLED_COLOR - Element.draw(self, gc, window, bg_color=None, border_color=border_color) - #draw arrow on sink port - gc.set_foreground(self._arrow_color) - window.draw_polygon(gc, True, self._arrow) diff --git a/grc/src/platforms/gui/Constants.py b/grc/src/platforms/gui/Constants.py deleted file mode 100644 index 90c8c1c3..00000000 --- a/grc/src/platforms/gui/Constants.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -#label constraint dimensions -LABEL_SEPARATION = 3 -BLOCK_LABEL_PADDING = 7 -PORT_LABEL_PADDING = 2 -#port constraint dimensions -PORT_SEPARATION = 17 -PORT_BORDER_SEPARATION = 9 -PORT_MIN_WIDTH = 20 -#minimal length of connector -CONNECTOR_EXTENSION_MINIMAL = 11 -#increment length for connector -CONNECTOR_EXTENSION_INCREMENT = 11 -#connection arrow dimensions -CONNECTOR_ARROW_BASE = 13 -CONNECTOR_ARROW_HEIGHT = 17 -#possible rotations in degrees -POSSIBLE_ROTATIONS = (0, 90, 180, 270) -#How close can the mouse get to the window border before mouse events are ignored. -BORDER_PROXIMITY_SENSITIVITY = 50 -#How close the mouse can get to the edge of the visible window before scrolling is invoked. -SCROLL_PROXIMITY_SENSITIVITY = 30 -#When the window has to be scrolled, move it this distance in the required direction. -SCROLL_DISTANCE = 15 -#How close the mouse click can be to a line and register a connection select. -LINE_SELECT_SENSITIVITY = 5 diff --git a/grc/src/platforms/gui/Element.py b/grc/src/platforms/gui/Element.py deleted file mode 100644 index 31519172..00000000 --- a/grc/src/platforms/gui/Element.py +++ /dev/null @@ -1,226 +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 -""" - -import Colors -import pygtk -pygtk.require('2.0') -import gtk -import pango -from Constants import LINE_SELECT_SENSITIVITY -from Constants import POSSIBLE_ROTATIONS - -class Element(object): - """ - GraphicalElement is the base class for all graphical elements. - It contains an X,Y coordinate, a list of rectangular areas that the element occupies, - and methods to detect selection of those areas. - """ - - def __init__(self, *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 draw(self, gc, window, border_color, bg_color): - """ - Draw in the given window. - @param gc the graphics context - @param window the gtk window to draw on - @param border_color the color for lines and rectangle borders - @param bg_color the color for the inside of the rectangle - """ - X,Y = self.get_coordinate() - for (rX,rY),(W,H) in self.areas_dict[self.get_rotation()]: - aX = X + rX - aY = Y + rY - gc.set_foreground(bg_color) - window.draw_rectangle(gc, True, aX, aY, W, H) - gc.set_foreground(border_color) - window.draw_rectangle(gc, False, aX, aY, W, H) - for (x1, y1),(x2, y2) in self.lines_dict[self.get_rotation()]: - gc.set_foreground(border_color) - window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2) - - def rotate(self, rotation): - """ - Rotate all of the areas by 90 degrees. - @param rotation multiple of 90 degrees - """ - self.set_rotation((self.get_rotation() + rotation)%360) - - def clear(self): - """Empty the lines and areas.""" - self.areas_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-LINE_SELECT_SENSITIVITY, x2+LINE_SELECT_SENSITIVITY - if y1 == y2: y1, y2 = y1-LINE_SELECT_SENSITIVITY, y2+LINE_SELECT_SENSITIVITY - if in_between(x, x1, x2) and in_between(y, y1, y2): return self - return None - - def get_rotation(self): - """ - Get the rotation in degrees. - @return the rotation - """ - return self.rotation - - def set_rotation(self, rotation): - """ - Set the rotation in degrees. - @param rotation the rotation""" - if rotation not in POSSIBLE_ROTATIONS: - raise Exception('"%s" is not one of the possible rotations: (%s)'%(rotation, POSSIBLE_ROTATIONS)) - self.rotation = rotation - - 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 deleted file mode 100644 index 40f39181..00000000 --- a/grc/src/platforms/gui/FlowGraph.py +++ /dev/null @@ -1,488 +0,0 @@ -""" -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from Constants import SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE -from ... gui.Actions import \ - ELEMENT_CREATE, ELEMENT_SELECT, \ - BLOCK_PARAM_MODIFY, BLOCK_MOVE, \ - ELEMENT_DELETE -import Colors -import Utils -from Element import Element -from .. base import FlowGraph as _FlowGraph -import pygtk -pygtk.require('2.0') -import gtk -import random -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.press_coor = (0, 0) - #selected ports - self._old_selected_port = None - self._new_selected_port = None - - ########################################################################### - # Access Drawing Area - ########################################################################### - def get_drawing_area(self): return self.drawing_area - def queue_draw(self): self.get_drawing_area().queue_draw() - def get_size(self): return self.get_drawing_area().get_size_request() - def set_size(self, *args): self.get_drawing_area().set_size_request(*args) - def get_scroll_pane(self): return self.drawing_area.get_parent() - def get_ctrl_mask(self): return self.drawing_area.ctrl_mask - def new_pixmap(self, *args): return self.get_drawing_area().new_pixmap(*args) - - def add_new_block(self, key, coor=None): - """ - Add a block of the given key to this flow graph. - @param key the block key - @param coor an optional coordinate or None for random - """ - id = self._get_unique_id(key) - #calculate the position coordinate - h_adj = self.get_scroll_pane().get_hadjustment() - v_adj = self.get_scroll_pane().get_vadjustment() - if coor is None: coor = ( - int(random.uniform(.25, .75)*h_adj.page_size + h_adj.get_value()), - int(random.uniform(.25, .75)*v_adj.page_size + v_adj.get_value()), - ) - #get the new block - block = self.get_new_block(key) - block.set_coordinate(coor) - block.set_rotation(0) - block.get_param('id').set_value(id) - 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.find('key') - if block_key == 'options': continue - block = self.get_new_block(block_key) - selected.add(block) - #set params - params_n = block_n.findall('param') - for param_n in params_n: - param_key = param_n.find('key') - param_value = param_n.find('value') - #setup id parameter - if param_key == 'id': - old_id2block[param_value] = block - #if the block id is not unique, get a new block id - if param_value in [block.get_id() for block in self.get_blocks()]: - param_value = self._get_unique_id(param_value) - #set value to key - block.get_param(param_key).set_value(param_value) - #move block to offset coordinate - block.move((x_off, y_off)) - #update before creating connections - self.update() - #create connections - for connection_n in connections_n: - source = old_id2block[connection_n.find('source_block_id')].get_source(connection_n.find('source_key')) - sink = old_id2block[connection_n.find('sink_block_id')].get_sink(connection_n.find('sink_key')) - self.connect(source, sink) - #set all pasted elements selected - for block in selected: selected = selected.union(set(block.get_connections())) - self._selected_elements = list(selected) - - ########################################################################### - # Modify Selected - ########################################################################### - def type_controller_modify_selected(self, direction): - """ - Change the registered type controller for the selected signal blocks. - @param direction +1 or -1 - @return true for change - """ - return any([sb.type_controller_modify(direction) for sb in self.get_selected_blocks()]) - - def port_controller_modify_selected(self, direction): - """ - Change port controller for the selected signal blocks. - @param direction +1 or -1 - @return true for changed - """ - return any([sb.port_controller_modify(direction) for sb in self.get_selected_blocks()]) - - def enable_selected(self, enable): - """ - Enable/disable the selected blocks. - @param enable true to enable - @return true if changed - """ - changed = False - for selected_block in self.get_selected_blocks(): - if selected_block.get_enabled() != enable: - selected_block.set_enabled(enable) - changed = True - return changed - - def move_selected(self, delta_coordinate): - """ - Move the element and by the change in coordinates. - @param delta_coordinate the change in coordinates - """ - for selected_block in self.get_selected_blocks(): - selected_block.move(delta_coordinate) - self.element_moved = True - - def rotate_selected(self, rotation): - """ - Rotate the selected blocks by multiples of 90 degrees. - @param rotation the rotation in degrees - @return true if changed, otherwise false. - """ - if not self.get_selected_blocks(): return False - #initialize min and max coordinates - min_x, min_y = self.get_selected_block().get_coordinate() - max_x, max_y = self.get_selected_block().get_coordinate() - #rotate each selected block, and find min/max coordinate - for selected_block in self.get_selected_blocks(): - selected_block.rotate(rotation) - #update the min/max coordinate - x, y = selected_block.get_coordinate() - min_x, min_y = min(min_x, x), min(min_y, y) - max_x, max_y = max(max_x, x), max(max_y, y) - #calculate center point of slected blocks - ctr_x, ctr_y = (max_x + min_x)/2, (max_y + min_y)/2 - #rotate the blocks around the center point - for selected_block in self.get_selected_blocks(): - x, y = selected_block.get_coordinate() - x, y = Utils.get_rotated_coordinate((x - ctr_x, y - ctr_y), rotation) - selected_block.set_coordinate((x + ctr_x, y + ctr_y)) - return True - - def remove_selected(self): - """ - Remove selected elements - @return true if changed. - """ - changed = False - for selected_element in self.get_selected_elements(): - self.remove_element(selected_element) - changed = True - return changed - - def draw(self, gc, window): - """ - Draw the background and grid if enabled. - Draw all of the elements in this flow graph onto the pixmap. - Draw the pixmap to the drawable window of this flow graph. - """ - W,H = self.get_size() - #draw the background - gc.set_foreground(Colors.FLOWGRAPH_BACKGROUND_COLOR) - window.draw_rectangle(gc, True, 0, 0, W, H) - #draw multi select rectangle - if self.mouse_pressed and (not self.get_selected_elements() or self.get_ctrl_mask()): - #coordinates - x1, y1 = self.press_coor - x2, y2 = self.get_coordinate() - #calculate top-left coordinate and width/height - x, y = int(min(x1, x2)), int(min(y1, y2)) - w, h = int(abs(x1 - x2)), int(abs(y1 - y2)) - #draw - gc.set_foreground(Colors.HIGHLIGHT_COLOR) - window.draw_rectangle(gc, True, x, y, w, h) - gc.set_foreground(Colors.BORDER_COLOR) - window.draw_rectangle(gc, False, x, y, w, h) - #draw blocks on top of connections - for element in self.get_connections() + self.get_blocks(): - element.draw(gc, window) - #draw selected blocks on top of selected connections - for selected_element in self.get_selected_connections() + self.get_selected_blocks(): - selected_element.draw(gc, window) - - def update_selected(self): - """ - Remove deleted elements from the selected elements list. - Update highlighting so only the selected are highlighted. - """ - selected_elements = self.get_selected_elements() - elements = self.get_elements() - #remove deleted elements - for selected in selected_elements: - if selected in elements: continue - selected_elements.remove(selected) - #update highlighting - for element in elements: - element.set_highlighted(element in selected_elements) - - def update(self): - """ - Call update on all elements. - """ - for element in self.get_elements(): element.update() - - ########################################################################## - ## Get Selected - ########################################################################## - def unselect(self): - """ - Set selected elements to an empty set. - """ - self._selected_elements = [] - - def what_is_selected(self, coor, coor_m=None): - """ - What is selected? - At the given coordinate, return the elements found to be selected. - If coor_m is unspecified, return a list of only the first element found to be selected: - Iterate though the elements backwards since top elements are at the end of the list. - If an element is selected, place it at the end of the list so that is is drawn last, - and hence on top. Update the selected port information. - @param coor the coordinate of the mouse click - @param coor_m the coordinate for multi select - @return the selected blocks and connections or an empty list - """ - selected_port = None - selected = set() - #check the elements - for element in reversed(self.get_elements()): - selected_element = element.what_is_selected(coor, coor_m) - if not selected_element: continue - #update the selected port information - if selected_element.is_port(): - if not coor_m: selected_port = selected_element - selected_element = selected_element.get_parent() - selected.add(selected_element) - #place at the end of the list - self.get_elements().remove(element) - self.get_elements().append(element) - #single select mode, break - if not coor_m: break - #update selected ports - self._old_selected_port = self._new_selected_port - self._new_selected_port = selected_port - return list(selected) - - def get_selected_connections(self): - """ - Get a group of selected connections. - @return sub set of connections in this flow graph - """ - selected = set() - for selected_element in self.get_selected_elements(): - if selected_element.is_connection(): selected.add(selected_element) - return list(selected) - - def get_selected_blocks(self): - """ - Get a group of selected blocks. - @return sub set of blocks in this flow graph - """ - selected = set() - for selected_element in self.get_selected_elements(): - if selected_element.is_block(): selected.add(selected_element) - return list(selected) - - def get_selected_block(self): - """ - Get the selected block when a block or port is selected. - @return a block or None - """ - return self.get_selected_blocks() and self.get_selected_blocks()[0] or None - - def get_selected_elements(self): - """ - Get the group of selected elements. - @return sub set of elements in this flow graph - """ - return self._selected_elements - - def get_selected_element(self): - """ - Get the selected element. - @return a block, port, or connection or None - """ - return self.get_selected_elements() and self.get_selected_elements()[0] or None - - def update_selected_elements(self): - """ - Update the selected elements. - The update behavior depends on the state of the mouse button. - When the mouse button pressed the selection will change when - the control mask is set or the new selection is not in the current group. - When the mouse button is released the selection will change when - the mouse has moved and the control mask is set or the current group is empty. - Attempt to make a new connection if the old and ports are filled. - If the control mask is set, merge with the current elements. - """ - selected_elements = None - if self.mouse_pressed: - new_selections = self.what_is_selected(self.get_coordinate()) - #update the selections if the new selection is not in the current selections - #allows us to move entire selected groups of elements - if self.get_ctrl_mask() or not ( - new_selections and new_selections[0] in self.get_selected_elements() - ): selected_elements = new_selections - else: #called from a mouse release - if not self.element_moved and (not self.get_selected_elements() or self.get_ctrl_mask()): - selected_elements = self.what_is_selected(self.get_coordinate(), self.press_coor) - #this selection and the last were ports, try to connect them - if self._old_selected_port and self._new_selected_port and \ - self._old_selected_port is not self._new_selected_port: - try: - self.connect(self._old_selected_port, self._new_selected_port) - 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 - if double_click: self.unselect() - self.update_selected_elements() - #double click detected, bring up params dialog if possible - if double_click and self.get_selected_block(): - self.mouse_pressed = False - 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: - self.handle_states(BLOCK_MOVE) - self.element_moved = False - self.update_selected_elements() - - def handle_mouse_motion(self, coordinate): - """ - The mouse has moved, respond to mouse dragging. - Move a selected element to the new coordinate. - Auto-scroll the scroll bars at the boundaries. - """ - #to perform a movement, the mouse must be pressed, no pending events - if gtk.events_pending() or not self.mouse_pressed: return - #perform autoscrolling - width, height = self.get_size() - x, y = coordinate - h_adj = self.get_scroll_pane().get_hadjustment() - v_adj = self.get_scroll_pane().get_vadjustment() - for pos, length, adj, adj_val, adj_len in ( - (x, width, h_adj, h_adj.get_value(), h_adj.page_size), - (y, height, v_adj, v_adj.get_value(), v_adj.page_size), - ): - #scroll if we moved near the border - if pos-adj_val > adj_len-SCROLL_PROXIMITY_SENSITIVITY and adj_val+SCROLL_DISTANCE < length-adj_len: - adj.set_value(adj_val+SCROLL_DISTANCE) - adj.emit('changed') - elif pos-adj_val < SCROLL_PROXIMITY_SENSITIVITY: - adj.set_value(adj_val-SCROLL_DISTANCE) - adj.emit('changed') - #remove the connection if selected in drag event - if len(self.get_selected_elements()) == 1 and self.get_selected_element().is_connection(): - self.handle_states(ELEMENT_DELETE) - #move the selected elements and record the new coordinate - X, Y = self.get_coordinate() - if not self.get_ctrl_mask(): self.move_selected((int(x - X), int(y - Y))) - self.set_coordinate((x, y)) - #queue draw for animation - self.queue_draw() diff --git a/grc/src/platforms/gui/Makefile.am b/grc/src/platforms/gui/Makefile.am deleted file mode 100644 index 2e3972ef..00000000 --- a/grc/src/platforms/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)/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 deleted file mode 100644 index 33a9b1f5..00000000 --- a/grc/src/platforms/gui/Param.py +++ /dev/null @@ -1,103 +0,0 @@ -""" -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import Utils -from Element import Element -import pygtk -pygtk.require('2.0') -import gtk - -PARAM_MARKUP_TMPL="""\ -#set $foreground = $param.is_valid() and 'black' or 'red' -#set $value = not $param.is_valid() and 'error' or repr($param) -$encode($param.get_name()): $encode($value)""" - -PARAM_LABEL_MARKUP_TMPL="""\ -#set $foreground = $param.is_valid() and 'black' or 'red' -#set $underline = $has_cb and 'low' or 'none' -$encode($param.get_name())""" - -TIP_MARKUP_TMPL="""\ -Key: $param.get_key() -Type: $param.get_type() -#if $param.is_valid() -Value: $param.evaluate() -#elif len($param.get_error_messages()) == 1 -Error: $(param.get_error_messages()[0]) -#else -Error: - #for $error_msg in $param.get_error_messages() - * $error_msg - #end for -#end if""" - -class Param(Element): - """The graphical parameter.""" - - def 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 object 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 - self._input = self.get_input_class()(self, self._handle_changed) - if not self._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. - """ - self.set_value(self._input.get_text()) - #is param is involved in a callback? #FIXME: messy - has_cb = \ - hasattr(self.get_parent(), 'get_callbacks') and \ - filter(lambda c: self.get_key() in c, self.get_parent()._callbacks) - self._input.set_markup(Utils.parse_template(PARAM_LABEL_MARKUP_TMPL, param=self, has_cb=has_cb)) - #hide/show - if self.get_hide() == 'all': self._input.hide_all() - else: self._input.show_all() - #set the color - self._input.set_color(self.get_color()) - #set the tooltip - if self._input.tp: self._input.tp.set_tip( - self._input.entry, - Utils.parse_template(TIP_MARKUP_TMPL, param=self).strip(), - ) - #execute the external callback - if self._callback: self._callback(self) - - 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(Utils.parse_template(PARAM_MARKUP_TMPL, param=self)) - return layout diff --git a/grc/src/platforms/gui/Platform.py b/grc/src/platforms/gui/Platform.py deleted file mode 100644 index a32b0209..00000000 --- a/grc/src/platforms/gui/Platform.py +++ /dev/null @@ -1,48 +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 -""" - -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 deleted file mode 100644 index d1f36f8b..00000000 --- a/grc/src/platforms/gui/Port.py +++ /dev/null @@ -1,190 +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 -""" - -from Element import Element -from Constants import \ - PORT_SEPARATION, CONNECTOR_EXTENSION_MINIMAL, \ - CONNECTOR_EXTENSION_INCREMENT, \ - PORT_LABEL_PADDING, PORT_MIN_WIDTH -import Utils -import Colors -import pygtk -pygtk.require('2.0') -import gtk - -PORT_MARKUP_TMPL="""\ -$encode($port.get_name())""" - -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() - #get current rotation - rotation = self.get_rotation() - #get all sibling ports - if self.is_source(): ports = self.get_parent().get_sources() - elif self.is_sink(): ports = self.get_parent().get_sinks() - #get the max width - self.W = max([port.W for port in ports] + [PORT_MIN_WIDTH]) - #get a numeric index for this port relative to its sibling ports - index = ports.index(self) - length = len(ports) - #reverse the order of ports for these rotations - if rotation in (180, 270): index = length-index-1 - offset = (self.get_parent().H - length*self.H - (length-1)*PORT_SEPARATION)/2 - #create areas and connector coordinates - if (self.is_sink() and rotation == 0) or (self.is_source() and rotation == 180): - x = -1*self.W - y = (PORT_SEPARATION+self.H)*index+offset - self.add_area((x, y), (self.W, self.H)) - self._connector_coordinate = (x-1, y+self.H/2) - elif (self.is_source() and rotation == 0) or (self.is_sink() and rotation == 180): - x = self.get_parent().W - y = (PORT_SEPARATION+self.H)*index+offset - self.add_area((x, y), (self.W, self.H)) - self._connector_coordinate = (x+1+self.W, y+self.H/2) - elif (self.is_source() and rotation == 90) or (self.is_sink() and rotation == 270): - y = -1*self.W - x = (PORT_SEPARATION+self.H)*index+offset - self.add_area((x, y), (self.H, self.W)) - self._connector_coordinate = (x+self.H/2, y-1) - elif (self.is_sink() and rotation == 90) or (self.is_source() and rotation == 270): - y = self.get_parent().W - x = (PORT_SEPARATION+self.H)*index+offset - self.add_area((x, y), (self.H, self.W)) - self._connector_coordinate = (x+self.H/2, y+1+self.W) - #the connector length - self._connector_length = CONNECTOR_EXTENSION_MINIMAL + CONNECTOR_EXTENSION_INCREMENT*index - - def _create_labels(self): - """Create the labels for the socket.""" - self._bg_color = Colors.get_color(self.get_color()) - #create the layout - layout = gtk.DrawingArea().create_pango_layout('') - layout.set_markup(Utils.parse_template(PORT_MARKUP_TMPL, port=self)) - self.w, self.h = layout.get_pixel_size() - self.W, self.H = 2*PORT_LABEL_PADDING+self.w, 2*PORT_LABEL_PADDING+self.h - #create the pixmap - pixmap = self.get_parent().get_parent().new_pixmap(self.w, self.h) - gc = pixmap.new_gc() - gc.set_foreground(self._bg_color) - pixmap.draw_rectangle(gc, True, 0, 0, self.w, self.h) - pixmap.draw_layout(gc, 0, 0, layout) - #create the images - self.horizontal_label = image = pixmap.get_image(0, 0, self.w, self.h) - if self.is_vertical(): - self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), self.h, self.w) - for i in range(self.w): - for j in range(self.h): vimage.put_pixel(j, self.w-i-1, image.get_pixel(i, j)) - - def draw(self, gc, window): - """ - Draw the socket with a label. - @param gc the graphics context - @param window the gtk window to draw on - """ - Element.draw( - self, gc, window, bg_color=self._bg_color, - border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or Colors.BORDER_COLOR, - ) - X,Y = self.get_coordinate() - (x,y),(w,h) = self.areas_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+(self.W-self.w)/2, y+Y+(self.H-self.h)/2, -1, -1) - elif self.is_vertical(): - window.draw_image(gc, self.vertical_label, 0, 0, x+X+(self.H-self.h)/2, y+Y+(self.W-self.w)/2, -1, -1) - - def get_connector_coordinate(self): - """ - Get the coordinate where connections may attach to. - @return the connector coordinate (x, y) tuple - """ - x,y = self._connector_coordinate - X,Y = self.get_coordinate() - return (x+X, y+Y) - - def get_connector_direction(self): - """ - Get the direction that the socket points: 0,90,180,270. - This is the rotation degree if the socket is an output or - the rotation degree + 180 if the socket is an input. - @return the direction in degrees - """ - if self.is_source(): return self.get_rotation() - elif self.is_sink(): return (self.get_rotation() + 180)%360 - - def get_connector_length(self): - """ - Get the length of the connector. - The connector length increases as the port index changes. - @return the length in pixels - """ - return self._connector_length - - def get_rotation(self): - """ - Get the parent's rotation rather than self. - @return the parent's rotation - """ - return self.get_parent().get_rotation() - - def move(self, delta_coor): - """ - Move the parent rather than self. - @param delta_corr the (delta_x, delta_y) tuple - """ - self.get_parent().move(delta_coor) - - def rotate(self, direction): - """ - Rotate the parent rather than self. - @param direction degrees to rotate - """ - self.get_parent().rotate(direction) - - def get_coordinate(self): - """ - Get the parent's coordinate rather than self. - @return the parents coordinate - """ - return self.get_parent().get_coordinate() - - def set_highlighted(self, highlight): - """ - Set the parent highlight rather than self. - @param highlight true to enable highlighting - """ - self.get_parent().set_highlighted(highlight) - - def is_highlighted(self): - """ - Get the parent's is highlight rather than self. - @return the parent's highlighting status - """ - return self.get_parent().is_highlighted() diff --git a/grc/src/platforms/gui/Utils.py b/grc/src/platforms/gui/Utils.py deleted file mode 100644 index ee6dc6cd..00000000 --- a/grc/src/platforms/gui/Utils.py +++ /dev/null @@ -1,82 +0,0 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from Constants import POSSIBLE_ROTATIONS -from Cheetah.Template import Template - -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 - -def parse_template(tmpl_str, **kwargs): - """ - Parse the template string with the given args. - Pass in the xml encode method for pango escape chars. - @param tmpl_str the template as a string - @return a string of the parsed template - """ - kwargs['encode'] = xml_encode - return str(Template(tmpl_str, kwargs)) diff --git a/grc/src/platforms/gui/__init__.py b/grc/src/platforms/gui/__init__.py deleted file mode 100644 index 8b137891..00000000 --- a/grc/src/platforms/gui/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/grc/src/platforms/python/Block.py b/grc/src/platforms/python/Block.py deleted file mode 100644 index 341e5fdc..00000000 --- a/grc/src/platforms/python/Block.py +++ /dev/null @@ -1,152 +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 -""" - -from .. base.Block import Block as _Block -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 = n.find('doc') or '' - imports = map(lambda i: i.strip(), n.findall('import')) - make = n.find('make') - checks = n.findall('check') - callbacks = n.findall('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) - #adjust nports - 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 port_controller_modify(self, direction): - """ - Change the port controller. - @param direction +1 or -1 - @return true for change - """ - changed = False - #concat the nports string from the private nports settings of both port0 - nports_str = \ - (self.get_sinks() and self.get_sinks()[0]._nports or '') + \ - (self.get_sources() and self.get_sources()[0]._nports or '') - #modify all params whose keys appear in the nports string - for param in self.get_params(): - if param.is_enum() or param.get_key() not in nports_str: continue - #try to increment the port controller by direction - try: - value = param.evaluate() - value = value + direction - assert 0 < value - param.set_value(value) - changed = True - except: pass - return changed - - def get_doc(self): - doc = self._doc.strip('\n').replace('\\\n', '') - #merge custom doc with doxygen docs - return '\n'.join([doc, extract_docs.extract(self.get_key())]).strip('\n') - - def get_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 deleted file mode 100644 index f742ff63..00000000 --- a/grc/src/platforms/python/Connection.py +++ /dev/null @@ -1,34 +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 -""" - -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 deleted file mode 100644 index 4a43147f..00000000 --- a/grc/src/platforms/python/Constants.py.in +++ /dev/null @@ -1,54 +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 -""" - -import os -import sys -import stat -from .. base.Constants import PKG_DIR - -PYEXEC = '@PYTHONW@' - -#setup paths -DOCS_DIR = os.path.join(os.environ.get('GR_DOCDIR', '@docdir@'), 'xml') -DATA_DIR = os.path.join(PKG_DIR, '@reldatadir@') -BLOCKS_DIR = os.path.join(PKG_DIR, '@relblocksdir@') -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') - -#coloring -COMPLEX_COLOR_SPEC = '#3399FF' -FLOAT_COLOR_SPEC = '#FF8C69' -INT_COLOR_SPEC = '#00FF99' -SHORT_COLOR_SPEC = '#FFFF66' -BYTE_COLOR_SPEC = '#FF66FF' -COMPLEX_VECTOR_COLOR_SPEC = '#3399AA' -FLOAT_VECTOR_COLOR_SPEC = '#CC8C69' -INT_VECTOR_COLOR_SPEC = '#00CC99' -SHORT_VECTOR_COLOR_SPEC = '#CCCC33' -BYTE_VECTOR_COLOR_SPEC = '#CC66CC' -ID_COLOR_SPEC = '#DDDDDD' diff --git a/grc/src/platforms/python/FlowGraph.py b/grc/src/platforms/python/FlowGraph.py deleted file mode 100644 index d0b997a5..00000000 --- a/grc/src/platforms/python/FlowGraph.py +++ /dev/null @@ -1,162 +0,0 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from utils import expr_utils -from .. base.FlowGraph import FlowGraph as _FlowGraph -from Block import Block -from Connection import Connection - -def _get_value_expr(variable_block): - """ - Get the expression to evaluate from the value param. - Parameter blocks need to be evaluated so the stringify flag can be determined. - @param variable_block the variable or parameter block - @return the expression string - """ - value_param = variable_block.get_param('value') - if variable_block.get_key() == 'parameter': value_param.evaluate() - return value_param.to_code() - -class FlowGraph(_FlowGraph): - - _eval_cache = dict() - def _eval(self, code, namespace): - """ - Evaluate the code with the given namespace. - @param code a string with python code - @param namespace a dict representing the namespace - @return the resultant object - """ - my_hash = hash(code + str(namespace)) - #cache if does not exist - if not self._eval_cache.has_key(my_hash): - self._eval_cache[my_hash] = eval(code, namespace, namespace) - #return from cache - return self._eval_cache[my_hash] - - def _get_io_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(), var.get_param('value').get_value()) 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 = self._eval(_get_value_expr(parameter), n) - np[parameter.get_id()] = e - except: pass - n.update(np) #merge param namespace - #load variables - for variable in self.get_variables(): - try: - e = self._eval(_get_value_expr(variable), n) - n[variable.get_id()] = e - except: pass - #make namespace public - self.n = n - #evaluate - e = self._eval(expr, self.n) - return e diff --git a/grc/src/platforms/python/Generator.py b/grc/src/platforms/python/Generator.py deleted file mode 100644 index 93321404..00000000 --- a/grc/src/platforms/python/Generator.py +++ /dev/null @@ -1,142 +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 -""" - -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 -from ... gui import Messages - -class Generator(object): - - def __init__(self, flow_graph, file_path): - """ - Initialize the generator object. - Determine the file to generate. - @param flow_graph the flow graph object - @param file_path the path to write the file to - """ - self._flow_graph = flow_graph - self._generate_options = self._flow_graph.get_option('generate_options') - if self._generate_options == 'hb': - self._mode = HIER_BLOCK_FILE_MODE - dirname = HIER_BLOCKS_LIB_DIR - else: - self._mode = TOP_BLOCK_FILE_MODE - dirname = os.path.dirname(file_path) - filename = self._flow_graph.get_option('id') + '.py' - self._file_path = os.path.join(dirname, filename) - - def get_file_path(self): return self._file_path - - def write(self): - #do throttle warning - all_keys = ' '.join(map(lambda b: b.get_key(), self._flow_graph.get_enabled_blocks())) - if ('usrp' not in all_keys) and ('audio' not in all_keys) and ('throttle' not in all_keys) and self._generate_options != 'hb': - Messages.send_warning('''\ -This flow graph may not have flow control: no audio or usrp blocks found. \ -Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''') - #generate - open(self.get_file_path(), 'w').write(str(self)) - if self._generate_options == 'hb': - #convert hier block to xml wrapper - convert_hier.convert_hier(self._flow_graph, self.get_file_path()) - os.chmod(self.get_file_path(), self._mode) - - def get_popen(self): - """ - Execute this python flow graph. - @return a popen object - """ - #execute - cmds = [PYEXEC, '-u', self.get_file_path()] #-u is unbuffered stdio - 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())) - probes = filter(lambda b: b.get_key().startswith('probe_'), blocks) #ensure probes are last in the block list - blocks = filter(lambda b: b not in (imports + parameters + variables + probes), blocks) + probes - #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_enabled_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 deleted file mode 100644 index c23d1479..00000000 --- a/grc/src/platforms/python/Makefile.am +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2008,2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -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 - -Constants.py: $(srcdir)/Constants.py.in Makefile - sed \ - -e 's|@PYTHONW[@]|$(PYTHONW)|g' \ - -e 's|@reldatadir[@]|$(grc_python_data_reldir)|g' \ - -e 's|@relblocksdir[@]|$(grc_blocks_data_reldir)|g' \ - -e 's|@docdir[@]|$(gr_docdir)|g' \ - $< > $@ - -EXTRA_DIST = $(srcdir)/Constants.py.in -BUILT_SOURCES = Constants.py diff --git a/grc/src/platforms/python/Param.py b/grc/src/platforms/python/Param.py deleted file mode 100644 index e5ac1dcf..00000000 --- a/grc/src/platforms/python/Param.py +++ /dev/null @@ -1,402 +0,0 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from utils import expr_utils -from .. base.Param import Param as _Param, EntryParam -import Constants -import numpy -import os -import pygtk -pygtk.require('2.0') -import gtk -from gnuradio import eng_notation - -class FileParam(EntryParam): - """Provide an entry box for filename and a button to browse for a file.""" - - def __init__(self, *args, **kwargs): - EntryParam.__init__(self, *args, **kwargs) - input = gtk.Button('...') - input.connect('clicked', self._handle_clicked) - self.pack_start(input, False) - - def _handle_clicked(self, widget=None): - """ - If the button was clicked, open a file dialog in open/save format. - Replace the text in the entry with the new filename from the file dialog. - """ - #get the paths - file_path = self.param.is_valid() and self.param.evaluate() or '' - (dirname, basename) = os.path.isfile(file_path) and os.path.split(file_path) or (file_path, '') - if not os.path.exists(dirname): dirname = os.getcwd() #fix bad paths - #build the dialog - if self.param.get_type() == 'file_open': - file_dialog = gtk.FileChooserDialog('Open a Data File...', None, - gtk.FILE_CHOOSER_ACTION_OPEN, ('gtk-cancel',gtk.RESPONSE_CANCEL,'gtk-open',gtk.RESPONSE_OK)) - elif self.param.get_type() == 'file_save': - file_dialog = gtk.FileChooserDialog('Save a Data File...', None, - gtk.FILE_CHOOSER_ACTION_SAVE, ('gtk-cancel',gtk.RESPONSE_CANCEL, 'gtk-save',gtk.RESPONSE_OK)) - file_dialog.set_do_overwrite_confirmation(True) - file_dialog.set_current_name(basename) #show the current filename - file_dialog.set_current_folder(dirname) #current directory - file_dialog.set_select_multiple(False) - file_dialog.set_local_only(True) - if gtk.RESPONSE_OK == file_dialog.run(): #run the dialog - file_path = file_dialog.get_filename() #get the file path - self.entry.set_text(file_path) - self._handle_changed() - file_dialog.destroy() #destroy the dialog - -#blacklist certain ids, its not complete, but should help -import __builtin__ -ID_BLACKLIST = ['options', 'gr', 'blks2', 'wxgui', 'wx', 'math', 'forms', 'firdes'] + dir(__builtin__) -#define types, native python + numpy -VECTOR_TYPES = (tuple, list, set, numpy.ndarray) -COMPLEX_TYPES = [complex, numpy.complex, numpy.complex64, numpy.complex128] -REAL_TYPES = [float, numpy.float, numpy.float32, numpy.float64] -INT_TYPES = [int, long, numpy.int, numpy.int8, numpy.int16, numpy.int32, numpy.uint64, - numpy.uint, numpy.uint8, numpy.uint16, numpy.uint32, numpy.uint64] -#cast to tuple for isinstance, concat subtypes -COMPLEX_TYPES = tuple(COMPLEX_TYPES + REAL_TYPES + INT_TYPES) -REAL_TYPES = tuple(REAL_TYPES + INT_TYPES) -INT_TYPES = tuple(INT_TYPES) - -class Param(_Param): - - _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 __repr__(self): - """ - Get the repr (nice string format) for this param. - @return the string representation - """ - if self.get_value() in self.get_option_keys(): return self.get_option(self.get_value()).get_name() - ################################################## - # display logic for numbers - ################################################## - def num_to_str(num): - if isinstance(num, COMPLEX_TYPES): - num = complex(num) #cast to python complex - if num == 0: return '0' #value is zero - elif num.imag == 0: return '%s'%eng_notation.num_to_str(num.real) #value is real - elif num.real == 0: return '%sj'%eng_notation.num_to_str(num.imag) #value is imaginary - elif num.imag < 0: return '%s-%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(abs(num.imag))) - else: return '%s+%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(num.imag)) - else: return str(num) - ################################################## - # split up formatting by type - ################################################## - truncate = 0 #default center truncate - max_len = max(27 - len(self.get_name()), 3) - e = self.evaluate() - t = self.get_type() - if isinstance(e, COMPLEX_TYPES): dt_str = num_to_str(e) - elif isinstance(e, VECTOR_TYPES): #vector types - if len(e) > 8: - dt_str = self.get_value() #large vectors use code - truncate = 1 - else: dt_str = ', '.join(map(num_to_str, e)) #small vectors use eval - elif t in ('file_open', 'file_save'): - dt_str = self.get_value() - truncate = -1 - else: dt_str = str(e) #other types - ################################################## - # truncate - ################################################## - if len(dt_str) > max_len: - if truncate < 0: #front truncate - dt_str = '...' + dt_str[3-max_len:] - elif truncate == 0: #center truncate - dt_str = dt_str[:max_len/2 -3] + '...' + dt_str[-max_len/2:] - elif truncate > 0: #rear truncate - dt_str = dt_str[:max_len-3] + '...' - return dt_str - - def get_input_class(self): - if self.get_type() in ('file_open', 'file_save'): return FileParam - return _Param.get_input_class(self) - - def get_color(self): - """ - Get the color that represents this param's type. - @return a hex color code. - """ - try: - return { - #number types - 'complex': Constants.COMPLEX_COLOR_SPEC, - 'real': Constants.FLOAT_COLOR_SPEC, - 'int': Constants.INT_COLOR_SPEC, - #vector types - 'complex_vector': Constants.COMPLEX_VECTOR_COLOR_SPEC, - 'real_vector': Constants.FLOAT_VECTOR_COLOR_SPEC, - 'int_vector': Constants.INT_VECTOR_COLOR_SPEC, - #special - 'hex': Constants.INT_COLOR_SPEC, - 'string': Constants.BYTE_VECTOR_COLOR_SPEC, - 'id': Constants.ID_COLOR_SPEC, - 'grid_pos': Constants.INT_VECTOR_COLOR_SPEC, - }[self.get_type()] - except: return _Param.get_color(self) - - def get_hide(self): - """ - Get the hide value from the base class. - Hide the ID parameter for most blocks. Exceptions below. - If the parameter controls a port type, vlen, or nports, return part. - If the parameter is an empty grid position, return part. - These parameters are redundant to display in the flow graph view. - @return hide the hide property string - """ - hide = _Param.get_hide(self) - if hide: return hide - #hide ID in non variable blocks - if self.get_key() == 'id' and self.get_parent().get_key() not in ( - 'variable', 'variable_slider', 'variable_chooser', 'variable_text_box', 'parameter', 'options' - ): return 'part' - #hide port controllers for type and nports - if self.get_key() in ' '.join(map( - lambda p: ' '.join([p._type, p._nports]), self.get_parent().get_ports()) - ): return 'part' - #hide port controllers for vlen, when == 1 - if self.get_key() in ' '.join(map( - lambda p: p._vlen, self.get_parent().get_ports()) - ): - try: - assert int(self.evaluate()) == 1 - return 'part' - except: pass - #hide empty grid positions - if self.get_key() == 'grid_pos' and not self.get_value(): return '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 v - ######################### - # 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 Exception, e: - self._add_error_message('Value "%s" cannot be evaluated: %s'%(v, e)) - raise Exception - #raise an exception if the data is invalid - if t == 'raw': return e - elif t == 'complex': - try: assert(isinstance(e, COMPLEX_TYPES)) - 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, REAL_TYPES)) - 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_TYPES)) - except AssertionError: - self._add_error_message('Expression "%s" is invalid for type integer.'%str(e)) - raise Exception - return e - ######################### - # Numeric Vector Types - ######################### - elif t == 'complex_vector': - if not isinstance(e, VECTOR_TYPES): - self._lisitify_flag = True - e = [e] - try: - for ei in e: - assert(isinstance(ei, COMPLEX_TYPES)) - 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, VECTOR_TYPES): - self._lisitify_flag = True - e = [e] - try: - for ei in e: - assert(isinstance(ei, REAL_TYPES)) - 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, VECTOR_TYPES): - self._lisitify_flag = True - e = [e] - try: - for ei in e: - assert(isinstance(ei, INT_TYPES)) - 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 keys.count(v) <= 1 #id should only appear once, or zero times if block is disabled - except: - self._add_error_message('ID "%s" is not unique.'%v) - raise Exception - try: assert v not in ID_BLACKLIST - except: - self._add_error_message('ID "%s" is blacklisted.'%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_enabled_blocks()], []) diff --git a/grc/src/platforms/python/Platform.py b/grc/src/platforms/python/Platform.py deleted file mode 100644 index d2bb4627..00000000 --- a/grc/src/platforms/python/Platform.py +++ /dev/null @@ -1,69 +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 -""" - -import os -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 - -_critical_blocks_only = map(lambda b: os.path.join(BLOCKS_DIR, b), ['options.xml', 'usrp_probe.xml', 'usrp2_probe.xml']) - -class Platform(_Platform): - - def __init__(self, extra_blocks=[], critical_only=False): - """ - Make a platform for gnuradio. - @param extra_blocks a list of block paths to load in addition to main block library - @param critical_only only load critical blocks (used only for usrp probe scripts to speed up load time) - """ - #ensure hier dir - if not os.path.exists(HIER_BLOCKS_LIB_DIR): os.mkdir(HIER_BLOCKS_LIB_DIR) - if critical_only: block_paths = _critical_blocks_only - else: block_paths = extra_blocks + [HIER_BLOCKS_LIB_DIR, BLOCKS_DIR] - #convert block paths to absolute paths, ensure uniqueness - block_paths = set(map(os.path.abspath, block_paths)) - #init - _Platform.__init__( - self, - name='GRC', - key='grc', - 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 deleted file mode 100644 index b5bc9696..00000000 --- a/grc/src/platforms/python/Port.py +++ /dev/null @@ -1,129 +0,0 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from .. base.Port import Port as _Port -import Constants - -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 = n.find('vlen') or '1' - nports = n.find('nports') or '' - optional = n.find('optional') or '' - #build the port - _Port.__init__( - self, - block=block, - n=n, - ) - self._nports = nports - self._vlen = vlen - self._optional = bool(optional) - - def validate(self): - _Port.validate(self) - try: assert(self.get_enabled_connections() or self.get_optional()) - except AssertionError: self._add_error_message('Port is not connected.') - try: assert(self.is_source() or len(self.get_enabled_connections()) <= 1) - except AssertionError: self._add_error_message('Port has too many connections.') - - 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': Constants.COMPLEX_COLOR_SPEC, - 'float': Constants.FLOAT_COLOR_SPEC, - 'int': Constants.INT_COLOR_SPEC, - 'short': Constants.SHORT_COLOR_SPEC, - 'byte': Constants.BYTE_COLOR_SPEC, - }[self.get_type()] - return {#vlen is non 1 - 'complex': Constants.COMPLEX_VECTOR_COLOR_SPEC, - 'float': Constants.FLOAT_VECTOR_COLOR_SPEC, - 'int': Constants.INT_VECTOR_COLOR_SPEC, - 'short': Constants.SHORT_VECTOR_COLOR_SPEC, - 'byte': Constants.BYTE_VECTOR_COLOR_SPEC, - }[self.get_type()] - except: return _Port.get_color(self) - -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 deleted file mode 100644 index 8b137891..00000000 --- a/grc/src/platforms/python/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/grc/src/platforms/python/utils/Makefile.am b/grc/src/platforms/python/utils/Makefile.am deleted file mode 100644 index b12e51d8..00000000 --- a/grc/src/platforms/python/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)/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 deleted file mode 100644 index 8b137891..00000000 --- a/grc/src/platforms/python/utils/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/grc/src/platforms/python/utils/convert_hier.py b/grc/src/platforms/python/utils/convert_hier.py deleted file mode 100644 index 49535898..00000000 --- a/grc/src/platforms/python/utils/convert_hier.py +++ /dev/null @@ -1,78 +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 -""" - -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 deleted file mode 100644 index 40700993..00000000 --- a/grc/src/platforms/python/utils/expr_utils.py +++ /dev/null @@ -1,137 +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 -""" - -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 deleted file mode 100644 index 523519f9..00000000 --- a/grc/src/platforms/python/utils/extract_docs.py +++ /dev/null @@ -1,92 +0,0 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from .. Constants import DOCS_DIR -from lxml import etree -import os -import re - -DOXYGEN_NAME_XPATH = '/doxygen/compounddef/compoundname' -DOXYGEN_BRIEFDESC_GR_XPATH = '/doxygen/compounddef/briefdescription' -DOXYGEN_DETAILDESC_GR_XPATH = '/doxygen/compounddef/detaileddescription' - -def extract_txt(xml): - """ - Recursivly pull the text out of an xml tree. - @param xml the xml tree - @return a string - """ - text = (xml.text or '').replace('\n', '') - tail = (xml.tail or '').replace('\n', '') - if xml.tag == 'para': tail += '\n\n' - if xml.tag == 'linebreak': text += '\n' - if xml.tag == 'parametername': text += ': ' - return text + ''.join( - map(lambda x: extract_txt(x), xml) - ) + tail - -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 - """ - UBUNTU_DOCS_DIR = '/usr/share/doc/gnuradio-doc/xml' - if os.path.exists(DOCS_DIR): docs_dir = DOCS_DIR - elif os.path.exists(UBUNTU_DOCS_DIR): docs_dir = UBUNTU_DOCS_DIR - else: return '' - #extract matches - pattern = key.replace('_', '_*').replace('x', '\w') - prog = re.compile('^class%s\..*$'%pattern) - matches = filter(lambda f: prog.match(f), os.listdir(docs_dir)) - #combine all matches - doc_strs = list() - for match in matches: - try: - xml_file = os.path.join(docs_dir, match) - xml = etree.parse(xml_file) - #extract descriptions - comp_name = extract_txt(xml.xpath(DOXYGEN_NAME_XPATH)[0]).strip() - comp_name = ' --- ' + comp_name + ' --- ' - if re.match('(gr|usrp2|trellis)_.*', key): - brief_desc = extract_txt(xml.xpath(DOXYGEN_BRIEFDESC_GR_XPATH)[0]).strip() - detailed_desc = extract_txt(xml.xpath(DOXYGEN_DETAILDESC_GR_XPATH)[0]).strip() - else: - brief_desc = '' - detailed_desc = '' - #combine - doc_strs.append('\n\n'.join([comp_name, brief_desc, detailed_desc]).strip()) - except IndexError: pass #bad format - return '\n\n'.join(doc_strs) - -_docs_cache = dict() -def extract(key): - """ - Call the private extract and cache the result. - @param key the block key - @return a string with documentation - """ - try: assert _docs_cache.has_key(key) - except: _docs_cache[key] = _extract(key) - return _docs_cache[key] - -if __name__ == '__main__': - import sys - print extract(sys.argv[1]) diff --git a/grc/src/utils/Makefile.am b/grc/src/utils/Makefile.am deleted file mode 100644 index a4890479..00000000 --- a/grc/src/utils/Makefile.am +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright 2008, 2009 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/grc/Makefile.inc - -ourpythondir = $(grc_src_prefix)/utils - -ourpython_PYTHON = \ - converter.py \ - odict.py \ - ParseXML.py \ - __init__.py diff --git a/grc/src/utils/ParseXML.py b/grc/src/utils/ParseXML.py deleted file mode 100644 index d05b7b8b..00000000 --- a/grc/src/utils/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 -""" - -from lxml import etree -from .. utils import odict - -class XMLSyntaxError(Exception): - def __init__(self, error_log): - self._error_log = error_log - def __str__(self): - return '\n'.join(map(str, self._error_log.filter_from_errors())) - -def validate_dtd(xml_file, dtd_file=None): - """ - Validate an xml file against its dtd. - @param xml_file the xml file - @param dtd_file the optional dtd file - @throws Exception validation fails - """ - #perform parsing, use dtd validation if dtd file is not specified - parser = etree.XMLParser(dtd_validation=not dtd_file) - xml = etree.parse(xml_file, parser=parser) - if parser.error_log: raise XMLSyntaxError(parser.error_log) - #perform dtd validation if the dtd file is specified - if not dtd_file: return - dtd = etree.DTD(dtd_file) - if not dtd.validate(xml.getroot()): raise XMLSyntaxError(dtd.error_log) - -def from_file(xml_file): - """ - Create nested data from an xml file using the from xml helper. - @param xml_file the xml file path - @return the nested data - """ - xml = etree.parse(xml_file).getroot() - return _from_file(xml) - -def _from_file(xml): - """ - Recursivly parse the xml tree into nested data format. - @param xml the xml tree - @return the nested data - """ - tag = xml.tag - if not len(xml): - return odict({tag: xml.text or ''}) #store empty tags (text is None) as empty string - nested_data = odict() - for elem in xml: - key, value = _from_file(elem).items()[0] - if nested_data.has_key(key): nested_data[key].append(value) - else: nested_data[key] = [value] - #delistify if the length of values is 1 - for key, values in nested_data.iteritems(): - if len(values) == 1: nested_data[key] = values[0] - return odict({tag: nested_data}) - -def to_file(nested_data, xml_file): - """ - Write an xml file and use the to xml helper method to load it. - @param nested_data the nested data - @param xml_file the xml file path - """ - xml = _to_file(nested_data)[0] - open(xml_file, 'w').write(etree.tostring(xml, xml_declaration=True, pretty_print=True)) - -def _to_file(nested_data): - """ - Recursivly parse the nested data into xml tree format. - @param nested_data the nested data - @return the xml tree filled with child nodes - """ - nodes = list() - for key, values in nested_data.iteritems(): - #listify the values if not a list - if not isinstance(values, (list, set, tuple)): - values = [values] - for value in values: - node = etree.Element(key) - if isinstance(value, (str, unicode)): node.text = value - else: node.extend(_to_file(value)) - nodes.append(node) - return nodes - -if __name__ == '__main__': - """Use the main method to test parse xml's functions.""" - pass diff --git a/grc/src/utils/__init__.py b/grc/src/utils/__init__.py deleted file mode 100644 index 2682db81..00000000 --- a/grc/src/utils/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -""" -Copyright 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from odict import odict diff --git a/grc/src/utils/converter.py b/grc/src/utils/converter.py deleted file mode 100644 index 34fc438f..00000000 --- a/grc/src/utils/converter.py +++ /dev/null @@ -1,248 +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 -""" - -from .. platforms.base.Constants import FLOW_GRAPH_DTD -import ParseXML -from .. import utils -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 ( - ('gr_add_vxx', 'gr_add_xx'), - ('gr_multiply_vxx', 'gr_multiply_xx'), - ): - keys = xml.xpath('/flow_graph/block[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/utils/odict.py b/grc/src/utils/odict.py deleted file mode 100644 index ac3cb207..00000000 --- a/grc/src/utils/odict.py +++ /dev/null @@ -1,93 +0,0 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from UserDict import DictMixin - -class odict(DictMixin): - - def __init__(self, d={}): - self._keys = list(d.keys()) - self._data = dict(d.copy()) - - def __setitem__(self, key, value): - if key not in self._data: - self._keys.append(key) - self._data[key] = value - - def __getitem__(self, key): - return self._data[key] - - def __delitem__(self, key): - del self._data[key] - self._keys.remove(key) - - def keys(self): - return list(self._keys) - - def copy(self): - copy_dict = odict() - copy_dict._data = self._data.copy() - copy_dict._keys = list(self._keys) - return copy_dict - - def insert_after(self, pos_key, key, val): - """ - Insert the new key, value entry after the entry given by the position key. - If the positional key is None, insert at the end. - @param pos_key the positional key - @param key the key for the new entry - @param val the value for the new entry - """ - index = (pos_key is None) and len(self._keys) or self._keys.index(pos_key) - assert key not in self._keys - self._keys.insert(index+1, key) - self._data[key] = val - - def insert_before(self, pos_key, key, val): - """ - Insert the new key, value entry before the entry given by the position key. - If the positional key is None, insert at the begining. - @param pos_key the positional key - @param key the key for the new entry - @param val the value for the new entry - """ - index = (pos_key is not None) and self._keys.index(pos_key) or 0 - assert key not in self._keys - self._keys.insert(index, key) - self._data[key] = val - - def find(self, key): - """ - Get the value for this key if exists. - @param key the key to search for - @return the value or None - """ - if self.has_key(key): return self[key] - return None - - def findall(self, key): - """ - Get a list of values for this key. - @param key the key to search for - @return a list of values or empty list - """ - obj = self.find(key) - if obj is None: obj = list() - if isinstance(obj, list): return obj - return [obj] diff --git a/grc/todo.txt b/grc/todo.txt index b4f020c0..ad7e62ff 100644 --- a/grc/todo.txt +++ b/grc/todo.txt @@ -1,3 +1,10 @@ +################################################## +# Examples +################################################## +* Push-to-Talk example +* Variable Config usage example +* Start/Stop the flow graph + ################################################## # Blocks ################################################## @@ -5,6 +12,8 @@ * log slider gui control * generic usrp (when its ready) * packet mod: whitening offset +* wx min window size in options block +* gr_adaptive_fir_ccf ################################################## # Features @@ -20,7 +29,18 @@ * separate generated code into top block and gui class * use gui.py in gr-wxgui and remove custom top_block_gui * configuration option for adding block paths -* data types guide/colors for the help menu +* orientations for ports (top, right, bottom, left) + * source defaults to right, sink defaults to left +* grid params take a notebook argument + * add a wx notebook block +* separation of variables and gui controls +* speedup w/ background layer and animation layer +* multiple doxygen directories (doc_dir becomes doc_path) +* use pango markup in tooltips for params +* use get_var_make to determine if it is a variable, not regexp +* concept of a project, or project flow graph + * collection of blocks, hier and top + * system-wide, default/work, and user created ################################################## # Problems @@ -34,12 +54,14 @@ * threads dont die on exit in probe and variable sink * overloaded gui classes for each platform, move param input objects into overloaded * align param titles in paramsdialog +* better error for blank string params +* weird grid params misbehaving +* params dialog needs to dynamically update for all params + * will not update for non-enum params + * needs to account for added or removed params ################################################## # Future ################################################## * require pygtk 2.12 for treeview tooltips * remove try/except in BlockTreeWindow.py -* remove support for saved flow graphs ending in .xml -* remove converter script for previous format -* reorganize module structure