1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """model objects used by the configuration assistant steps"""
23
24 import random
25
26 from flumotion.common import log
27 from flumotion.common.errors import ComponentValidationError
28 from flumotion.common.fraction import fractionFromValue
29
30 __version__ = "$Rev: 7738 $"
34 """Generate a random US-ASCII string of length numchars
35 """
36 s = ""
37 chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
38 for unused in range(numchars):
39 s += chars[random.randint(0, len(chars)-1)]
40
41 return s
42
45 """I am a special dictionary which you also can treat as an instance.
46 Setting and getting an attribute works.
47 This is suitable for using in a kiwi proxy.
48 >>> p = Properties()
49 >>> p.attr = 'value'
50 >>> p
51 <Properties {'attr': 'value'}>
52
53 Note that you cannot insert the attributes which has the same name
54 as dictionary methods, such as 'keys', 'values', 'items', 'update'.
55
56 Underscores are converted to dashes when setting attributes, eg:
57
58 >>> p.this_is_outrageous = True
59 >>> p
60 <Properties {'this-is-outrageous': True}>
61 """
62
64 if attr in dict.__dict__:
65 raise AttributeError(
66 "Cannot set property %r, it's a dictionary attribute"
67 % (attr, ))
68 dict.__setitem__(self, attr, value)
69
71 self[attr.replace('_', '-')] = value
72
74 attr = attr.replace('_', '-')
75 try:
76 return self[attr]
77 except KeyError:
78 raise AttributeError(
79 "%r object has no attribute %r" % (
80 self, attr))
81
83 del self[attr.replace('_', '-')]
84
87
89 return '<Properties %r>' % (dict.__repr__(self), )
90
93 """I am a Component.
94 A component has a name which identifies it and must be unique
95 within a flow.
96 A component has a list of feeders and a list of eaters and must
97 belong to a worker. The feeder list or the eater list can be empty,
98 but not both at the same time.
99 @cvar eaterType: restrict the eaters which can be linked with this
100 component to this type
101 @cvar feederType: restrict the feeders which can be linked with this
102 component to this type
103 @cvar componentType: the type of the component, such as ogg-muxer,
104 this is not mandatory in the class, can also be set in the instance.
105 @cvar isAtmosphereComponent: if this component should live in
106 the atmosphere instead of in a flow
107 @ivar name: name of the component
108 @ivar exists: if the component already exists, if this is set to true,
109 a configuration saver or validator might chose to ignore this component
110 """
111 eaterType = None
112 feederType = None
113 componentType = None
114 isAtmosphereComponent = False
115
124
126 return '<%s.%s name=%r>' % (self.__class__.__module__,
127 self.__class__.__name__, self.name)
128
129
130
131 @property
133 import warnings
134 warnings.warn('Use %s.componentType' % (self.__class__.__name, ),
135 DeprecationWarning, stacklevel=2)
136 return self.componentType
137
142
145
148
151
153 """
154 Add a plug to the component
155 @param plug: the plug
156 @type plug: L{Plug}
157 """
158 self.plugs.append(plug)
159
160 - def link(self, component):
161 """Link two components together
162 @param component: component to link with
163 @type component: Component
164 """
165 if not isinstance(component, Component):
166 raise TypeError(
167 "component must be a Component, not %r" % (component, ))
168 self.feeders.append(component)
169 component.eaters.append(self)
170
172 """Unlink two components from each other
173 @param component: component to unlink from
174 @type component: Component
175 """
176 if not isinstance(component, Component):
177 raise TypeError(
178 "component must be a Component, not %r" % (component, ))
179
180 self.feeders.remove(component)
181 component.eaters.remove(self)
182
184 """Get the names of all the eaters for this component
185 @returns: feeder names
186 """
187
188
189
190 for source in self.eaters:
191 feederName = source.getFeederName(self)
192 if feederName is None:
193 feederName = ''
194 else:
195 feederName = ':' + feederName
196
197 yield source.name + feederName
198
200 """Get the feeder name a component should use to link to
201 @param component: the component who links to this
202 @type component: L{Component} subclass
203 @returns: feeder name
204 @rtype: string
205 """
206
207
208 -class Plug(object):
209 """I am a Plug.
210 A plug has a name which identifies it and must be unique
211 within a flow.
212 @cvar plugType: the type of the plug, such as cortado,
213 this is not mandatory in the class, can also be set in the instance.
214 """
215
218
221
224 """I am a component which produces data.
225 """
226
228 super(Producer, self).validate()
229
230 if self.eaters:
231 raise ComponentValidationError(
232 "producer component %s can not have any easters" %
233 (self.name, ))
234
235 if not self.feeders:
236 log.debug("component-validation",
237 "producer component %s doesn't have any feeder" %
238 (self.name, ))
239
251
254 """I am a component which encodes data
255 """
256
258 super(Encoder, self).validate()
259
260 if not self.eaters:
261 raise ComponentValidationError(
262 "encoder component %s must have at least one eater" %
263 (self.name, ))
264
265 if not self.feeders:
266 log.debug("component-validation",
267 "encoder component %s doesn't have any feeder" %
268 (self.name, ))
269
270
271 -class Muxer(Component):
272 """I am a component which muxes data from different components together.
273 """
274
276 super(Muxer, self).validate()
277
278 if not self.eaters:
279 raise ComponentValidationError(
280 "muxer component %s must have at least one eater" %
281 (self.name, ))
282
283 if not self.feeders:
284 log.debug("component-validation",
285 "muxer component %s doesn't have any feeder" %
286 (self.name, ))
287
314
317 """I am a component which produces audio
318 """
319
322 """I am a component which produces video
323 """
324
326 """Get the framerate video producer
327 @returns: the framerate
328 @rtype: fraction: 2 sized tuple of two integers
329 """
330 return fractionFromValue(self.properties.framerate)
331
333 """Get the width of the video producer
334 @returns: the width
335 @rtype: integer
336 """
337 return self.properties.width
338
340 """Get the height of the video producer
341 @returns: the height
342 @rtype: integer
343 """
344 return self.properties.height
345
348 """I am a component which converts video
349 """
350
357
364
378
381
382 - def __init__(self, server, streamer, audioProducer, videoProducer):
383 """
384 @param server: server
385 @type server: L{HTTPServer} subclass
386 @param streamer: streamer
387 @type streamer: L{HTTPStreamer}
388 @param audioProducer: audio producer
389 @type audioProducer: L{flumotion.admin.assistant.models.AudioProducer}
390 subclass or None
391 @param videoProducer: video producer
392 @type videoProducer: L{flumotion.admin.assistant.models.VideoProducer}
393 subclass or None
394 """
395 super(HTTPPlug, self).__init__()
396 self.server = server
397 self.streamer = streamer
398 self.audioProducer = audioProducer
399 self.videoProducer = videoProducer
400
403 """I am a model representing the configuration file for a
404 porter component.
405 """
406 componentType = 'porter'
407 isAtmosphereComponent = True
408
409 - def __init__(self, worker, port, username=None, password=None,
410 socketPath=None):
425
426
427
430
433
436
439
440
441
446