added include <cstdio> statements in several files to make it compatible with g+...
[debian/gnuradio] / grc / src / platforms / base / Platform.py
1 """
2 Copyright 2008, 2009 Free Software Foundation, Inc.
3 This file is part of GNU Radio
4
5 GNU Radio Companion is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 GNU Radio Companion is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18 """
19
20 import os
21 from ... utils import ParseXML
22 from Element import Element as _Element
23 from FlowGraph import FlowGraph as _FlowGraph
24 from Connection import Connection as _Connection
25 from Block import Block as _Block
26 from Port import Port as _Port
27 from Param import Param as _Param
28 from Constants import BLOCK_TREE_DTD
29
30 class Platform(_Element):
31
32         def __init__(self, name, key, block_paths, block_dtd, block_tree, default_flow_graph, generator):
33                 """
34                 Make a platform from the arguments.
35                 @param name the platform name
36                 @param key the unique platform key
37                 @param block_paths the file paths to blocks in this platform
38                 @param block_dtd the dtd validator for xml block wrappers
39                 @param block_tree the nested tree of block keys and categories
40                 @param default_flow_graph the default flow graph file path
41                 @param load_one a single file to load into this platform or None
42                 @return a platform object
43                 """
44                 _Element.__init__(self)
45                 self._name = name
46                 self._key = key
47                 self._block_paths = block_paths
48                 self._block_dtd = block_dtd
49                 self._block_tree = block_tree
50                 self._default_flow_graph = default_flow_graph
51                 self._generator = generator
52                 #create a dummy flow graph for the blocks
53                 self._flow_graph = _Element(self)
54                 #load the blocks
55                 self._blocks = dict()
56                 self._blocks_n = dict()
57                 for block_path in self._block_paths:
58                         if os.path.isfile(block_path): self._load_blocks(block_path)
59                         elif os.path.isdir(block_path):
60                                 for dirpath, dirnames, filenames in os.walk(block_path):
61                                         for filename in filter(lambda f: f.endswith('.xml'), filenames):
62                                                 self._load_blocks(os.path.join(dirpath, filename))
63
64         def _load_blocks(self, f):
65                 """
66                 Load the block wrappers from the file path.
67                 The block wrapper must pass validation.
68                 If any of the checks fail, exit with error.
69                 @param f the file path
70                 """
71                 try: ParseXML.validate_dtd(f, self._block_dtd)
72                 except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block definition "%s" failed: \n\t%s'%(f, e))
73                 n = ParseXML.from_file(f).find('block')
74                 #inject block wrapper path
75                 n['block_wrapper_path'] = f
76                 block = self.Block(self._flow_graph, n)
77                 key = block.get_key()
78                 #test against repeated keys
79                 try: assert(key not in self.get_block_keys())
80                 except AssertionError: self._exit_with_error('Key "%s" already exists in blocks'%key)
81                 #store the block
82                 self._blocks[key] = block
83                 self._blocks_n[key] = n
84
85         def load_block_tree(self, block_tree):
86                 """
87                 Load a block tree with categories and blocks.
88                 Step 1: Load all blocks from the xml specification.
89                 Step 2: Load blocks with builtin category specifications.
90                 @param block_tree the block tree object
91                 """
92                 #recursive function to load categories and blocks
93                 def load_category(cat_n, parent=[]):
94                         #add this category
95                         parent = parent + [cat_n.find('name')]
96                         block_tree.add_block(parent)
97                         #recursive call to load sub categories
98                         map(lambda c: load_category(c, parent), cat_n.findall('cat'))
99                         #add blocks in this category
100                         for block_key in cat_n.findall('block'):
101                                 block_tree.add_block(parent, self.get_block(block_key))
102                 #load the block tree
103                 f = self._block_tree
104                 try: ParseXML.validate_dtd(f, BLOCK_TREE_DTD)
105                 except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block tree "%s" failed: \n\t%s'%(f, e))
106                 #add all blocks in the tree
107                 load_category(ParseXML.from_file(f).find('cat'))
108                 #add all other blocks, use the catgory
109                 for block in self.get_blocks():
110                         #blocks with empty categories are in the xml block tree or hidden
111                         if block.get_category(): block_tree.add_block(block.get_category(), block)
112
113         def __str__(self): return 'Platform - %s(%s)'%(self.get_key(), self.get_name())
114
115         def is_platform(self): return True
116
117         def get_new_flow_graph(self): return self.FlowGraph(self)
118
119         def get_default_flow_graph(self): return self._default_flow_graph
120
121         def get_generator(self): return self._generator
122
123         ##############################################
124         # Access Blocks
125         ##############################################
126         def get_block_keys(self): return self._blocks.keys()
127         def get_block(self, key): return self._blocks[key]
128         def get_blocks(self): return self._blocks.values()
129         def get_new_block(self, flow_graph, key): return self.Block(flow_graph, n=self._blocks_n[key])
130
131         def get_name(self): return self._name
132
133         def get_key(self): return self._key
134
135         ##############################################
136         # Constructors
137         ##############################################
138         FlowGraph = _FlowGraph
139         Connection = _Connection
140         Block = _Block
141         Source = _Port
142         Sink = _Port
143         Param = _Param