converter.py

Go to the documentation of this file.
00001 """
00002 Copyright 2008 Free Software Foundation, Inc.
00003 This file is part of GNU Radio
00004 
00005 GNU Radio Companion is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU General Public License
00007 as published by the Free Software Foundation; either version 2
00008 of the License, or (at your option) any later version.
00009 
00010 GNU Radio Companion is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
00018 """
00019 ##@package grc.converter
00020 #convert old flow graph file format to new format
00021 #@author Josh Blum
00022 
00023 from grc.Constants import FLOW_GRAPH_DTD
00024 from grc import ParseXML, Utils
00025 from grc.Utils import odict
00026 from lxml import etree
00027 import difflib
00028 import os
00029 
00030 def _make_param(key, value):
00031         """!
00032         Make a paramater dict from the key/value pair.
00033         @param key the key
00034         @param value the value
00035         @return a dictionary object
00036         """
00037         param = odict()
00038         param['key'] = key
00039         param['value'] = value
00040         return param
00041 
00042 def _get_blocks(blocks, tag):
00043         """!
00044         Get a list of blocks with the tag.
00045         @param blocks the old block list
00046         @param tag the tag name
00047         @retun a list of matching blocks
00048         """
00049         return filter(lambda b: b['tag'] == tag, blocks)
00050 
00051 def _get_params(block):
00052         """!
00053         Get a list of params.
00054         @param block the old block
00055         @retun a list of params
00056         """
00057         params = Utils.exists_or_else(block, 'params', {}) or {}
00058         params = Utils.listify(params, 'param')
00059         return params
00060 
00061 def _convert_id(id):
00062         """!
00063         Convert an old id to a new safe id.
00064         Replace spaces with underscores.
00065         Lower case the odl id.
00066         @return the reformatted id
00067         """
00068         return id.lower().replace(' ', '_')
00069 
00070 def convert(file_path, platform):
00071         """!
00072         Convert the flow graph to the new format.
00073         Make a backup of the old file.
00074         Save a reformated flow graph to the file path.
00075         If this is a new format flow graph, do nothing.
00076         @param file_path the path to the saved flow graph
00077         @param platform the grc gnuradio platform
00078         """
00079         try: #return if file passes validation
00080                 ParseXML.validate_dtd(file_path, FLOW_GRAPH_DTD)
00081                 try:
00082                         changed = False
00083                         #convert instances of gui_coordinate and gui_rotation
00084                         xml = etree.parse(file_path)
00085                         for find, replace in (
00086                                 ('gui_coordinate', '_coordinate'),
00087                                 ('gui_rotation', '_rotation'),
00088                         ):
00089                                 keys = xml.xpath('/flow_graph/block/param[key="%s"]/key'%find)
00090                                 for key in keys:
00091                                         key.text = replace
00092                                         changed = True
00093                         if not changed: return
00094                         #backup after successful conversion
00095                         os.rename(file_path, file_path+'.bak')
00096                         #save new flow graph to file path
00097                         xml.write(file_path, xml_declaration=True, pretty_print=True)
00098                 except Exception, e: print e
00099                 return
00100         except: pass #convert
00101         ############################################################
00102         # extract window size, variables, blocks, and connections
00103         ############################################################
00104         old_n = ParseXML.from_file(file_path)['flow_graph']
00105         try: window_width = min(3*int(old_n['window_width'])/2, 2048)
00106         except: window_width = 2048
00107         try: window_height = min(3*int(old_n['window_height'])/2, 2048)
00108         except: window_height = 2048
00109         window_size = '%d, %d'%(window_width, window_height)
00110         variables = Utils.exists_or_else(old_n, 'vars', {}) or {}
00111         variables = Utils.listify(variables, 'var')
00112         blocks = Utils.exists_or_else(old_n, 'signal_blocks', {}) or {}
00113         blocks = Utils.listify(blocks, 'signal_block')
00114         connections = Utils.exists_or_else(old_n, 'connections', {}) or {}
00115         connections = Utils.listify(connections, 'connection')
00116         #initialize new nested data
00117         new_n = odict()
00118         new_n['block'] = list()
00119         new_n['connection'] = list()
00120         ############################################################
00121         # conversion - options block
00122         ############################################################
00123         #get name
00124         about_blocks = _get_blocks(blocks, 'About')
00125         if about_blocks: title = _get_params(about_blocks[0])[0]
00126         else: title = 'Untitled'
00127         #get author
00128         if about_blocks: author = _get_params(about_blocks[0])[1]
00129         else: author = ''
00130         #get desc
00131         note_blocks = _get_blocks(blocks, 'Note')
00132         if note_blocks: desc = _get_params(note_blocks[0])[0]
00133         else: desc = ''
00134         #create options block
00135         options_block = odict()
00136         options_block['key'] = 'options'
00137         options_block['param'] = [
00138                 _make_param('id', 'top_block'),
00139                 _make_param('title', title),
00140                 _make_param('author', author),
00141                 _make_param('description', desc),
00142                 _make_param('window_size', window_size),
00143                 _make_param('_coordinate', '(10, 10)'),
00144         ]
00145         #append options block
00146         new_n['block'].append(options_block)
00147         ############################################################
00148         # conversion - variables
00149         ############################################################
00150         x = 100 
00151         for variable in variables:
00152                 key = variable['key']
00153                 value = variable['value']
00154                 minimum = Utils.exists_or_else(variable, 'min', '')
00155                 maximum = Utils.exists_or_else(variable, 'max', '')
00156                 step = Utils.exists_or_else(variable, 'step', '')
00157                 x = x + 150
00158                 coor = '(%d, %d)'%(x, 10)
00159                 var_block = odict()
00160                 if minimum and maximum: #slider varible
00161                         #determine num steps
00162                         try: num_steps = str(int((float(maximum) - float(minimum))/float(step)))
00163                         except: num_steps = '100'
00164                         var_block['key'] = 'variable_slider'
00165                         var_block['param'] = [
00166                                 _make_param('id', key),
00167                                 _make_param('value', value),
00168                                 _make_param('min', minimum),
00169                                 _make_param('max', maximum),
00170                                 _make_param('num_steps', num_steps),
00171                                 _make_param('_coordinate', coor),
00172                         ]
00173                 else: #regular variable
00174                         var_block['key'] = 'variable'
00175                         var_block['param'] = [
00176                                 _make_param('id', key),
00177                                 _make_param('value', value),
00178                                 _make_param('_coordinate', coor),
00179                         ]
00180                 #append variable block
00181                 new_n['block'].append(var_block)
00182         ############################################################
00183         # conversion - blocks
00184         ############################################################
00185         #create name to key map for all blocks in platform
00186         name_to_key = dict((b.get_name(), b.get_key()) for b in platform.get_blocks())
00187         for block in blocks:
00188                 #extract info
00189                 tag = block['tag']
00190                 #ignore list
00191                 if tag in ('Note', 'About'): continue
00192                 id = _convert_id(block['id'])
00193                 coor = '(%s, %s + 100)'%(
00194                         Utils.exists_or_else(block, 'x_coordinate', '0'),
00195                         Utils.exists_or_else(block, 'y_coordinate', '0'),
00196                 )
00197                 rot = Utils.exists_or_else(block, 'rotation', '0')
00198                 params = _get_params(block)
00199                 #new block
00200                 new_block = odict()
00201                 matches = difflib.get_close_matches(tag, name_to_key.keys(), 1)
00202                 if not matches: continue
00203                 #match found
00204                 key = name_to_key[matches[0]]
00205                 new_block['key'] = key
00206                 new_block['param'] = [
00207                         _make_param('id', id),
00208                         _make_param('_coordinate', coor),
00209                         _make_param('_rotation', rot),
00210                 ]
00211                 #handle specific blocks
00212                 if key == 'wxgui_fftsink2':
00213                         params = params[0:3] + ['0'] + params[3:4] + ['8'] + params[4:]
00214                 #append params
00215                 for i, param in enumerate(params):
00216                         platform_block = platform.get_block(key)
00217                         try: platform_param = platform_block.get_params()[i+2]
00218                         except IndexError: break
00219                         if platform_param.is_enum():
00220                                 try: param_value = platform_param.get_option_keys()[int(param)]
00221                                 except: param_value = platform_param.get_option_keys()[0]
00222                         else:
00223                                 param_value = param.replace('$', '').replace('^', '**')
00224                         new_block['param'].append(_make_param(platform_param.get_key(), param_value))
00225                 #append block
00226                 new_n['block'].append(new_block)
00227         ############################################################
00228         # conversion - connections
00229         ############################################################
00230         for connection in connections:
00231                 #extract info
00232                 input_signal_block_id = connection['input_signal_block_id']
00233                 input_socket_index = connection['input_socket_index']
00234                 output_signal_block_id = connection['output_signal_block_id']
00235                 output_socket_index = connection['output_socket_index']
00236                 #new connection
00237                 new_conn = odict()
00238                 new_conn['source_block_id'] = _convert_id(output_signal_block_id)
00239                 new_conn['sink_block_id'] = _convert_id(input_signal_block_id)
00240                 new_conn['source_key'] = output_socket_index
00241                 new_conn['sink_key'] = input_socket_index
00242                 #append connection
00243                 new_n['connection'].append(new_conn)
00244         ############################################################
00245         # backup and replace
00246         ############################################################
00247         #backup after successful conversion
00248         os.rename(file_path, file_path+'.bak')
00249         #save new flow graph to file path
00250         ParseXML.to_file({'flow_graph': new_n}, file_path)
00251 

Generated on Sat Aug 23 02:00:11 2008 for GNU Radio Companion by  doxygen 1.5.4