From 7f7fa2f91467fdb2b11312be8562e7b51fdeb199 Mon Sep 17 00:00:00 2001 From: Sebastian Koslowski <sebastian.koslowski@gmail.com> Date: Tue, 3 May 2016 17:13:08 +0200 Subject: grc: added yaml/mako support Includes basic converter from XML/Cheetah to YAML/Mako based block format. --- grc/core/generator/flow_graph.py.mako | 352 ++++++++++++++++++++++++++++++++++ 1 file changed, 352 insertions(+) create mode 100644 grc/core/generator/flow_graph.py.mako (limited to 'grc/core/generator/flow_graph.py.mako') diff --git a/grc/core/generator/flow_graph.py.mako b/grc/core/generator/flow_graph.py.mako new file mode 100644 index 0000000000..484441f00f --- /dev/null +++ b/grc/core/generator/flow_graph.py.mako @@ -0,0 +1,352 @@ +% if not generate_options.startswith('hb'): +#!/usr/bin/env python2 +% endif +# -*- coding: utf-8 -*- +<%def name="indent(code)">${ '\n '.join(str(code).splitlines()) }</%def> +""" +GNU Radio Python Flow Graph + +Title: ${title} +% if flow_graph.get_option('author'): +Author: ${flow_graph.get_option('author')} +% endif +% if flow_graph.get_option('description'): +Description: ${flow_graph.get_option('description')} +% endif +Generated: ${ generated_time } +""" + +% if generate_options == 'qt_gui': +from distutils.version import StrictVersion + +if __name__ == '__main__': + import ctypes + import sys + if sys.platform.startswith('linux'): + try: + x11 = ctypes.cdll.LoadLibrary('libX11.so') + x11.XInitThreads() + except: + print "Warning: failed to XInitThreads()" + +% endif +######################################################## +##Create Imports +######################################################## +% for imp in imports: +##${imp.replace(" # grc-generated hier_block", "")} +${imp} +% endfor +######################################################## +##Create Class +## Write the class declaration for a top or hier block. +## The parameter names are the arguments to __init__. +## Setup the IO signature (hier block only). +######################################################## +<% + class_name = flow_graph.get_option('id') + param_str = ', '.join(['self'] + ['%s=%s'%(param.name, param.templates.render('make')) for param in parameters]) +%>\ +% if generate_options == 'qt_gui': +from gnuradio import qtgui + +class ${class_name}(gr.top_block, Qt.QWidget): + + def __init__(${param_str}): + gr.top_block.__init__(self, "${title}") + Qt.QWidget.__init__(self) + self.setWindowTitle("${title}") + qtgui.util.check_set_qss() + try: + self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) + except: + pass + self.top_scroll_layout = Qt.QVBoxLayout() + self.setLayout(self.top_scroll_layout) + self.top_scroll = Qt.QScrollArea() + self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) + self.top_scroll_layout.addWidget(self.top_scroll) + self.top_scroll.setWidgetResizable(True) + self.top_widget = Qt.QWidget() + self.top_scroll.setWidget(self.top_widget) + self.top_layout = Qt.QVBoxLayout(self.top_widget) + self.top_grid_layout = Qt.QGridLayout() + self.top_layout.addLayout(self.top_grid_layout) + + self.settings = Qt.QSettings("GNU Radio", "${class_name}") + + try: + if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): + self.restoreGeometry(self.settings.value("geometry").toByteArray()) + else: + self.restoreGeometry(self.settings.value("geometry")) + except: + pass +% elif generate_options == 'no_gui': + +class ${class_name}(gr.top_block): + + def __init__(${param_str}): + gr.top_block.__init__(self, "${title}") +% elif generate_options.startswith('hb'): + <% in_sigs = flow_graph.get_hier_block_stream_io('in') %> + <% out_sigs = flow_graph.get_hier_block_stream_io('out') %> + + +% if generate_options == 'hb_qt_gui': +class ${class_name}(gr.hier_block2, Qt.QWidget): +% else: +class ${class_name}(gr.hier_block2): +% endif +<%def name="make_io_sig(io_sigs)"> + <% size_strs = ['%s*%s'%(io_sig['size'], io_sig['vlen']) for io_sig in io_sigs] %> + % if len(io_sigs) == 0: +gr.io_signature(0, 0, 0)\ + #elif len(${io_sigs}) == 1 +gr.io_signature(1, 1, ${size_strs[0]}) + % else: +gr.io_signaturev(${len(io_sigs)}, ${len(io_sigs)}, [${', '.join(ize_strs)}]) + % endif +</%def> + + def __init__(${param_str}): + gr.hier_block2.__init__( + self, "${ title }", + ${make_io_sig(in_sigs)}, + ${make_io_sig(out_sigs)}, + ) + % for pad in flow_graph.get_hier_block_message_io('in'): + self.message_port_register_hier_in("${ pad['label'] }") + % endfor + % for pad in flow_graph.get_hier_block_message_io('out'): + self.message_port_register_hier_out("${ pad['label'] }") + % endfor + % if generate_options == 'hb_qt_gui': + + Qt.QWidget.__init__(self) + self.top_layout = Qt.QVBoxLayout() + self.top_grid_layout = Qt.QGridLayout() + self.top_layout.addLayout(self.top_grid_layout) + self.setLayout(self.top_layout) + % endif +% endif +% if flow_graph.get_option('thread_safe_setters'): + + self._lock = threading.RLock() +% endif +######################################################## +##Create Parameters +## Set the parameter to a property of self. +######################################################## +% if parameters: + + ${'##################################################'} + # Parameters + ${'##################################################'} +% endif +% for param in parameters: + ${indent(param.get_var_make())} +% endfor +######################################################## +##Create Variables +######################################################## +% if variables: + + ${'##################################################'} + # Variables + ${'##################################################'} +% endif +% for var in variables: + ${indent(var.templates.render('var_make'))} +% endfor + % if blocks: + + ${'##################################################'} + # Blocks + ${'##################################################'} + % endif + % for blk, blk_make in blocks: + ${ indent(blk_make.strip('\n')) } +## % if 'alias' in blk.params and blk.params['alias'].get_evaluated(): +## (self.${blk.name}).set_block_alias("${blk.params['alias'].get_evaluated()}") +## % endif +## % if 'affinity' in blk.params and blk.params['affinity'].get_evaluated(): +## (self.${blk.name}).set_processor_affinity(${blk.params['affinity'].get_evaluated()}) +## % endif +## % if len(blk.sources) > 0 and 'minoutbuf' in blk.params and int(blk.params['minoutbuf'].get_evaluated()) > 0: +## (self.${blk.name}).set_min_output_buffer(${blk.params['minoutbuf'].get_evaluated()}) +## % endif +## % if len(blk.sources) > 0 and 'maxoutbuf' in blk.params and int(blk.params['maxoutbuf'].get_evaluated()) > 0: +## (self.${blk.name}).set_max_output_buffer(${blk.params['maxoutbuf'].get_evaluated()}) +## % endif + % endfor + % if connections: + + ${'##################################################'} + # Connections + ${'##################################################'} + % for connection in connections: + ${ connection.rstrip() } + % endfor + % endif +######################################################## +## QT sink close method reimplementation +######################################################## +% if generate_options == 'qt_gui': + + def closeEvent(self, event): + self.settings = Qt.QSettings("GNU Radio", "${class_name}") + self.settings.setValue("geometry", self.saveGeometry()) + event.accept() + % if flow_graph.get_option('qt_qss_theme'): + + def setStyleSheetFromFile(self, filename): + try: + if not os.path.exists(filename): + filename = os.path.join( + gr.prefix(), "share", "gnuradio", "themes", filename) + with open(filename) as ss: + self.setStyleSheet(ss.read()) + except Exception as e: + print >> sys.stderr, e + % endif +% endif +## +## +## +## Create Callbacks +## Write a set method for this variable that calls the callbacks +######################################################## + % for var in parameters + variables: + + def get_${ var.name }(self): + return self.${ var.name } + + def set_${ var.name }(self, ${ var.name }): + % if flow_graph.get_option('thread_safe_setters'): + with self._lock: + self.${ var.name } = ${ var.name } + % for callback in callbacks[var.name]: + ${ indent(callback) } + % endfor + % else: + self.${ var.name } = ${ var.name } + % for callback in callbacks[var.name]: + ${ indent(callback) } + % endfor + % endif + % endfor +######################################################## +##Create Main +## For top block code, generate a main routine. +## Instantiate the top block and run as gui or cli. +######################################################## +<%def name="make_default(type_, param)"> + % if type_ == 'eng_float': +eng_notation.num_to_str(${param.templates.render('make')}) + % else: +${param.templates.render('make')} + % endif +</%def>\ +% if not generate_options.startswith('hb'): +<% params_eq_list = list() %> +% if parameters: + +<% arg_parser_args = '' %>\ +def argument_parser(): + % if flow_graph.get_option('description'): + <% + arg_parser_args = 'description=description' + %>description = ${repr(flow_graph.get_option('description'))} + % endif + parser = ArgumentParser(${arg_parser_args}) + % for param in parameters: +<% + switches = ['"--{}"'.format(param.name.replace('_', '-'))] + short_id = param.params['short_id'].get_value() + if short_id: + switches.insert(0, '"-{}"'.format(short_id)) + + type_ = param.params['type'].get_value() + if type_: + params_eq_list.append('%s=options.%s' % (param.name, param.name)) + + default = param.templates.render('make') + if type_ == 'eng_float': + default = eng_notation.num_to_str(default) + # FIXME: + if type_ == 'string': + type_ = 'str' + %>\ + % if type_: + parser.add_argument( + ${ ', '.join(switches) }, dest="${param.name}", type=${type_}, default=${ default }, + help="Set ${param.params['label'].get_evaluated() or param.name} [default=%(default)r]") + % endif + % endfor + return parser +% endif + + +def main(top_block_cls=${class_name}, options=None): + % if parameters: + if options is None: + options = argument_parser().parse_args() + % endif + % if flow_graph.get_option('realtime_scheduling'): + if gr.enable_realtime_scheduling() != gr.RT_OK: + print "Error: failed to enable real-time scheduling." + % endif + % if generate_options == 'qt_gui': + + if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): + style = gr.prefs().get_string('qtgui', 'style', 'raster') + Qt.QApplication.setGraphicsSystem(style) + qapp = Qt.QApplication(sys.argv) + + tb = top_block_cls(${ ', '.join(params_eq_list) }) + % if flow_graph.get_option('run'): + tb.start(${flow_graph.get_option('max_nouts') or ''}) + % endif + % if flow_graph.get_option('qt_qss_theme'): + tb.setStyleSheetFromFile(${ flow_graph.get_option('qt_qss_theme') }) + % endif + tb.show() + + def quitting(): + tb.stop() + tb.wait() + qapp.aboutToQuit.connect(quitting) + % for m in monitors: + if 'en' in m.params: + if m.params['en'].get_value(): + (tb.${m.name}).start() + else: + sys.stderr.write("Monitor '{0}' does not have an enable ('en') parameter.".format("tb.${m.name}")) + % endfor + qapp.exec_() + % elif generate_options == 'no_gui': + tb = top_block_cls(${ ', '.join(params_eq_list) }) + % if flow_graph.get_option('run_options') == 'prompt': + tb.start(${ flow_graph.get_option('max_nouts') or '' }) + % for m in monitors: + (tb.${m.name}).start() + % endfor + try: + raw_input('Press Enter to quit: ') + except EOFError: + pass + tb.stop() + % elif flow_graph.get_option('run_options') == 'run': + tb.start(${flow_graph.get_option('max_nouts') or ''}) + % endif + % for m in monitors: + (tb.${m.name}).start() + % endfor + tb.wait() + % endif + + +if __name__ == '__main__': + main() +% endif -- cgit v1.2.3