diff options
author | Harald Welte <laforge@gnumonks.org> | 2015-12-05 13:30:46 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2015-12-05 13:51:43 +0100 |
commit | 5b283e8942d845c5c6919c78a9ccf57c6c46da7c (patch) | |
tree | 4b50a35ff9c7c52ff30d2605871b1886d18dd54a /gsm_call_fsm.py | |
parent | a5fce601217645242ac057ef1a32f7e830c0b50e (diff) |
gcm_call_fsm: Allow user to specify which codec(s) are to be used
The user can submit a list of permitted codecs for a GsmCallFsm or
GsmCallConnector. This list is ordered by priority (highest first),
and the first matching codec is chosen.
TODO: Proper error handling in case no matching codec is found
Diffstat (limited to 'gsm_call_fsm.py')
-rw-r--r-- | gsm_call_fsm.py | 72 |
1 files changed, 65 insertions, 7 deletions
diff --git a/gsm_call_fsm.py b/gsm_call_fsm.py index e993de1..1522f57 100644 --- a/gsm_call_fsm.py +++ b/gsm_call_fsm.py @@ -18,6 +18,53 @@ from mncc_sock import mncc_msg, mncc_number, mncc_rtp_msg, mncc_bridge_msg Uint32Array2 = mncc.uint32_t * 2 +class GSM48: + class BCAP_SV(object): + # GSM 04.08 bearer capability speech version + FR = 0 + HR = 1 + EFR = 2 + AMR_F = 4 + AMR_H = 5 + + def __init__(self, codec): + self.codec = codec; + + def __str__(self): + if self.codec == GSM48.BCAP_SV.FR: + return 'FR' + elif self.codec == GSM48.BCAP_SV.HR: + return 'HR' + elif self.codec == GSM48.BCAP_SV.EFR: + return 'EFR' + elif self.codec == GSM48.BCAP_SV.AMR_F: + return 'AMR-FR' + elif self.codec == GSM48.BCAP_SV.AMR_H: + return 'AMR-HR' + else: + return 'Unknown' + + def to_lchan_mode(self): + if self.codec == GSM48.BCAP_SV.FR: + return GSM48.ChanMode.SPEECH_V1 + elif self.codec == GSM48.BCAP_SV.HR: + return GSM48.ChanMode.SPEECH_V1 + elif self.codec == GSM48.BCAP_SV.EFR: + return GSM48.ChanMode.SPEECH_EFR + elif self.codec == GSM48.BCAP_SV.AMR_F: + return GSM48.ChanMode.SPEECH_AMR + elif self.codec == GSM48.BCAP_SV.AMR_H: + return GSM48.ChanMode.SPEECH_AMR + + AllCodecs = (BCAP_SV.FR, BCAP_SV.HR, BCAP_SV.EFR, BCAP_SV.AMR_F, BCAP_SV.AMR_H) + + class ChanMode: + # GSM 04.08 Channel Mode + CMODE_SIGN = 0x00 + SPEECH_V1 = 0x01 + SPEECH_EFR = 0x21 + SPEECH_AMR = 0x41 + class GsmCallFsm(pykka.ThreadingActor): last_callref = 0 @@ -37,11 +84,20 @@ class GsmCallFsm(pykka.ThreadingActor): called = mncc_number(self.called)) self.mncc_ref.tell({'type': 'send', 'msg': msg}) + def find_matching_codec(self, ms_codecs): + # find common denominator of permitted codecs and MS codecs + for i in self.codecs_permitted: + if i in ms_codecs: + return GSM48.BCAP_SV(i) + return None + def _onmncc_call_conf_ind(self, e): msg_in = e.args[0] - for i in msg_in.bearer_cap.speech_ver: - print 'SPV: 0x%02x' % i, - msg = mncc_msg(msg_type = mncc.MNCC_LCHAN_MODIFY, callref = msg_in.callref, lchan_mode = 1) + codec = self.find_matching_codec(msg_in.bearer_cap.speech_ver) + print 'CALL-CONF.ind(selected codec = %s)' % codec + # select the according lchan_mode + lchan_mode = codec.to_lchan_mode() + msg = mncc_msg(msg_type = mncc.MNCC_LCHAN_MODIFY, callref = msg_in.callref, lchan_mode = lchan_mode) self.mncc_ref.tell({'type': 'send', 'msg': msg}) def _onmncc_setup_cnf(self, e): @@ -65,13 +121,14 @@ class GsmCallFsm(pykka.ThreadingActor): if e.event != 'startup': self.stop() - def __init__(self, mncc_ref, ctrl_ref = None, rtp_bridge = True): + def __init__(self, mncc_ref, ctrl_ref = None, rtp_bridge = True, codecs_permitted = GSM48.AllCodecs): super(GsmCallFsm, self).__init__() self.mncc_ref = mncc_ref; self.callref = self._get_next_callref() self.ctrl_ref = ctrl_ref self.rtp_bridge = rtp_bridge self.rtp = None + self.codecs_permitted = codecs_permitted self.fsm = Fysom(initial = 'NULL', events = [ # MT call setup @@ -221,14 +278,15 @@ class GsmCallFsm(pykka.ThreadingActor): class GsmCallConnector(pykka.ThreadingActor): - def __init__(self, mncc_act, rtp_bridge = True): + def __init__(self, mncc_act, rtp_bridge = True, codecs_permitted = GSM48.AllCodecs): super(GsmCallConnector, self).__init__() self.mncc_act = mncc_act self.rtp_bridge = rtp_bridge + self.codecs_permitted = codecs_permitted print 'Starting Call A actor' - self.call_a = GsmCallFsm.start(self.mncc_act, self.actor_ref, self.rtp_bridge) + self.call_a = GsmCallFsm.start(self.mncc_act, self.actor_ref, self.rtp_bridge, self.codecs_permitted) print 'Starting Call B actor' - self.call_b = GsmCallFsm.start(self.mncc_act, self.actor_ref, self.rtp_bridge) + self.call_b = GsmCallFsm.start(self.mncc_act, self.actor_ref, self.rtp_bridge, self.codecs_permitted) self.callref_a = self.call_a.ask({'type':'get_callref'}) self.callref_b = self.call_b.ask({'type':'get_callref'}) self.state_a = self_state_b = 'NULL' |