class MediaDescription: "The MediaDescription encapsulates all of the SDP media descriptions" def __init__(self, text=None): self.media = None self.nettype = 'IN' self.addrfamily = 'IP4' self.ipaddr = None self.port = None self.transport = None self.formats = [] self._d = {} self._a = {} self.rtpmap = OrderedDict() self.media = 'audio' self.transport = 'RTP/AVP' self.keyManagement = None if text: parse_m(self, 'm', text) def setFormats(self, formats): if self.media in ( 'audio', 'video'): for pt in formats: pt = int(pt) if pt < 97: try: PT = RTPDict[pt] except KeyError: # We don't know this one - hopefully there's an # a=rtpmap entry for it. continue self.addRtpMap(PT) # XXX the above line is unbound local variable error if not RTPDict.has_key(pt) --Zooko 2004-09-29 self.formats = formats def setMedia(self, media): self.media = media def setTransport(self, transport): self.transport = transport def setServerIP(self, l): self.ipaddr = l def setLocalPort(self, l): self.port = l def setKeyManagement(self, km): parse_a(self, 'keymgmt', km) def clearRtpMap(self): self.rtpmap = OrderedDict() def addRtpMap(self, fmt): if fmt.pt is None: pts = self.rtpmap.keys() pts.sort() if pts and pts[-1] > 100: payload = pts[-1] + 1 else: payload = 101 else: payload = fmt.pt rtpmap = "%d %s/%d%s%s"%(payload, fmt.name, fmt.clock, ((fmt.params and '/') or ""), fmt.params or "") self.rtpmap[int(payload)] = (rtpmap, fmt) self._a.setdefault('rtpmap', OrderedDict())[payload] = rtpmap self.formats.append(str(payload)) def addFMTP(self, streamtype, mode="rtp-midi", profile_level=12, config=0): """specific for midirtp""" payload = 96 fmtp = "%d streamtype=%d; mode=%s; profile-level-id=%d; config=%d" % (payload, streamtype, mode, profile_level, config) self._a.setdefault('fmtp', OrderedDict())[96]= fmtp def intersect(self, other): # See RFC 3264 map1 = self.rtpmap d1 = {} for code,(e,fmt) in map1.items(): d1[rtpmap2canonical(code,e)] = e map2 = other.rtpmap outmap = OrderedDict() # XXX quadratic - make rtpmap an ordereddict for code, (e, fmt) in map2.items(): canon = rtpmap2canonical(code,e) if d1.has_key(canon): outmap[code] = (e, fmt) self.rtpmap = outmap self.formats = [ str(x) for x in self.rtpmap.keys() ] self._a['rtpmap'] = OrderedDict([ (code,e) for (code, (e, fmt)) in outmap.items() ])
class MediaDescription: "The MediaDescription encapsulates all of the SDP media descriptions" def __init__(self, text=None): self.media = None self.nettype = 'IN' self.addrfamily = 'IP4' self.ipaddr = None self.port = None self.transport = None self.formats = [] self._d = {} self._a = {} self.rtpmap = OrderedDict() self.media = 'audio' self.transport = 'RTP/AVP' self.keyManagement = None if text: parse_m(self, 'm', text) def setFormats(self, formats): if self.media in ('audio', 'video'): for pt in formats: pt = int(pt) if pt < 97: try: PT = RTPDict[pt] except KeyError: # We don't know this one - hopefully there's an # a=rtpmap entry for it. continue self.addRtpMap(PT) # XXX the above line is unbound local variable error if not RTPDict.has_key(pt) --Zooko 2004-09-29 self.formats = formats def setMedia(self, media): self.media = media def setTransport(self, transport): self.transport = transport def setServerIP(self, l): self.ipaddr = l def setLocalPort(self, l): self.port = l def setKeyManagement(self, km): parse_a(self, 'keymgmt', km) def clearRtpMap(self): self.rtpmap = OrderedDict() def addRtpMap(self, fmt): if fmt.pt is None: pts = list(self.rtpmap.keys()) pts.sort() if pts and pts[-1] > 100: payload = pts[-1] + 1 else: payload = 101 else: payload = fmt.pt rtpmap = "%d %s/%d%s%s" % (payload, fmt.name, fmt.clock, ( (fmt.params and '/') or ""), fmt.params or "") self.rtpmap[int(payload)] = (rtpmap, fmt) self._a.setdefault('rtpmap', OrderedDict())[payload] = rtpmap self.formats.append(str(payload)) def addFMTP(self, streamtype, mode="rtp-midi", profile_level=12, config=0): """specific for midirtp""" payload = 96 fmtp = "%d streamtype=%d; mode=%s; profile-level-id=%d; config=%d" % ( payload, streamtype, mode, profile_level, config) self._a.setdefault('fmtp', OrderedDict())[96] = fmtp def intersect(self, other): # See RFC 3264 map1 = self.rtpmap d1 = {} for code, (e, fmt) in list(map1.items()): d1[rtpmap2canonical(code, e)] = e map2 = other.rtpmap outmap = OrderedDict() # XXX quadratic - make rtpmap an ordereddict for code, (e, fmt) in list(map2.items()): canon = rtpmap2canonical(code, e) if canon in d1: outmap[code] = (e, fmt) self.rtpmap = outmap self.formats = [str(x) for x in list(self.rtpmap.keys())] self._a['rtpmap'] = OrderedDict([ (code, e) for (code, (e, fmt)) in list(outmap.items()) ])
class VoiceApp(StateMachine): _inbound = None def __init__(self, defer, appl, cookie, **kwargs): self.__cookie = cookie self.__appl = appl self.__legs = OrderedDict() self.__dict__.update(kwargs) self.__currentDTMFKey = None self.__collectedDTMFKeys = '' self.__dtmfSingleMode = True super(VoiceApp, self).__init__(defer, **kwargs) def getDefaultLeg(self): if self.__legs: return self.__legs.values()[0] def getLeg(self, cookie): return self.__legs.get(cookie) def setLeg(self, leg, cookie): self.__legs[cookie] = leg #self.leg.hijackLeg(self) def va_selectDefaultFormat(self, ptlist, callcookie): return self.getLeg(callcookie).selectDefaultFormat(ptlist) def va_incomingRTP(self, packet, callcookie): leg = self.getLeg(callcookie) if leg is None: log.msg('no leg for cookie %s for incoming RTP'%(callcookie,), system='doug') return else: return leg.leg_incomingRTP(packet) def va_outgoingRTP(self, sample, cookie=None): if cookie is None: cookie = self.__cookie self.__appl.outgoingRTP(cookie, sample) def va_start(self, args): self._start(callstart=0, args=args) def va_callstart(self, inboundLeg, args=None): if args is None: args = {} if inboundLeg is not None: self.__legs[inboundLeg.getCookie()] = inboundLeg if self._inbound is None: self._inbound = inboundLeg ce = CallStartedEvent(inboundLeg) ce.args = args self._triggerEvent(ce) def va_callanswered(self, leg=None): if leg is None: leg = self._inbound self._triggerEvent(CallAnsweredEvent(leg)) def va_callrejected(self, leg=None): if leg is None: leg = self._inbound try: del self.__legs[leg] except KeyError: log.msg("can't find leg %s, current legs: %r"%( leg, self.__legs.keys()), system='doug') self._triggerEvent(CallRejectedEvent(leg)) def _clear_legs(self): from shtoom.util import stack #print self, "clearing running legs %r"%(self.__legs.items())#,stack(8) for name, leg in self.__legs.items(): leg._stopAudio() del self.__legs[name] _cleanup = _clear_legs def va_abort(self): self.mediaStop() self._clear_legs() self._triggerEvent(CallEndedEvent(None)) def mediaPlay(self, playlist, leg=None): if leg is None: leg = self.getDefaultLeg() leg.mediaPlay(playlist) def mediaRecord(self, dest, leg=None): if leg is None: leg = self.getDefaultLeg() leg.mediaRecord(dest) def mediaStop(self, leg=None): if leg is None: leg = self.getDefaultLeg() if leg is not None: leg.mediaStop() def mediaStopRecording(self, leg=None): if leg is None: leg = self.getDefaultLeg() if leg is not None: leg.mediaStopRecording() def setTimer(self, delay): return Timer(self, delay) def isPlaying(self, leg=None): if leg is None: leg = self.getDefaultLeg() return leg.isPlaying() def isRecording(self, leg=None): if leg is None: leg = self.getDefaultLeg() return leg.isRecording() def dtmfMode(self, single=False, inband=False, timeout=0, leg=None): if leg is None: leg = self.getDefaultLeg() leg.dtmfMode(single, inband, timeout) def placeCall(self, toURI, fromURI=None): from shtoom.doug.leg import Leg nleg = Leg(cookie=None, dialog=None, voiceapp=self) self.__appl.placeCall(self.__cookie, nleg, toURI, fromURI) def va_hangupCall(self, cookie): self.__appl.dropCall(cookie) def connectLegs(self, leg1, leg2=None): from shtoom.doug.leg import Bridge if leg2 is None: leg2 = self.getDefaultLeg() if leg1 is leg2: raise ValueError, "can't join %r to itself!"%(leg1) else: b = Bridge(leg1, leg2) return b def sendDTMF(self, digits, cookie=None, duration=0.1, delay=0.05): "Send a string of DTMF keystrokes" for n,key in enumerate(digits): if key not in ',01234567890#*': raise ValueError, key if key == ',': # pause continue n = float(n) # just in case if cookie is None: cookie = self.__cookie i = 0.2 reactor.callLater(i+n*(duration+delay), lambda k=key: self.__appl.startDTMF(cookie, k)) reactor.callLater(i+n*(duration+delay)+duration, lambda k=key: self.__appl.stopDTMF(cookie, k)) def _inboundDTMFKeyPress(self, dtmf): if self.__dtmfSingleMode: self._triggerEvent(DTMFReceivedEvent(dtmf, self)) else: self.__collectedDTMFKeys += dtmf if dtmf in ('#', '*'): dtmf, self.__collectedDTMFKeys = self.__collectedDTMFKeys, '' self._triggerEvent(DTMFReceivedEvent(dtmf, self)) def va_startDTMFevent(self, dtmf, cookie=None): c = self.__currentDTMFKey if dtmf: if c is not dtmf: self.va_stopDTMFevent(c) self.__currentDTMFKey = dtmf self._inboundDTMFKeyPress(dtmf) else: # repeat pass def va_stopDTMFevent(self, dtmf, cookie=None): # For now, I only care about dtmf start events if dtmf == self.__currentDTMFKey: self.__currentDTMFKey = None
def update_progress(self): """Update the list of recent transfers and current transfers.""" recent_transfers = self.status_frontend.recent_transfers() current_transfers = self.status_frontend.files_uploading() current_transfers.sort(key=itemgetter(2)) current_transfers.reverse() uploading_data = OrderedDict() for filename, size, written in current_transfers: uploading_data[filename] = (size, written) temp_transfers = {} if recent_transfers != self.previous_transfers: logger.debug("Update recent transfers with: %r", recent_transfers) for item_transfer in self._transfers_items: self.child_delete(self._transfers_items[item_transfer]) for item in recent_transfers: recent_file = Dbusmenu.Menuitem() recent_file.property_set( Dbusmenu.MENUITEM_PROP_LABEL, item.replace('_', '__')) self.child_add_position(recent_file, 0) temp_transfers[item] = recent_file self._transfers_items = temp_transfers if self.separator is None: self.separator = Dbusmenu.Menuitem() self.separator.property_set( Dbusmenu.MENUITEM_PROP_TYPE, Dbusmenu.CLIENT_TYPES_SEPARATOR) self.child_append(self.separator) items_added = 0 remove = [] for item in self._uploading_items: if item in uploading_data.keys(): size, written = uploading_data[item] percentage = written * 100 / size upload_item = self._uploading_items[item] upload_item.property_set_int( SyncMenu.PROGRESS_MENUITEM_PROP_PERCENT_DONE, percentage) logger.debug( "Current transfer %s progress update: %r", item, percentage) items_added += 1 else: self.child_delete(self._uploading_items[item]) remove.append(item) for item in remove: self._uploading_items.pop(item) if items_added < 5: for item in uploading_data.keys(): if item not in self._uploading_items and items_added < 5: size, written = uploading_data[item] percentage = written * 100 / size uploading_file = Dbusmenu.Menuitem() uploading_file.property_set( Dbusmenu.MENUITEM_PROP_LABEL, item.replace('_', '__')) uploading_file.property_set( Dbusmenu.MENUITEM_PROP_TYPE, SyncMenu.PROGRESS_MENUITEM_TYPE) uploading_file.property_set_int( SyncMenu.PROGRESS_MENUITEM_PROP_PERCENT_DONE, percentage) logger.debug("Current transfer %s created", item) self.child_append(uploading_file) self._uploading_items[item] = uploading_file items_added += 1
class VoiceApp(StateMachine): _inbound = None def __init__(self, defer, appl, cookie, **kwargs): self.__cookie = cookie self.__appl = appl self.__legs = OrderedDict() self.__dict__.update(kwargs) self.__currentDTMFKey = None self.__collectedDTMFKeys = '' self.__dtmfSingleMode = True super(VoiceApp, self).__init__(defer, **kwargs) def getDefaultLeg(self): if self.__legs: return self.__legs.values()[0] def getLeg(self, cookie): return self.__legs.get(cookie) def setLeg(self, leg, cookie): self.__legs[cookie] = leg #self.leg.hijackLeg(self) def va_selectDefaultFormat(self, ptlist, callcookie): return self.getLeg(callcookie).selectDefaultFormat(ptlist) def va_incomingRTP(self, packet, callcookie): leg = self.getLeg(callcookie) if leg is None: log.msg('no leg for cookie %s for incoming RTP' % (callcookie, ), system='doug') return else: return leg.leg_incomingRTP(packet) def va_outgoingRTP(self, sample, cookie=None): if cookie is None: cookie = self.__cookie self.__appl.outgoingRTP(cookie, sample) def va_start(self, args): self._start(callstart=0, args=args) def va_callstart(self, inboundLeg, args=None): if args is None: args = {} if inboundLeg is not None: self.__legs[inboundLeg.getCookie()] = inboundLeg if self._inbound is None: self._inbound = inboundLeg ce = CallStartedEvent(inboundLeg) ce.args = args self._triggerEvent(ce) def va_callanswered(self, leg=None): if leg is None: leg = self._inbound self._triggerEvent(CallAnsweredEvent(leg)) def va_callrejected(self, leg=None): if leg is None: leg = self._inbound try: del self.__legs[leg] except KeyError: log.msg("can't find leg %s, current legs: %r" % (leg, self.__legs.keys()), system='doug') self._triggerEvent(CallRejectedEvent(leg)) def _clear_legs(self): from shtoom.util import stack #print self, "clearing running legs %r"%(self.__legs.items())#,stack(8) for name, leg in self.__legs.items(): leg._stopAudio() del self.__legs[name] _cleanup = _clear_legs def va_abort(self): self.mediaStop() self._clear_legs() self._triggerEvent(CallEndedEvent(None)) def mediaPlay(self, playlist, leg=None): if leg is None: leg = self.getDefaultLeg() leg.mediaPlay(playlist) def mediaRecord(self, dest, leg=None): if leg is None: leg = self.getDefaultLeg() leg.mediaRecord(dest) def mediaStop(self, leg=None): if leg is None: leg = self.getDefaultLeg() if leg is not None: leg.mediaStop() def mediaStopRecording(self, leg=None): if leg is None: leg = self.getDefaultLeg() if leg is not None: leg.mediaStopRecording() def setTimer(self, delay): return Timer(self, delay) def isPlaying(self, leg=None): if leg is None: leg = self.getDefaultLeg() return leg.isPlaying() def isRecording(self, leg=None): if leg is None: leg = self.getDefaultLeg() return leg.isRecording() def dtmfMode(self, single=False, inband=False, timeout=0, leg=None): if leg is None: leg = self.getDefaultLeg() leg.dtmfMode(single, inband, timeout) def placeCall(self, toURI, fromURI=None): from shtoom.doug.leg import Leg nleg = Leg(cookie=None, dialog=None, voiceapp=self) self.__appl.placeCall(self.__cookie, nleg, toURI, fromURI) def va_hangupCall(self, cookie): self.__appl.dropCall(cookie) def connectLegs(self, leg1, leg2=None): from shtoom.doug.leg import Bridge if leg2 is None: leg2 = self.getDefaultLeg() if leg1 is leg2: raise ValueError, "can't join %r to itself!" % (leg1) else: b = Bridge(leg1, leg2) return b def sendDTMF(self, digits, cookie=None, duration=0.1, delay=0.05): "Send a string of DTMF keystrokes" for n, key in enumerate(digits): if key not in ',01234567890#*': raise ValueError, key if key == ',': # pause continue n = float(n) # just in case if cookie is None: cookie = self.__cookie i = 0.2 reactor.callLater(i + n * (duration + delay), lambda k=key: self.__appl.startDTMF(cookie, k)) reactor.callLater(i + n * (duration + delay) + duration, lambda k=key: self.__appl.stopDTMF(cookie, k)) def _inboundDTMFKeyPress(self, dtmf): if self.__dtmfSingleMode: self._triggerEvent(DTMFReceivedEvent(dtmf, self)) else: self.__collectedDTMFKeys += dtmf if dtmf in ('#', '*'): dtmf, self.__collectedDTMFKeys = self.__collectedDTMFKeys, '' self._triggerEvent(DTMFReceivedEvent(dtmf, self)) def va_startDTMFevent(self, dtmf, cookie=None): c = self.__currentDTMFKey if dtmf: if c is not dtmf: self.va_stopDTMFevent(c) self.__currentDTMFKey = dtmf self._inboundDTMFKeyPress(dtmf) else: # repeat pass def va_stopDTMFevent(self, dtmf, cookie=None): # For now, I only care about dtmf start events if dtmf == self.__currentDTMFKey: self.__currentDTMFKey = None