1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """model objects used by the configuration assistant steps"""
20
21 import random
22
23 from flumotion.common import log
24 from flumotion.common.errors import ComponentValidationError
25 from flumotion.common.fraction import fractionFromValue
26
27 __version__ = "$Rev$"
31 """Generate a random US-ASCII string of length numchars
32 """
33 s = ""
34 chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
35 for unused in range(numchars):
36 s += chars[random.randint(0, len(chars)-1)]
37
38 return s
39
42 """I am a special dictionary which you also can treat as an instance.
43 Setting and getting an attribute works.
44 This is suitable for using in a kiwi proxy.
45 >>> p = Properties()
46 >>> p.attr = 'value'
47 >>> p
48 <Properties {'attr': 'value'}>
49
50 Note that you cannot insert the attributes which has the same name
51 as dictionary methods, such as 'keys', 'values', 'items', 'update'.
52
53 Underscores are converted to dashes when setting attributes, eg:
54
55 >>> p.this_is_outrageous = True
56 >>> p
57 <Properties {'this-is-outrageous': True}>
58 """
59
61 if attr in dict.__dict__:
62 raise AttributeError(
63 "Cannot set property %r, it's a dictionary attribute"
64 % (attr, ))
65 dict.__setitem__(self, attr, value)
66
68 self[attr.replace('_', '-')] = value
69
71 attr = attr.replace('_', '-')
72 try:
73 return self[attr]
74 except KeyError:
75 raise AttributeError(
76 "%r object has no attribute %r" % (
77 self, attr))
78
80 del self[attr.replace('_', '-')]
81
84
86 return '<Properties %r>' % (dict.__repr__(self), )
87
90 """I am a Component.
91 A component has a name which identifies it and must be unique
92 within a flow.
93 A component has a list of feeders and a list of eaters and must
94 belong to a worker. The feeder list or the eater list can be empty,
95 but not both at the same time.
96 @cvar eaterType: restrict the eaters which can be linked with this
97 component to this type
98 @cvar feederType: restrict the feeders which can be linked with this
99 component to this type
100 @cvar componentType: the type of the component, such as ogg-muxer,
101 this is not mandatory in the class, can also be set in the instance.
102 @cvar isAtmosphereComponent: if this component should live in
103 the atmosphere instead of in a flow
104 @ivar name: name of the component
105 @ivar exists: if the component already exists, if this is set to true,
106 a configuration saver or validator might chose to ignore this component
107 """
108 eaterType = None
109 feederType = None
110 componentType = None
111 isAtmosphereComponent = False
112
121
123 return '<%s.%s name=%r>' % (self.__class__.__module__,
124 self.__class__.__name__, self.name)
125
132
134 return not self.__eq__(other)
135
136
137
138 @property
140 import warnings
141 warnings.warn('Use %s.componentType' % (self.__class__.__name, ),
142 DeprecationWarning, stacklevel=2)
143 return self.componentType
144
149
152
155
158
160 """
161 Add a plug to the component
162 @param plug: the plug
163 @type plug: L{Plug}
164 """
165 self.plugs.append(plug)
166
169
170 - def link(self, component):
171 """Link two components together
172 @param component: component to link with
173 @type component: Component
174 """
175 if not isinstance(component, Component):
176 raise TypeError(
177 "component must be a Component, not %r" % (component, ))
178 self.feeders.append(component)
179 component.eaters.append(self)
180
182 """Unlink two components from each other
183 @param component: component to unlink from
184 @type component: Component
185 """
186 if not isinstance(component, Component):
187 raise TypeError(
188 "component must be a Component, not %r" % (component, ))
189
190 self.feeders.remove(component)
191 component.eaters.remove(self)
192
194 """Get the names of all the eaters for this component
195 @returns: feeder names
196 """
197
198
199
200 for source in self.eaters:
201 feederName = source.getFeederName(self)
202 if feederName is None:
203 feederName = ''
204 else:
205 feederName = ':' + feederName
206
207 yield source.name + feederName
208
210 """Get the feeder name a component should use to link to
211 @param component: the component who links to this
212 @type component: L{Component} subclass
213 @returns: feeder name
214 @rtype: string
215 """
216
217
218 -class Plug(object):
219 """I am a Plug.
220 A plug has a name which identifies it and must be unique
221 within a flow.
222 @cvar plugType: the type of the plug, such as cortado,
223 this is not mandatory in the class, can also be set in the instance.
224 """
225
228
231
234 """I am a component which produces data.
235 """
236
238 super(Producer, self).validate()
239
240 if self.eaters:
241 raise ComponentValidationError(
242 "producer component %s can not have any eaters" %
243 (self.name, ))
244
245 if not self.feeders:
246 log.debug("component-validation",
247 "producer component %s doesn't have any feeder" %
248 (self.name, ))
249
261
264 """I am a component which encodes data
265 """
266
268 super(Encoder, self).validate()
269
270 if not self.eaters:
271 raise ComponentValidationError(
272 "encoder component %s must have at least one eater" %
273 (self.name, ))
274
275 if not self.feeders:
276 log.debug("component-validation",
277 "encoder component %s doesn't have any feeder" %
278 (self.name, ))
279
280
281 -class Muxer(Component):
282 """I am a component which muxes data from different components together.
283 """
284
286 super(Muxer, self).validate()
287
288 if not self.eaters:
289 raise ComponentValidationError(
290 "muxer component %s must have at least one eater" %
291 (self.name, ))
292
293 if not self.feeders:
294 log.debug("component-validation",
295 "muxer component %s doesn't have any feeder" %
296 (self.name, ))
297
326
329 """I am a component which produces audio
330 """
331
333 """Get the samplerate audio producer
334 @returns: the samplerate
335 @rtype: int
336 """
337 return self.getProperties().samplerate
338
341 """I am a component which produces video
342 """
343
345 """Get the framerate video producer
346 @returns: the framerate
347 @rtype: fraction: 2 sized tuple of two integers
348 """
349 return fractionFromValue(self.getProperties().framerate)
350
352 """Get the width of the video producer
353 @returns: the width
354 @rtype: integer
355 """
356 return self.getProperties().width
357
359 """Get the height of the video producer
360 @returns: the height
361 @rtype: integer
362 """
363 return self.getProperties().height
364
367 """I am a component which converts video
368 """
369
376
383
397
400
401 - def __init__(self, server, streamer, audioProducer, videoProducer):
402 """
403 @param server: server
404 @type server: L{HTTPServer} subclass
405 @param streamer: streamer
406 @type streamer: L{HTTPStreamer}
407 @param audioProducer: audio producer
408 @type audioProducer: L{flumotion.admin.assistant.models.AudioProducer}
409 subclass or None
410 @param videoProducer: video producer
411 @type videoProducer: L{flumotion.admin.assistant.models.VideoProducer}
412 subclass or None
413 """
414 super(HTTPPlug, self).__init__()
415 self.server = server
416 self.streamer = streamer
417 self.audioProducer = audioProducer
418 self.videoProducer = videoProducer
419
422 """I am a model representing the configuration file for a
423 porter component.
424 """
425 componentType = 'porter'
426 isAtmosphereComponent = True
427
428 - def __init__(self, worker, port, username=None, password=None,
429 socketPath=None):
444
445
446
449
452
455
458
459
460
465