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$"
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
135
137 return not self.__eq__(other)
138
139
140
141 @property
143 import warnings
144 warnings.warn('Use %s.componentType' % (self.__class__.__name, ),
145 DeprecationWarning, stacklevel=2)
146 return self.componentType
147
152
155
158
161
163 """
164 Add a plug to the component
165 @param plug: the plug
166 @type plug: L{Plug}
167 """
168 self.plugs.append(plug)
169
172
173 - def link(self, component):
174 """Link two components together
175 @param component: component to link with
176 @type component: Component
177 """
178 if not isinstance(component, Component):
179 raise TypeError(
180 "component must be a Component, not %r" % (component, ))
181 self.feeders.append(component)
182 component.eaters.append(self)
183
185 """Unlink two components from each other
186 @param component: component to unlink from
187 @type component: Component
188 """
189 if not isinstance(component, Component):
190 raise TypeError(
191 "component must be a Component, not %r" % (component, ))
192
193 self.feeders.remove(component)
194 component.eaters.remove(self)
195
197 """Get the names of all the eaters for this component
198 @returns: feeder names
199 """
200
201
202
203 for source in self.eaters:
204 feederName = source.getFeederName(self)
205 if feederName is None:
206 feederName = ''
207 else:
208 feederName = ':' + feederName
209
210 yield source.name + feederName
211
213 """Get the feeder name a component should use to link to
214 @param component: the component who links to this
215 @type component: L{Component} subclass
216 @returns: feeder name
217 @rtype: string
218 """
219
220
221 -class Plug(object):
222 """I am a Plug.
223 A plug has a name which identifies it and must be unique
224 within a flow.
225 @cvar plugType: the type of the plug, such as cortado,
226 this is not mandatory in the class, can also be set in the instance.
227 """
228
231
234
237 """I am a component which produces data.
238 """
239
241 super(Producer, self).validate()
242
243 if self.eaters:
244 raise ComponentValidationError(
245 "producer component %s can not have any eaters" %
246 (self.name, ))
247
248 if not self.feeders:
249 log.debug("component-validation",
250 "producer component %s doesn't have any feeder" %
251 (self.name, ))
252
264
267 """I am a component which encodes data
268 """
269
271 super(Encoder, self).validate()
272
273 if not self.eaters:
274 raise ComponentValidationError(
275 "encoder component %s must have at least one eater" %
276 (self.name, ))
277
278 if not self.feeders:
279 log.debug("component-validation",
280 "encoder component %s doesn't have any feeder" %
281 (self.name, ))
282
283
284 -class Muxer(Component):
285 """I am a component which muxes data from different components together.
286 """
287
289 super(Muxer, self).validate()
290
291 if not self.eaters:
292 raise ComponentValidationError(
293 "muxer component %s must have at least one eater" %
294 (self.name, ))
295
296 if not self.feeders:
297 log.debug("component-validation",
298 "muxer component %s doesn't have any feeder" %
299 (self.name, ))
300
329
332 """I am a component which produces audio
333 """
334
337 """I am a component which produces video
338 """
339
341 """Get the framerate video producer
342 @returns: the framerate
343 @rtype: fraction: 2 sized tuple of two integers
344 """
345 return fractionFromValue(self.getProperties().framerate)
346
348 """Get the width of the video producer
349 @returns: the width
350 @rtype: integer
351 """
352 return self.getProperties().width
353
355 """Get the height of the video producer
356 @returns: the height
357 @rtype: integer
358 """
359 return self.getProperties().height
360
363 """I am a component which converts video
364 """
365
372
379
393
396
397 - def __init__(self, server, streamer, audioProducer, videoProducer):
398 """
399 @param server: server
400 @type server: L{HTTPServer} subclass
401 @param streamer: streamer
402 @type streamer: L{HTTPStreamer}
403 @param audioProducer: audio producer
404 @type audioProducer: L{flumotion.admin.assistant.models.AudioProducer}
405 subclass or None
406 @param videoProducer: video producer
407 @type videoProducer: L{flumotion.admin.assistant.models.VideoProducer}
408 subclass or None
409 """
410 super(HTTPPlug, self).__init__()
411 self.server = server
412 self.streamer = streamer
413 self.audioProducer = audioProducer
414 self.videoProducer = videoProducer
415
418 """I am a model representing the configuration file for a
419 porter component.
420 """
421 componentType = 'porter'
422 isAtmosphereComponent = True
423
424 - def __init__(self, worker, port, username=None, password=None,
425 socketPath=None):
440
441
442
445
448
451
454
455
456
461