Changes between Version 12 and Version 13 of Python_SIP_Tutorial


Ignore:
Timestamp:
Jul 22, 2008 9:35:48 PM (11 years ago)
Author:
bennylp
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Python_SIP_Tutorial

    v12 v13  
    2121Applications should use the '''pjsua''' module rather than '''_pjsua''' module, since it is easier to use and it is the module which API compatibility will be maintained between releases. 
    2222 
    23  
    24 == Getting the Module == #getting 
    25  
    26 The Python module source codes along with some samples are included in PJSIP distribution, in [source:pjproject/trunk/pjsip-apps/src/python pjproject/pjsip-apps/src/python] directory. 
    27  
    28  
    29 == Building The Modules == #build 
    30  
    31 Using Microsoft Visual Studio projects: 
    32  * Open '''pjsip-apps.dsw''' from {{{pjsip-apps\build}}} directory. 
    33  * Select '''python_pjsua''' project as the active project. 
    34  * Build the project 
    35  * The {{{_pjsua.pyd}}} Python module will be placed in {{{pjsip-apps\lib}}} directory. 
    36  * Copy {{{_pjsua.pyd}}} and {{{pjsua.py}}} from {{{pjsip-apps\src\python}}} directory to Python's site_packages directory (see Python manual for this), or alternatively add the directories where these files reside to your {{{PYTHONPATH}}} environment variable. 
    37  
    38 Using Python build script: 
    39  * Go to {{{pjsip-apps/src/python}}} directory. 
    40  * Run '''{{{'python ./setup.py build'}}}''' 
    41  * The Python module will be placed in {{{build}}} directory inside current directory. 
    42  * Alternatively run '''{{{'python ./setup.py install'}}}''' to install both '''_pjsua''' and '''pjsua''' modules to Python's site_packages directory. 
    43  
    44 [[BR]] 
    45  
    46  
    47 == Developing Python SIP Application == #develop 
    48  
    49 === Concepts === #concepts 
    50  
    51 ==== Asynchronous Operations ==== 
    52  
    53 If you have developed applications with PJSIP you'll know about this already, but this concept probably needs to be explained a little bit here to new PJSIP users. 
    54  
    55 In PJSIP, all operations that involve sending and receiving SIP messages are asynchronous, meaning that the function that invokes the operation will complete immediately, and you will be given the completion status as callbacks. Take a look for example the {{{make_call()}}} method of the [http://www.pjsip.org/python/pjsua.htm#Account Account] class. This function is used to initiate outgoing call to a destination. When this function returns successfully, it does not mean that the call has been established, but rather that the call has been '''initiated''' successfully. You will be given the report of the call completion (such as ''Ringing'' or ''Connected''/''Confirmed''' events) in the {{{on_state()}}} callback of [http://www.pjsip.org/python/pjsua.htm#CallCallback CallCallback] class. 
    56  
    57  
    58 ==== Basic Usage Pattern ==== 
    59  
    60 Ah, talking about callbacks. 
    61  
    62  
    63  
    64 ==== Error Handling ==== 
    65  
    66 By convention, we use exceptions as means to report error, as this would make the program flows more naturally. Operations which yield error will raise [http://www.pjsip.org/python/pjsua.htm#Error pjsua.Error] exception. Here is a sample: 
    67  
    68  {{{ 
    69 #!python 
    70 import pjsua 
    71  
    72 try: 
    73     call = acc.make_call('sip:buddy@example.org') 
    74 except pjsua.Error, err: 
    75     print 'Exception has occured:', err 
    76 except: 
    77     print 'Ouch..' 
    78  }}} 
    79  
    80 The sample above will print the full error information to stdout. If you prefer to display the error in more structured manner, the [http://www.pjsip.org/python/pjsua.htm#Error pjsua.Error] class has several members to explain the error, such as the object name that raised the error, the operation name, and the error message itself. 
    81  
    82  
    83  
    84  
    85 == Lib Class == 
    86  
    87 The [http://www.pjsip.org/python/pjsua.htm#Lib Lib] class provides the base API's to communicate with PJSUA-API and to create objects (such as [http://www.pjsip.org/python/pjsua.htm#Account Account] and [http://www.pjsip.org/python/pjsua.htm#Transport Transport]). 
    88  
    89 [[BR]] 
    90  
    91 ==== Initializing the Library ==== 
    92  
    93 Instantiate the library: 
    94  
    95  {{{ 
    96 #!python 
    97  
    98 import pjsua as pj 
    99  
    100 lib = pj.Lib() 
    101  
    102  }}} 
    103  
    104 then initialize and start the library.  
    105  
    106  {{{ 
    107 #!python 
    108  
    109 try: 
    110     lib.init() 
    111     lib.start() 
    112  
    113 except pj.Error, e: 
    114     print "Error initializing library:", e 
    115  }}} 
    116  
    117 Both the {{{init()}}} and {{{start()}}} methods above may be given additional parameters. Please see [http://www.pjsip.org/python/pjsua.htm#Lib Lib] class reference manual for more information. 
    118  
    119 [[BR]] 
    120  
    121 == Transport == 
    122  
    123 Application needs to create one or more [http://www.pjsip.org/python/pjsua.htm#Transport Transport] objects before it can send or receive SIP messages: 
    124  
    125  {{{ 
    126 #!python 
    127  
    128 try: 
    129     udp = lib.create_transport(pj.TransportType.UDP) 
    130  
    131 except pj.Error, e: 
    132     print "Error creating transport:", e 
    133  }}} 
    134  
    135 [[BR]] 
    136  
    137 == Accounts == 
    138  
    139 Application must create at least one [http://www.pjsip.org/python/pjsua.htm#Account Account] before it can send and receive SIP messages. An account specifies the '''From:''' URI, so it's needed before you can send SIP messages. 
    140  
    141 There are two types of accounts in pjsua: 
    142  * real account: this is an account that can register to a SIP server 
    143  * transport account: this corresponds to one [http://www.pjsip.org/python/pjsua.htm#Transport Transport]. So for example if we have created UDP transport which listens to {{{192.168.0.1:5080}}}, the transport account will have URI: "{{{sip:192.168.0.1:5080}}}" (rather than, say, "{{{sip:user@domain}}}"). 
    144  
    145 There can be more than one accounts in an application. 
    146  
    147 [[BR]] 
    148  
    149 ==== Creating Accounts ==== 
    150  
    151 To create transport account: 
    152  
    153  {{{ 
    154 #!python 
    155  
    156 try: 
    157     acc = lib.create_account_for_transport(udp) 
    158  
    159 except pj.Error, e: 
    160     print "Error creating UDP local account:", e 
    161  }}} 
    162  
    163 To create a real account account, first you must configure an [http://www.pjsip.org/python/pjsua.htm#AccountConfig AccountConfig], then create the account: 
    164  
    165  {{{ 
    166 #!python 
    167  
    168 try: 
    169     acc_cfg = pj.AccountConfig() 
    170     acc_cfg.id = "sip:user@pjsip.org" 
    171     acc_cfg.reg_uri = "sip:pjsip.org" 
    172     acc_cfg.proxy = ["<sip:pjsip.org;lr>"] 
    173     acc_cfg.auth_cred = [pj.AuthCred("*", "user", "password")] 
    174  
    175     acc = lib.create_account(acc_cfg, True) 
    176  
    177 except pj.Error, e: 
    178     print "Error creating account:", e 
    179  }}} 
    180  
    181 Alternatively, for typical account config like above, we can do like this: 
    182  
    183  {{{ 
    184 #!python 
    185  
    186 try: 
    187     acc = lib.create_account(pj.AccountConfig("pjsip.org", "username", "password"), True) 
    188  
    189 except pj.Error, e: 
    190     print "Error creating account:", e 
    191  }}} 
    192  
    193 [[BR]] 
    194  
    195 ==== Getting Events from Account ==== 
    196  
    197 [http://www.pjsip.org/python/pjsua.htm#Account Account] object emits events such as incoming call and registration state.  
    198  
    199 To capture events from [http://www.pjsip.org/python/pjsua.htm#Account Account], first you need to derive your account callback class from [http://www.pjsip.org/python/pjsua.htm#AccountCallback AccountCallback] class and implement the relevant callback methods: 
    200  
    201  {{{ 
    202 #!python 
    203  
    204 class MyAccountCallback(pj.AccountCallback): 
    205     def __init__(self, account): 
    206         pj.AccountCallback.__init__(self, account) 
    207  
    208     def on_reg_state(self): 
    209         print "Account", self.account.info().uri, 
    210         print "registration status is", self.account.info().reg_reason 
    211  
    212     def on_incoming_call(self, call): 
    213         print "Incoming call from", call.info().remote_uri 
    214         call.answer(200) 
    215  }}} 
    216  
    217 (Note: we've touched the [http://www.pjsip.org/python/pjsua.htm#Call Call] object a little bit above, that will be explained later). 
    218  
    219 Then install the callback to [http://www.pjsip.org/python/pjsua.htm#Account Account] object: 
    220  
    221  {{{ 
    222 #!python 
    223  
    224    acc_cb = MyAccountCallback(acc) 
    225    acc.set_callback(acc_cb) 
    226  }}} 
    227  
    228 [[BR]] 
    229  
    230 ==== Account Sample Application ==== 
    231  
    232 For a complete account sample application (including registration), please see source:pjproject/trunk/pjsip-apps/src/python/samples/registration.py 
    233  
    234  
    235 [[BR]] 
    236  
    237 == Calls == 
    238  
    239 ==== Creating Calls ==== 
    240  
    241 Incoming call events are reported via [http://www.pjsip.org/python/pjsua.htm#AccountCallback AccountCallback]'s {{{on_incoming_call()}}} callback as shown above. 
    242  
    243 To make outgoing call: 
    244  
    245  {{{ 
    246 #!python 
    247  
    248     try: 
    249         call = acc.make_call("sip:buddy@pjsip.org") 
    250  
    251     except pj.Error, e: 
    252         print "Error in making call:", e 
    253  }}} 
    254  
    255 Note that as with all PJSIP operations, the {{{make_call()}}} function is asynchronous; it will not block until the call is connected, but rather it will return immediately as soon as the initial INVITE request is sent. Application is then informed about the call completion via [http://www.pjsip.org/python/pjsua.htm#CallCallback CallCallback] object (see below). 
    256  
    257 [[BR]] 
    258  
    259 ==== Getting Events from Call ==== 
    260  
    261 To retrieve events from a call, derive a class from [http://www.pjsip.org/python/pjsua.htm#CallCallback CallCallback] class and implement the methods that you want to be notified about. Normally at the very least you'd want to implement {{{on_state()}}} and {{{on_media_state()}}} methods: 
    262  
    263  {{{ 
    264 #!python 
    265  
    266 class MyCallCallback(pj.CallCallback): 
    267     def __init__(self, call): 
    268         pj.CallCallback.__init__(self, call) 
    269  
    270     def on_state(self): 
    271         print "Call with", self.call.info().remote_uri, 
    272         print "is", self.call.info().state_text 
    273  
    274     def on_media_state(self): 
    275         if self.call.info().media_state == pj.MediaState.ACTIVE: 
    276             # Connect the call to sound device 
    277  
    278             call_slot = self.call.info().conf_slot 
    279             pj.Lib.instance().conf_connect(call_slot, 0) 
    280             pj.Lib.instance().conf_connect(0, call_slot) 
    281             print "Media is now active" 
    282         else: 
    283             print "Media is inactive" 
    284  
    285  }}} 
    286  
    287 Then install your callback to the call object: 
    288  
    289  {{{ 
    290 #!python 
    291  
    292   call_cb = MyCallCallback(call) 
    293   call.set_callback(call_cb) 
    294  }}} 
    295  
    296 [[BR]] 
    297  
    298 ==== Call Sample Application ==== 
    299  
    300 For a complete call sample application, please see source:pjproject/trunk/pjsip-apps/src/python/samples/call.py 
    301  
    302  
    303 [[BR]] 
    304  
    305 == Presence and Instant Messaging == 
    306  
    307 (The doc is TBD) 
    308  
    309 An [http://www.pjsip.org/python/pjsua.htm#Account Account] has a presence status associated with it, and when the presence status is changed (with {{{set_basic_status()}}} or {{{set_presence_status()}}}), the changes will be propagated to presence subscriber with using either PUBLISH or NOTIFY SIP methods. 
    310  
    311 To subscribe to buddy's presence status, application creates [http://www.pjsip.org/python/pjsua.htm#Buddy Buddy] object using account's {{{add_buddy()}}} method. Changes in buddy's presence status will be reported via [http://www.pjsip.org/python/pjsua.htm#BuddyCallback BuddyCallback] class, which must be derived and then installed to the Buddy object. 
    312  
    313 For a complete presence and instant messaging sample application, please see source:pjproject/trunk/pjsip-apps/src/python/samples/presence.py 
    314  
    315  
    316 [[BR]] 
    317  
    318 == Working with Media == 
    319  
    320 The [http://www.pjsip.org/python/pjsua.htm#Lib Lib] class provides API to manage media, such as: 
    321  * create WAV file player or recorder 
    322  * manage conference bridge connections 
    323  * manage codecs 
    324  * etc. 
    325  
    326  
    327  
    328 [[BR]] 
    329  
    330 = Reference Documentation = 
    331  
    332 Please see [http://www.pjsip.org/python/pjsua.htm pjsua] Python module documentation for reference. 
    333