    001    package com.skype.api;
    002
    003    import java.io.IOException;
    004    import java.util.*;
    005    import com.skype.ipc.*;
    006    /**
    007     * Conversation participant class. Instances of this class represent contacts when in the context of conversations. Amongst others, this class has a Ring method for requesting live status with the target contact. This class also holds typing indicator property and access rights for the contact in context of public conversations. <br>
    008     */
    009
    010
    011    public class Participant extends SkypeObject {
    012
    013
    014            public interface ParticipantListener {
    015                    /** This event gets called when there are changes to Participant properties defined in Participant.PROPERTY  */
    016                    public void OnPropertyChange(SkypeObject obj, PROPERTY prop, Object value);
    017
    018                    /**This event gets fired on receiving a DTMF signal sent by Participant. Note that this event will only fire if the Participant is also using a Skype client. Skype audio library does not monitor incoming voice streams for dial tones. DTMF events are propagated to remote participants via data channel. Incoming DTMF tones transmitted from, for example, mobile phones, will not cause this event to fire. In case of incoming DTMF signals from Skype clients, DTMF tones are also inserted into the audio stream. You don't have to inject those into local audio playback yourself. <br>*/
    019                    public void OnIncomingDTMF(SkypeObject obj, DTMF dtmf);
    020
    021            }
    022
    023            public Participant(int oid, Skype skype) {
    024                    super(oid,skype);
    025                    /**get default properties for this module **/
    026                    GetDefaultProps();
    027            }
    028
    029            private static final int MODULE_ID = 19;
    030
    031            public static final int moduleID() {
    032                    return MODULE_ID;
    033            }
    034
    035            /** Properties of the Participant class */
    036            public enum PROPERTY {
    037
    038                    /** [ALL] ID of corresponding conversation. Here and below, [ALL] tag indicates that the property has meaning and is set in context of all participants in the conversation. [OTHERS] tag has meaning only for participants who are not the local user. <br>, type: Conversation */
    039                    convo_id(930),
    040
    041                    /** [ALL] skypename OR pstn_number OR namespace:identity, type: String */
    042                    identity(931),
    043
    044                    /** [ALL] Participant.RANK, type: RANK */
    045                    rank(932),
    046
    047                    /** Not set (should be: requested Participant.RANK, higher than the current one), type: RANK */
    048                    requested_rank(933),
    049
    050                    /** [ALL] the typing indicator, type: TEXT_STATUS */
    051                    text_status(934),
    052
    053                    /** [ALL] voice status, type: VOICE_STATUS */
    054                    voice_status(935),
    055
    056                    /** [ALL] video status, type: VIDEO_STATUS */
    057                    video_status(936),
    058
    059                    /** [ALL] identity that was used to establish current live session with that participant (can be different from participant identity), type: String */
    060                    live_identity(943),
    061
    062                    /** [OTHERS] 'price_per_minute_float currency' - eg '0.01 EUR'. Note that this property obtains value only after the participant goes into live state. It cannot be used to display call rates before the call starts. <br>, type: String */
    063                    live_price_for_me(938),
    064
    065                    /** [OTHERS] list of identities where the live session is being forwarded (if they are disclosed), space separated, type: String */
    066                    live_fwd_identities(948),
    067
    068                    /** [ALL] time of joining the live session, type: int */
    069                    live_start_timestamp(939),
    070
    071                    /** [ALL] current 'loudness' level when SPEAKING (0..10), type: int */
    072                    sound_level(941),
    073
    074                    /** [OTHERS] call (audio and video) debug info, type: String */
    075                    debuginfo(942),
    076
    077                    /** [OTHERS], type: String */
    078                    last_voice_error(947),
    079
    080                    /** [ALL] space separated tokens values: CPU_INUSE CPU_SLOW CPU_HIGH HIGH_ECHO HIGH_NOISE MUTED_INPUT LOW_INPUT MUTED_INPUT_ACTIVITY FW_STRONG FW_BAD NOT_UDP CALL_BW_LOW RECORD_ERROR + values in video debug info, type: String */
    081                    quality_problems(949),
    082
    083                    /** [ALL] participant type during livesession as specified in IDENTITYTYPE, type: contact.IDENTITYTYPE */
    084                    live_type(950),
    085
    086                    /** [OTHERS] participant livesession country code - used for emergency calls only atm, type: String */
    087                    live_country(951),
    088
    089                    /** [OTHERS] Transferor identity (transferee side) <br>, type: String */
    090                    transferred_by(952),
    091
    092                    /** [OTHERS] Identity of recipient of transfer (transferor side, caller side) <br>, type: String */
    093                    transferred_to(953),
    094
    095                    /** [ALL] Identity of the user who added this participant to the conversation, type: Sid.String  <br>, type: String */
    096                    adder(954);
    097
    098                    private static final Map<Integer,PROPERTY> lookup = new HashMap<Integer,PROPERTY>();
    099
    100                    static {
    101                            for(PROPERTY s : EnumSet.allOf(PROPERTY.class))
    102                                    lookup.put(s.getId(), s);
    103                    }
    104
    105                    private final int id;
    106
    107                    private PROPERTY(int value) {
    108                            this.id = value;
    109                    }
    110
    111                    public int getId() { return id; }
    112
    113                    public static PROPERTY get(int code) {
    114                            return lookup.get(code);
    115                    }
    116
    117                    public static PROPERTY fromString(String s) {
    118                            for (PROPERTY p : lookup.values()) {
    119                                    if (p.toString() == s) {
    120                                            return p;
    121                                    }
    122                            }
    123                            return null;
    124                    }
    125            }
    126
    127            public Object GetPropertyAsEnum(int propid) {
    128                    return PROPERTY.get(propid);
    129            }
    130
    131            public String GetStrProperty(PROPERTY prop) {
    132                    //check in propcache if so then return
    133                    if (mPropCache.containsKey(new Integer(prop.id))){
    134                            String value =  (String)mPropCache.get(prop.id);
    135                            if (value != null && !(value.length() == 0) ){
    136                                    return value;
    137                            }
    138                    }
    139                    //else get from skypekit...
    140                    GetPropertyRequest request = new GetPropertyRequest(19, mObjectId, prop.id);
    141
    142                    String string = null;
    143                    GetPropertyResponse r = skype.GetProperty(request);
    144                    if (r != null){
    145                            string = r.GetAsString();
    146                    }
    147
    148                    if (string != null)
    149                    {
    150                            mPropCache.put(new Integer(prop.id), string);
    151                    }
    152                    return string;
    153            }
    154
    155            public int GetIntProperty(PROPERTY prop) {
    156                    //check in propcache if so then return
    157                    if (mPropCache.containsKey(new Integer(prop.id))){
    158                            int value = ((Integer)mPropCache.get(prop.id)).intValue();
    159                            if (value != 0){
    160                                    return value;
    161                            }
    162                    }
    163                    //else get from skypekit...
    164                    GetPropertyRequest request = new GetPropertyRequest(moduleID(), mObjectId, prop.id);
    165
    166                    Integer integer = null;
    167                    GetPropertyResponse r = skype.GetProperty(request);
    168                    if (r != null){
    169                            integer  = r.GetAsInt();
    170                    }
    171
    172                    if (integer != null)
    173                    {
    174                            mPropCache.put(new Integer(prop.id), integer);
    175                            return integer.intValue();
    176                    }
    177                    else
    178                    {
    179                            return 0;
    180                    }
    181            }
    182
    183            public boolean GetBooleanProperty(PROPERTY prop) {
    184                    //check in propcache if so then return
    185                    if (mPropCache.containsKey(new Integer(prop.id))){
    186                            return ((Boolean)mPropCache.get(prop.id)).booleanValue();
    187                    }
    188                    //else get from skypekit...
    189                    GetPropertyRequest request = new GetPropertyRequest(moduleID(), mObjectId, prop.id);
    190
    191                    Boolean boolResp = null;
    192                    GetPropertyResponse r = skype.GetProperty(request);
    193                    if (r != null){
    194                            boolResp  = r.GetAsBoolean();
    195                    }
    196
    197                    if (boolResp != null)
    198                    {
    199                            mPropCache.put(new Integer(prop.id), boolResp);
    200                            return boolResp.booleanValue();
    201                    }
    202                    else
    203                    {
    204                            return false;
    205                    }
    206            }
    207
    208            public byte [] GetBinProperty(PROPERTY prop) {
    209                    //get from skypekit...
    210                    GetPropertyRequest request = new GetPropertyRequest(19, mObjectId, prop.id);
    211
    212                    byte [] data = null;
    213                    GetPropertyResponse r = skype.GetProperty(request);
    214                    if (r != null) {
    215                            data = r.GetAsBinary();
    216                    }
    217                    return data;
    218            }
    219
    220            /**default array of Participant Properties that get fetched & cached upon class construction*/
    221            private static PROPERTY [] defaultProperties = { PROPERTY.convo_id, PROPERTY.rank, PROPERTY.identity, PROPERTY.adder};
    222
    223            private void GetDefaultProps() {
    224                    MultiGetPropertyRequest request = null;
    225                    ArrayList<Integer> proparray = null;
    226                            /**Add the single oid into array*/
    227                            ArrayList<Integer> oidarray=new ArrayList<Integer>();
    228                            oidarray.add(mObjectId);
    229
    230                            /**Add all requested propids into array*/
    231                            proparray=new ArrayList<Integer>();
    232                            for (PROPERTY defaultProp : defaultProperties) {
    233                                    proparray.add(defaultProp.getId());
    234                            }
    235                            /**Generate the request*/
    236                            request = new MultiGetPropertyRequest(moduleID(), oidarray,proparray);
    237
    238                            /** Make Multi Get call*/
    239                            GetPropertyResponse r=skype.MultiGetProperty(request);
    240                            /**Verify that it is a proper multiresponse*/
    241                            if(!r.isMultiresponse())
    242                            {
    243                                    return;
    244                            }
    245                            /**update property cache with results*/
    246                            mPropCache.putAll(r.GetAsMap(mObjectId, proparray));
    247                    }
    248
    249                    /**
    250                    Recognized values for the P_RANK property. The P_RANK controls participant's privileges in the conversation. See Participant.CanSetRankTo and Participant.SetRankTo methods. <br> */
    251                    public enum RANK {
    252
    253                            /** Creator of the chat. There can be only one participant with this type per conversation. Other participants cannot be promoted to Creator rank. <br>*/
    254                            CREATOR(1),
    255
    256                            /** Participant who has administrator privileges <br>*/
    257                            ADMIN(2),
    258
    259                            /** Participant who can speak and write <br>*/
    260                            SPEAKER(3),
    261
    262                            /** Participant who can write but not speak <br>*/
    263                            WRITER(4),
    264
    265                            /** Participant who can read but not write/speak <br>*/
    266                            SPECTATOR(5),
    267
    268                            /** Participant who is applying to join the conversation. Member cannot be demoted to applicants once they have been accepted.  <br>*/
    269                            APPLICANT(6),
    270
    271                            /** Participant who has eft or has been kicked from the conversation <br>*/
    272                            RETIRED(7),
    273
    274                            /** Participant who has been banned from the chat <br>*/
    275                            OUTLAW(8);
    276
    277                            private static final Map<Integer,RANK> lookup = new HashMap<Integer,RANK>();
    278
    279                            static {
    280                                    for(RANK s : EnumSet.allOf(RANK.class))
    281                                            lookup.put(s.getId(), s);
    282                            }
    283
    284                            private final int id;
    285
    286                            private RANK(int value) {
    287                                    this.id = value;
    288                            }
    289
    290                            public int getId() { return id; }
    291
    292                            public static RANK get(int code) {
    293                                    return lookup.get(code);
    294                            }
    295
    296                            public static RANK fromString(String s) {
    297                                    for (RANK p : lookup.values()) {
    298                                            if (p.toString() == s) {
    299                                                    return p;
    300                                            }
    301                                    }
    302                                    return null;
    303                            }
    304                    }
    305
    306                    /**
    307                    Recognized values for the P_TEXT_STATUS property. The P_TEXT_STATUS property has two uses. Firstly, you can use it to implement typing indicators in your UI, to notify the local user that an incoming chat message from this Participant is imminent.  <br><br>To set the P_TEXT_STATUS value, so that remote client UIs can display the local user's typing indicator in their UI, use Conversation.SetMyTextStatusTo method. <br><br>Transmission of P_TEXT_STATUS updates to remote participants of conversations is controlled via SETUPKEY_DISABLE_CHAT_ACTIVITY_INDICATION setup key. <br><br>Secondly, the TEXT_NA value enables you to detect participants who are running clients with no chat capability. <br> */
    308                    public enum TEXT_STATUS {
    309
    310                            /** Fallback state in case the text status is not (yet) deternmined. <br>*/
    311                            TEXT_UNKNOWN(0),
    312
    313                            /** Text status is not applicable as the participant is using a Skype client that does not support chat (for example: voice-only USB phones). <br>*/
    314                            TEXT_NA(1),
    315
    316                            /** Participant is currently not typing. <br>*/
    317                            READING(2),
    318
    319                            /** Participant is currently typing. <br>*/
    320                            WRITING(3),
    321
    322                            /** This state should be set when following two conditions are true: <br> - interval between keypresses are less than 20 ms; <br> - at least one of the keys adjacent to current key are pressed down. <br>*/
    323                            WRITING_AS_ANGRY(4),
    324
    325                            /** The "Cat on keyboard detection" algorthm in Skype is implemented in the UI level, and as such is not present in the SkypeKit API. Should you wish to implement similar algorthm in your own UI, you can get the basic logic from the PawSense FAQ - http://www.bitboost.com/pawsense/pawsense-faq.html <br>*/
    326                            WRITING_AS_CAT(5);
    327
    328                            private static final Map<Integer,TEXT_STATUS> lookup = new HashMap<Integer,TEXT_STATUS>();
    329
    330                            static {
    331                                    for(TEXT_STATUS s : EnumSet.allOf(TEXT_STATUS.class))
    332                                            lookup.put(s.getId(), s);
    333                            }
    334
    335                            private final int id;
    336
    337                            private TEXT_STATUS(int value) {
    338                                    this.id = value;
    339                            }
    340
    341                            public int getId() { return id; }
    342
    343                            public static TEXT_STATUS get(int code) {
    344                                    return lookup.get(code);
    345                            }
    346
    347                            public static TEXT_STATUS fromString(String s) {
    348                                    for (TEXT_STATUS p : lookup.values()) {
    349                                            if (p.toString() == s) {
    350                                                    return p;
    351                                            }
    352                                    }
    353                                    return null;
    354                            }
    355                    }
    356
    357                    /**
    358                    Recognized values for the P_VOICE_STATUS property.  <br> */
    359                    public enum VOICE_STATUS {
    360
    361                            /** Participant voice status is not (yet) determined. <br>*/
    362                            VOICE_UNKNOWN(0),
    363
    364                            /** Participant is using a Skype client with no audio capability. <br>*/
    365                            VOICE_NA(1),
    366
    367                            /** Participant is using a Skype client that supports audio. <br>*/
    368                            VOICE_AVAILABLE(2),
    369
    370                            /** Participant is in process of joining current live session. This is a transitional state. <br>*/
    371                            VOICE_CONNECTING(3),
    372
    373                            /** Participant has been invited to join the live session but has not yet accepted. <br>*/
    374                            RINGING(4),
    375
    376                            /** Participant is in process of joining current live session. This is another transitional state. <br>*/
    377                            EARLY_MEDIA(5),
    378
    379                            /** Participant has joined the current live session but is currently not transmitting audio. <br>*/
    380                            LISTENING(6),
    381
    382                            /** Participant has joined the current live session and is transmitting audio. The UI can either use this state to display appropriate "speaking" notification, or alternatively use Participant.P_SOUND_LEVEL if you want your speaking indicator to also reflect audio volume coming from the Participant. <br>*/
    383                            SPEAKING(7),
    384
    385                            /** Participant has joined the current live session but the audio is currently on hold. <br>*/
    386                            VOICE_ON_HOLD(8),
    387
    388                            /** Participant will be placed in this state for some seconds after live session has finished. This is another transitional state. <br>*/
    389                            VOICE_STOPPED(9);
    390
    391                            private static final Map<Integer,VOICE_STATUS> lookup = new HashMap<Integer,VOICE_STATUS>();
    392
    393                            static {
    394                                    for(VOICE_STATUS s : EnumSet.allOf(VOICE_STATUS.class))
    395                                            lookup.put(s.getId(), s);
    396                            }
    397
    398                            private final int id;
    399
    400                            private VOICE_STATUS(int value) {
    401                                    this.id = value;
    402                            }
    403
    404                            public int getId() { return id; }
    405
    406                            public static VOICE_STATUS get(int code) {
    407                                    return lookup.get(code);
    408                            }
    409
    410                            public static VOICE_STATUS fromString(String s) {
    411                                    for (VOICE_STATUS p : lookup.values()) {
    412                                            if (p.toString() == s) {
    413                                                    return p;
    414                                            }
    415                                    }
    416                                    return null;
    417                            }
    418                    }
    419
    420                    /**
    421                    Recognized values for the P_VIDEO_STATUS property. This property applies to Participant's video send capability, not capability to receive video. <br> */
    422                    public enum VIDEO_STATUS {
    423
    424                            /** Video status is not (yet) determined. <br>*/
    425                            VIDEO_UNKNOWN(0),
    426
    427                            /** Indicates that this Participant does not have video available.. <br>*/
    428                            VIDEO_NA(1),
    429
    430                            /** Indicates that video is available for this participant. When the Participant.P_VIDEO_STATUS obtains this state, it is possible to retrieve the Video object, using Participant.GetVideo method. Further operations, such as starting or stopping the video send/receive will then go through the Video object. <br>*/
    431                            VIDEO_AVAILABLE(2),
    432
    433                            /** Transitional state indicating that the Participant is attempting to initiate video send. <br>*/
    434                            VIDEO_CONNECTING(3),
    435
    436                            /** Indicates that the participant is currently sending video. <br>*/
    437                            STREAMING(4),
    438
    439                            /** Indicates that the participant video send is currently paused. <br>*/
    440                            VIDEO_ON_HOLD(5);
    441
    442                            private static final Map<Integer,VIDEO_STATUS> lookup = new HashMap<Integer,VIDEO_STATUS>();
    443
    444                            static {
    445                                    for(VIDEO_STATUS s : EnumSet.allOf(VIDEO_STATUS.class))
    446                                            lookup.put(s.getId(), s);
    447                            }
    448
    449                            private final int id;
    450
    451                            private VIDEO_STATUS(int value) {
    452                                    this.id = value;
    453                            }
    454
    455                            public int getId() { return id; }
    456
    457                            public static VIDEO_STATUS get(int code) {
    458                                    return lookup.get(code);
    459                            }
    460
    461                            public static VIDEO_STATUS fromString(String s) {
    462                                    for (VIDEO_STATUS p : lookup.values()) {
    463                                            if (p.toString() == s) {
    464                                                    return p;
    465                                            }
    466                                    }
    467                                    return null;
    468                            }
    469                    }
    470
    471                    /**
    472                     */
    473                    public enum DTMF {
    474
    475                            /** */
    476                            DTMF_0(0),
    477
    478                            /** */
    479                            DTMF_1(1),
    480
    481                            /** */
    482                            DTMF_2(2),
    483
    484                            /** */
    485                            DTMF_3(3),
    486
    487                            /** */
    488                            DTMF_4(4),
    489
    490                            /** */
    491                            DTMF_5(5),
    492
    493                            /** */
    494                            DTMF_6(6),
    495
    496                            /** */
    497                            DTMF_7(7),
    498
    499                            /** */
    500                            DTMF_8(8),
    501
    502                            /** */
    503                            DTMF_9(9),
    504
    505                            /** */
    506                            DTMF_STAR(10),
    507
    508                            /** */
    509                            DTMF_POUND(11);
    510
    511                            private static final Map<Integer,DTMF> lookup = new HashMap<Integer,DTMF>();
    512
    513                            static {
    514                                    for(DTMF s : EnumSet.allOf(DTMF.class))
    515                                            lookup.put(s.getId(), s);
    516                            }
    517
    518                            private final int id;
    519
    520                            private DTMF(int value) {
    521                                    this.id = value;
    522                            }
    523
    524                            public int getId() { return id; }
    525
    526                            public static DTMF get(int code) {
    527                                    return lookup.get(code);
    528                            }
    529
    530                            public static DTMF fromString(String s) {
    531                                    for (DTMF p : lookup.values()) {
    532                                            if (p.toString() == s) {
    533                                                    return p;
    534                                            }
    535                                    }
    536                                    return null;
    537                            }
    538                    }
    539
    540                    /**
    541                     *Checks whether the current user can set this Participant's conversation privileges to the specified RANK. This enables you to gray out or disable in your UI all the unavailable options for Participant.SetRankTo method. <br>
    542                     * @param rank Participant.RANK value to check for. <br>
    543                     * @return result Returns true if local user can set participant's rank to the value given in rank argument. <br>
    544                     */
    545                    public boolean CanSetRankTo( RANK rank) {
    546
    547                            Request request = null;
    548                            try {
    549                                    request = new XCallRequest(19,1);
    550                            } catch (IOException e) {
    551                                    e.printStackTrace();
    552                                    if (skype.errorListener != null)
    553                                            skype.errorListener.OnSkypeKitFatalError();
    554                            }
    555                            request.addParm('O',0,mObjectId);
    556                            request.addParm('e',1,rank.getId());
    557
    558                            Response r = skype.XCall((XCallRequest)request);
    559
    560                            if (r.isErrCall())
    561                                    return false;
    562
    563                            boolean result = false;
    564                            result = r.GetAsBoolean(1);
    565                            return result;
    566                    }
    567
    568                    /**
    569                     *Sets Participant's conversation privileges to the given RANK <br>
    570                     * @param rank Target Participant.RANK value. <br>
    571                     */
    572                    public void SetRankTo( RANK rank) {
    573
    574                            Request request = null;
    575                            try {
    576                                    request = new XCallRequest(19,2);
    577                            } catch (IOException e) {
    578                                    e.printStackTrace();
    579                                    if (skype.errorListener != null)
    580                                            skype.errorListener.OnSkypeKitFatalError();
    581                            }
    582                            request.addParm('O',0,mObjectId);
    583                            request.addParm('e',1,rank.getId());
    584
    585                            skype.XCall((XCallRequest)request);
    586                    }
    587
    588                    /**
    589                     *Initiates live conversation attempt with Participant. <br>
    590                     * @param identityToUse Ring an alternate identity, such as a PSTN number. <br>
    591                     * @param videoCall Enable video. <br>
    592                     * @param nrofRedials Unused. <br>
    593                     * @param redialPeriod Unused. <br>
    594                     * @param autoStartVM Unused. On dialog, if falling on VM, greeting and recording will be automatically started. <br>
    595                     * @param origin When call is initiated from web link, must contain the URI that was used
    596                     */
    597                    public void Ring( String identityToUse, boolean videoCall, int nrofRedials, int redialPeriod, boolean autoStartVM, String origin) {
    598
    599                            Request request = null;
    600                            try {
    601                                    request = new XCallRequest(19,3);
    602                            } catch (IOException e) {
    603                                    e.printStackTrace();
    604                                    if (skype.errorListener != null)
    605                                            skype.errorListener.OnSkypeKitFatalError();
    606                            }
    607                            request.addParm('O',0,mObjectId);
    608                            request.addParm('S',1,identityToUse);
    609                            request.addParm('b',2,videoCall);
    610                            request.addParm('u',3,nrofRedials);
    611                            request.addParm('u',4,redialPeriod);
    612                            request.addParm('b',5,autoStartVM);
    613                            request.addParm('S',6,origin);
    614
    615                            skype.XCall((XCallRequest)request);
    616                    }
    617
    618                    /**
    619                     *Rings this participant, using P_LIVE_IDENTITY property if set. <br>
    620                     */
    621                    public void RingIt() {
    622
    623                            Request request = null;
    624                            try {
    625                                    request = new XCallRequest(19,8);
    626                            } catch (IOException e) {
    627                                    e.printStackTrace();
    628                                    if (skype.errorListener != null)
    629                                            skype.errorListener.OnSkypeKitFatalError();
    630                            }
    631                            request.addParm('O',0,mObjectId);
    632
    633                            skype.XCall((XCallRequest)request);
    634                    }
    635
    636                    /**
    637                     *Sets LIVE_IDENTITY property, an alternate identity to use when ringing, such as a PSTN. <br>
    638                     * @param identityToUse Empty string will reset it to default, i.e IDENTITY property value <br>
    639                     */
    640                    public void SetLiveIdentityToUse( String identityToUse) {
    641
    642                            Request request = null;
    643                            try {
    644                                    request = new XCallRequest(19,7);
    645                            } catch (IOException e) {
    646                                    e.printStackTrace();
    647                                    if (skype.errorListener != null)
    648                                            skype.errorListener.OnSkypeKitFatalError();
    649                            }
    650                            request.addParm('O',0,mObjectId);
    651                            request.addParm('S',1,identityToUse);
    652
    653                            skype.XCall((XCallRequest)request);
    654                    }
    655
    656                    /**
    657                     *Retrieves a reference to the Video object that corresponds to the Participant. It can be either local video - you can check if this participant's name (P_IDENTITY property) matches the name of the currently logged in account (P_SKYPENAME property) or incoming video from a remote participant.  <br><br>Note that for GetVideo to be successful, the video has to be available for that participant. This can be checked for by examining Participant VIDEO_STATUS property - once it becomes VIDEO_AVAILABLE - you can use GetVideo to obtain the Video object. <br>
    658                     * @return video Returns reference to a constructed video object. <br>
    659                     */
    660                    public Video GetVideo() {
    661
    662                            Request request = null;
    663                            try {
    664                                    request = new XCallRequest(19,4);
    665                            } catch (IOException e) {
    666                                    e.printStackTrace();
    667                                    if (skype.errorListener != null)
    668                                            skype.errorListener.OnSkypeKitFatalError();
    669                            }
    670                            request.addParm('O',0,mObjectId);
    671
    672                            Response r = skype.XCall((XCallRequest)request);
    673
    674                            if (r.isErrCall())
    675                                    return null;
    676
    677                            int oid = 0;
    678                            Video video = null;
    679                            oid = r.GetOid(1);
    680                            if (oid != AbstractDecoder.NULL_VALUE) {
    681                                    video = (Video)skype.factory(Video.moduleID(), oid, skype);
    682                            }
    683                            return video;
    684                    }
    685
    686                    /**
    687                     *Removes this participant from the current live session. Note that this does not remove the participant from conversation (for this, use Participant.Retire). It only removes participant from live state. <br>
    688                     */
    689                    public void Hangup() {
    690
    691                            Request request = null;
    692                            try {
    693                                    request = new XCallRequest(19,5);
    694                            } catch (IOException e) {
    695                                    e.printStackTrace();
    696                                    if (skype.errorListener != null)
    697                                            skype.errorListener.OnSkypeKitFatalError();
    698                            }
    699                            request.addParm('O',0,mObjectId);
    700
    701                            skype.XCall((XCallRequest)request);
    702                    }
    703
    704                    /**
    705                     *Forcibly removes this participant from conversation. This method is for removing other people from conversations (for example: as administrative punishment for flooding conversation with spam messages). For local user to leave a conversation, use Conversation.RetireFrom instead. <br>
    706                     */
    707                    public void Retire() {
    708
    709                            Request request = null;
    710                            try {
    711                                    request = new XCallRequest(19,6);
    712                            } catch (IOException e) {
    713                                    e.printStackTrace();
    714                                    if (skype.errorListener != null)
    715                                            skype.errorListener.OnSkypeKitFatalError();
    716                            }
    717                            request.addParm('O',0,mObjectId);
    718
    719                            skype.XCall((XCallRequest)request);
    720                    }
    721
    722
    723            }