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
00020
00021
00022
00023 import os
00024 from grc import ParseXML
00025 from grc import Utils
00026 from grc.elements.Element import Element as _Element
00027 from grc.elements.FlowGraph import FlowGraph as _FlowGraph
00028 from grc.elements.Connection import Connection as _Connection
00029 from grc.elements.Block import Block as _Block
00030 from grc.elements.Port import Port as _Port
00031 from grc.elements.Param import Param as _Param
00032 from grc.Constants import DATA_DIR
00033
00034 class Platform(_Element):
00035
00036 def __init__(self, name, key, block_paths, block_dtd, block_tree, default_flow_graph, generator):
00037 """!
00038 Make a platform from the arguments.
00039 @param name the platform name
00040 @param key the unique platform key
00041 @param block_paths the file paths to blocks in this platform
00042 @param block_dtd the dtd validator for xml block wrappers
00043 @param block_tree the nested tree of block keys and categories
00044 @param default_flow_graph the default flow graph file path
00045 @param load_one a single file to load into this platform or None
00046 @return a platform object
00047 """
00048 _Element.__init__(self)
00049 self._name = name
00050 self._key = key
00051 self._block_paths = block_paths
00052 self._block_dtd = block_dtd
00053 self._block_tree = block_tree
00054 self._default_flow_graph = default_flow_graph
00055 self._generator = generator
00056
00057 self._flow_graph = _Element(self)
00058
00059 self._blocks = dict()
00060 self._blocks_n = dict()
00061 for block_path in self._block_paths:
00062 if os.path.isfile(block_path): self._load_block(block_path)
00063 elif os.path.isdir(block_path):
00064 for dirpath,dirnames,filenames in os.walk(block_path):
00065 for filename in filter(lambda f: f.endswith('.xml'), filenames):
00066 self._load_block(os.path.join(dirpath, filename))
00067
00068 def get_prefs_block(self): return self.get_new_flow_graph().get_new_block('preferences')
00069
00070 def _load_block(self, f):
00071 """!
00072 Load the block wrapper from the file path.
00073 The block wrapper must pass validation, and have a unique block key.
00074 If any of the checks fail, exit with error.
00075 @param f the file path
00076 """
00077 try: ParseXML.validate_dtd(f, self._block_dtd)
00078 except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block definition "%s" failed: \n\t%s'%(f, e))
00079 n = ParseXML.from_file(f)['block']
00080 block = self.Block(self._flow_graph, n)
00081 key = block.get_key()
00082
00083 try: assert(key not in self.get_block_keys())
00084 except AssertionError: self._exit_with_error('Key "%s" already exists in blocks'%key)
00085
00086 self._blocks[key] = block
00087 self._blocks_n[key] = n
00088
00089 def load_block_tree(self, block_tree):
00090 """!
00091 Load a block tree with categories and blocks.
00092 Step 1: Load all blocks from the xml specification.
00093 Step 2: Load blocks with builtin category specifications.
00094 @param block_tree the block tree object
00095 """
00096
00097 def load_category(cat_n, parent=''):
00098
00099 parent = '%s/%s'%(parent, cat_n['name'])
00100 block_tree.add_block(parent)
00101
00102 map(lambda c: load_category(c, parent), Utils.listify(cat_n, 'cat'))
00103
00104 for block_key in Utils.listify(cat_n, 'block'):
00105 block_tree.add_block(parent, self.get_block(block_key))
00106
00107 f = self._block_tree
00108 try: ParseXML.validate_dtd(f, os.path.join(DATA_DIR, 'block_tree.dtd'))
00109 except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block tree "%s" failed: \n\t%s'%(f, e))
00110
00111 load_category(ParseXML.from_file(f)['cat'])
00112
00113 for block in self.get_blocks():
00114
00115 if block.get_category(): block_tree.add_block(block.get_category(), block)
00116
00117 def __str__(self): return 'Platform - %s(%s)'%(self.get_key(), self.get_name())
00118
00119 def is_platform(self): return True
00120
00121 def get_new_flow_graph(self): return self.FlowGraph(self)
00122
00123 def get_default_flow_graph(self): return self._default_flow_graph
00124
00125 def get_generator(self): return self._generator
00126
00127
00128
00129
00130 def get_block_keys(self): return self._blocks.keys()
00131 def get_block(self, key): return self._blocks[key]
00132 def get_blocks(self): return self._blocks.values()
00133 def get_new_block(self, flow_graph, key): return self.Block(flow_graph, n=self._blocks_n[key])
00134
00135 def get_name(self): return self._name
00136
00137 def get_key(self): return self._key
00138
00139
00140
00141
00142 FlowGraph = _FlowGraph
00143 Connection = _Connection
00144 Block = _Block
00145 Source = _Port
00146 Sink = _Port
00147 Param = _Param