Package flumotion :: Package component :: Package producers :: Package soundcard :: Module soundcard
[hide private]

Source Code for Module flumotion.component.producers.soundcard.soundcard

  1  # -*- Mode: Python; test-case-name:flumotion.test.test_soundcard -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3  # 
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007 Fluendo, S.L. (www.fluendo.com). 
  6  # All rights reserved. 
  7   
  8  # This file may be distributed and/or modified under the terms of 
  9  # the GNU General Public License version 2 as published by 
 10  # the Free Software Foundation. 
 11  # This file is distributed without any warranty; without even the implied 
 12  # warranty of merchantability or fitness for a particular purpose. 
 13  # See "LICENSE.GPL" in the source distribution for more information. 
 14   
 15  # Licensees having purchased or holding a valid Flumotion Advanced 
 16  # Streaming Server license may use this file in accordance with the 
 17  # Flumotion Advanced Streaming Server Commercial License Agreement. 
 18  # See "LICENSE.Flumotion" in the source distribution for more information. 
 19   
 20  # Headers in this file shall remain intact. 
 21   
 22  import gst 
 23  import gst.interfaces 
 24   
 25  from twisted.internet import defer 
 26   
 27  from flumotion.common import messages 
 28  from flumotion.common.i18n import N_, gettexter 
 29  from flumotion.component import feedcomponent 
 30  from flumotion.component.effects.volume import volume 
 31   
 32  __version__ = "$Rev: 7015 $" 
 33  T_ = gettexter() 
 34   
 35   
36 -class Soundcard(feedcomponent.ParseLaunchComponent):
37 - def do_check(self):
38 self.debug('running PyGTK/PyGST checks') 39 from flumotion.component.producers import checks 40 d1 = checks.checkTicket347() 41 d2 = checks.checkTicket348() 42 dl = defer.DeferredList([d1, d2]) 43 dl.addCallback(self._checkCallback) 44 return dl
45
46 - def _checkCallback(self, results):
47 for (state, result) in results: 48 for m in result.messages: 49 self.addMessage(m)
50
51 - def get_pipeline_string(self, properties):
52 element = properties.get('source-element', 'alsasrc') 53 self.device = properties.get('device', 'hw:0') 54 rate = properties.get('rate', 44100) 55 depth = properties.get('depth', 16) 56 channels = properties.get('channels', 2) 57 self.inputTrackLabel = properties.get('input-track', None) 58 d = self._change_monitor.add(gst.STATE_CHANGE_NULL_TO_READY) 59 d.addCallback(self._set_input_track, self.inputTrackLabel) 60 # FIXME: we should find a way to figure out what the card supports, 61 # so we can add in correct elements on the fly 62 # just adding audioscale and audioconvert always makes the soundcard 63 # open in 1000 Hz, mono 64 caps = 'audio/x-raw-int,rate=(int)%d,depth=%d,channels=%d' % ( 65 rate, depth, channels) 66 pipeline = "%s device=%s name=src ! %s ! " \ 67 "level name=volumelevel message=true" % ( 68 element, self.device, caps) 69 self._srcelement = None 70 return pipeline
71
72 - def configure_pipeline(self, pipeline, properties):
73 # add volume effect 74 comp_level = pipeline.get_by_name('volumelevel') 75 allowVolumeSet = True 76 if gst.pygst_version < (0, 10, 7): 77 allowVolumeSet = False 78 m = messages.Info(T_( 79 N_("The soundcard volume cannot be changed with this version " 80 "of the 'gst-python' library.\n")), 81 mid='mixer-track-setting') 82 m.add(T_(N_("Please upgrade '%s' to version %s or later " 83 "if you require this functionality."), 84 'gst-python', '0.10.7')) 85 self.addMessage(m) 86 87 vol = volume.Volume('inputVolume', comp_level, pipeline, 88 allowIncrease=False, allowVolumeSet=allowVolumeSet) 89 self.addEffect(vol) 90 self._srcelement = pipeline.get_by_name("src")
91
92 - def _set_input_track(self, result, trackLabel=None):
93 element = self._srcelement 94 for track in element.list_tracks(): 95 if trackLabel != None: 96 self.debug("Setting track %s to record", trackLabel) 97 # some low-end sound cards require the Capture track to be 98 # set to recording to get any sound, so set that track and 99 # the input track we selected 100 element.set_record(track, 101 (track.get_property("label") == trackLabel or 102 track.get_property("label") == "Capture"))
103
104 - def setVolume(self, value):
105 if gst.pygst_version < (0, 10, 7): 106 self.warning( 107 "Cannot set volume on soundcards with gst-python < 0.10.7") 108 return 109 self.debug("Volume set to: %f", value) 110 if self.inputTrackLabel and self._srcelement: 111 element = self._srcelement 112 volumeSet = False 113 for track in element.list_tracks(): 114 if track.get_property("label") == self.inputTrackLabel: 115 volumeVals = tuple(int(value/1.0 * 116 track.get_property("max-volume")) 117 for _ in xrange(0, track.get_property("num-channels"))) 118 element.set_volume(track, volumeVals) 119 volumeSet = True 120 break 121 if not volumeSet: 122 self.warning("could not find track %s", self.inputTrackLabel) 123 else: 124 self.warning("no input track selected, cannot set volume")
125
126 - def getVolume(self):
127 if gst.pygst_version < (0, 10, 7): 128 self.warning( 129 "Cannot query volume on soundcards with gst-python < 0.10.7") 130 return 1.0 131 if self.inputTrackLabel and self._srcelement: 132 element = self._srcelement 133 for track in element.list_tracks(): 134 if track.get_property("label") == self.inputTrackLabel: 135 volumeVals = element.get_volume(track) 136 vol = 0 137 nchannels = track.get_property("num-channels") 138 for k in range(0, track.get_property("num-channels")): 139 vol = vol + (volumeVals[k] / nchannels) 140 maxVolume = float(track.get_property('max-volume')) 141 self.debug("vol: %f max vol: %f", vol, maxVolume) 142 143 if maxVolume == 0.0: 144 return 1.0 145 146 v = vol / maxVolume 147 148 self.debug("v: %f", v) 149 return 150 self.warning("could not find track %s", self.inputTrackLabel) 151 else: 152 self.warning("no input track selected, cannot set volume") 153 return 1.0
154
155 - def make_message_for_gstreamer_error(self, gerror, debug):
156 if gerror.domain == 'gst-resource-error-quark': 157 # before 0.10.14 gst-plugins-base had the error as WRITE by mistake 158 if gerror.code in [ 159 gst.RESOURCE_ERROR_OPEN_WRITE, 160 gst.RESOURCE_ERROR_OPEN_READ]: 161 m = messages.Error(T_(N_( 162 "Could not open sound device '%s'. " 163 "Please check permissions on the device."), 164 self.device), debug=debug) 165 return m 166 if gerror.code == gst.RESOURCE_ERROR_BUSY: 167 m = messages.Error(T_(N_( 168 "The sound device '%s' is in use by another program. " 169 "Please stop the other program and try again."), 170 self.device)) 171 return m 172 173 base = feedcomponent.ParseLaunchComponent 174 return base.make_message_for_gstreamer_error(self, gerror, debug)
175