    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] DEPRECATED, use last_leavereason instead, 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                    /** [OTHERS] last reason for leaving conversation or live session.                   provides an enum alternative to last_voice_error as well                   as the reason this participant RETIRED, if so, type: LEAVE_REASON */
    099                    last_leavereason(955);
    100
    101                    private static final Map<Integer,PROPERTY> lookup = new HashMap<Integer,PROPERTY>();
    102
    103                    static {
    104                            for(PROPERTY s : EnumSet.allOf(PROPERTY.class))
    105                                    lookup.put(s.getId(), s);
    106                    }
    107
    108                    private final int id;
    109
    110                    private PROPERTY(int value) {
    111                            this.id = value;
    112                    }
    113
    114                    public int getId() { return id; }
    115
    116                    public static PROPERTY get(int code) {
    117                            return lookup.get(code);
    118                    }
    119
    120                    public static PROPERTY fromString(String s) {
    121                            for (PROPERTY p : lookup.values()) {
    122                                    if (p.toString() == s) {
    123                                            return p;
    124                                    }
    125                            }
    126                            return null;
    127                    }
    128            }
    129
    130            public Object GetPropertyAsEnum(int propid) {
    131                    return PROPERTY.get(propid);
    132            }
    133
    134            public String GetStrProperty(PROPERTY prop) {
    135                    //check in propcache if so then return
    136                    if (mPropCache.containsKey(new Integer(prop.id))){
    137                            String value =  (String)mPropCache.get(prop.id);
    138                            if (value != null && !(value.length() == 0) ){
    139                                    return value;
    140                            }
    141                    }
    142                    //else get from skypekit...
    143                    GetPropertyRequest request = new GetPropertyRequest(19, mObjectId, prop.id);
    144
    145                    String string = null;
    146                    GetPropertyResponse r = skype.GetProperty(request);
    147                    if (r != null){
    148                            string = r.GetAsString();
    149                    }
    150
    151                    if (string != null)
    152                    {
    153                            mPropCache.put(new Integer(prop.id), string);
    154                    }
    155                    return string;
    156            }
    157
    158            public int GetIntProperty(PROPERTY prop) {
    159                    //check in propcache if so then return
    160                    if (mPropCache.containsKey(new Integer(prop.id))){
    161                            int value = ((Integer)mPropCache.get(prop.id)).intValue();
    162                            if (value != 0){
    163                                    return value;
    164                            }
    165                    }
    166                    //else get from skypekit...
    167                    GetPropertyRequest request = new GetPropertyRequest(moduleID(), mObjectId, prop.id);
    168
    169                    Integer integer = null;
    170                    GetPropertyResponse r = skype.GetProperty(request);
    171                    if (r != null){
    172                            integer  = r.GetAsInt();
    173                    }
    174
    175                    if (integer != null)
    176                    {
    177                            mPropCache.put(new Integer(prop.id), integer);
    178                            return integer.intValue();
    179                    }
    180                    else
    181                    {
    182                            return 0;
    183                    }
    184            }
    185
    186            public boolean GetBooleanProperty(PROPERTY prop) {
    187                    //check in propcache if so then return
    188                    if (mPropCache.containsKey(new Integer(prop.id))){
    189                            return ((Boolean)mPropCache.get(prop.id)).booleanValue();
    190                    }
    191                    //else get from skypekit...
    192                    GetPropertyRequest request = new GetPropertyRequest(moduleID(), mObjectId, prop.id);
    193
    194                    Boolean boolResp = null;
    195                    GetPropertyResponse r = skype.GetProperty(request);
    196                    if (r != null){
    197                            boolResp  = r.GetAsBoolean();
    198                    }
    199
    200                    if (boolResp != null)
    201                    {
    202                            mPropCache.put(new Integer(prop.id), boolResp);
    203                            return boolResp.booleanValue();
    204                    }
    205                    else
    206                    {
    207                            return false;
    208                    }
    209            }
    210
    211            public byte [] GetBinProperty(PROPERTY prop) {
    212                    //get from skypekit...
    213                    GetPropertyRequest request = new GetPropertyRequest(19, mObjectId, prop.id);
    214
    215                    byte [] data = null;
    216                    GetPropertyResponse r = skype.GetProperty(request);
    217                    if (r != null) {
    218                            data = r.GetAsBinary();
    219                    }
    220                    return data;
    221            }
    222
    223            /**default array of Participant Properties that get fetched & cached upon class construction*/
    224            private static PROPERTY [] defaultProperties = { PROPERTY.convo_id, PROPERTY.rank, PROPERTY.identity, PROPERTY.adder};
    225
    226            private void GetDefaultProps() {
    227                    MultiGetPropertyRequest request = null;
    228                    ArrayList<Integer> proparray = null;
    229                            /**Add the single oid into array*/
    230                            ArrayList<Integer> oidarray=new ArrayList<Integer>();
    231                            oidarray.add(mObjectId);
    232
    233                            /**Add all requested propids into array*/
    234                            proparray=new ArrayList<Integer>();
    235                            for (PROPERTY defaultProp : defaultProperties) {
    236                                    proparray.add(defaultProp.getId());
    237                            }
    238                            /**Generate the request*/
    239                            request = new MultiGetPropertyRequest(moduleID(), oidarray,proparray);
    240
    241                            /** Make Multi Get call*/
    242                            GetPropertyResponse r=skype.MultiGetProperty(request);
    243                            /**Verify that it is a proper multiresponse*/
    244                            if(!r.isMultiresponse())
    245                            {
    246                                    return;
    247                            }
    248                            /**update property cache with results*/
    249                            mPropCache.putAll(r.GetAsMap(mObjectId, proparray));
    250                    }
    251
    252                    /**
    253                    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> */
    254                    public enum RANK {
    255
    256                            /** Creator of the chat. There can be only one participant with this type per conversation. Other participants cannot be promoted to Creator rank. <br>*/
    257                            CREATOR(1),
    258
    259                            /** Participant who has administrator privileges <br>*/
    260                            ADMIN(2),
    261
    262                            /** Participant who can speak and write <br>*/
    263                            SPEAKER(3),
    264
    265                            /** Participant who can write but not speak <br>*/
    266                            WRITER(4),
    267
    268                            /** Participant who can read but not write/speak <br>*/
    269                            SPECTATOR(5),
    270
    271                            /** Participant who is applying to join the conversation. Member cannot be demoted to applicants once they have been accepted.  <br>*/
    272                            APPLICANT(6),
    273
    274                            /** Participant who has eft or has been kicked from the conversation <br>*/
    275                            RETIRED(7),
    276
    277                            /** Participant who has been banned from the chat <br>*/
    278                            OUTLAW(8);
    279
    280                            private static final Map<Integer,RANK> lookup = new HashMap<Integer,RANK>();
    281
    282                            static {
    283                                    for(RANK s : EnumSet.allOf(RANK.class))
    284                                            lookup.put(s.getId(), s);
    285                            }
    286
    287                            private final int id;
    288
    289                            private RANK(int value) {
    290                                    this.id = value;
    291                            }
    292
    293                            public int getId() { return id; }
    294
    295                            public static RANK get(int code) {
    296                                    return lookup.get(code);
    297                            }
    298
    299                            public static RANK fromString(String s) {
    300                                    for (RANK p : lookup.values()) {
    301                                            if (p.toString() == s) {
    302                                                    return p;
    303                                            }
    304                                    }
    305                                    return null;
    306                            }
    307                    }
    308
    309                    /**
    310                    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> */
    311                    public enum TEXT_STATUS {
    312
    313                            /** Fallback state in case the text status is not (yet) deternmined. <br>*/
    314                            TEXT_UNKNOWN(0),
    315
    316                            /** 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>*/
    317                            TEXT_NA(1),
    318
    319                            /** Participant is currently not typing. <br>*/
    320                            READING(2),
    321
    322                            /** Participant is currently typing. <br>*/
    323                            WRITING(3),
    324
    325                            /** 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>*/
    326                            WRITING_AS_ANGRY(4),
    327
    328                            /** 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>*/
    329                            WRITING_AS_CAT(5);
    330
    331                            private static final Map<Integer,TEXT_STATUS> lookup = new HashMap<Integer,TEXT_STATUS>();
    332
    333                            static {
    334                                    for(TEXT_STATUS s : EnumSet.allOf(TEXT_STATUS.class))
    335                                            lookup.put(s.getId(), s);
    336                            }
    337
    338                            private final int id;
    339
    340                            private TEXT_STATUS(int value) {
    341                                    this.id = value;
    342                            }
    343
    344                            public int getId() { return id; }
    345
    346                            public static TEXT_STATUS get(int code) {
    347                                    return lookup.get(code);
    348                            }
    349
    350                            public static TEXT_STATUS fromString(String s) {
    351                                    for (TEXT_STATUS p : lookup.values()) {
    352                                            if (p.toString() == s) {
    353                                                    return p;
    354                                            }
    355                                    }
    356                                    return null;
    357                            }
    358                    }
    359
    360                    /**
    361                    Recognized values for the P_VOICE_STATUS property.  <br> */
    362                    public enum VOICE_STATUS {
    363
    364                            /** Participant voice status is not (yet) determined. <br>*/
    365                            VOICE_UNKNOWN(0),
    366
    367                            /** Participant is using a Skype client with no audio capability. <br>*/
    368                            VOICE_NA(1),
    369
    370                            /** Participant is using a Skype client that supports audio. <br>*/
    371                            VOICE_AVAILABLE(2),
    372
    373                            /** Participant is in process of joining current live session. This is a transitional state. <br>*/
    374                            VOICE_CONNECTING(3),
    375
    376                            /** Participant has been invited to join the live session but has not yet accepted. <br>*/
    377                            RINGING(4),
    378
    379                            /** Participant is in process of joining current live session. This is another transitional state. <br>*/
    380                            EARLY_MEDIA(5),
    381
    382                            /** Participant has joined the current live session but is currently not transmitting audio. <br>*/
    383                            LISTENING(6),
    384
    385                            /** 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>*/
    386                            SPEAKING(7),
    387
    388                            /** Participant has joined the current live session but the audio is currently on hold. <br>*/
    389                            VOICE_ON_HOLD(8),
    390
    391                            /** Participant will be placed in this state for some seconds after live session has finished. This is another transitional state. <br>*/
    392                            VOICE_STOPPED(9);
    393
    394                            private static final Map<Integer,VOICE_STATUS> lookup = new HashMap<Integer,VOICE_STATUS>();
    395
    396                            static {
    397                                    for(VOICE_STATUS s : EnumSet.allOf(VOICE_STATUS.class))
    398                                            lookup.put(s.getId(), s);
    399                            }
    400
    401                            private final int id;
    402
    403                            private VOICE_STATUS(int value) {
    404                                    this.id = value;
    405                            }
    406
    407                            public int getId() { return id; }
    408
    409                            public static VOICE_STATUS get(int code) {
    410                                    return lookup.get(code);
    411                            }
    412
    413                            public static VOICE_STATUS fromString(String s) {
    414                                    for (VOICE_STATUS p : lookup.values()) {
    415                                            if (p.toString() == s) {
    416                                                    return p;
    417                                            }
    418                                    }
    419                                    return null;
    420                            }
    421                    }
    422
    423                    /**
    424                    Recognized values for the P_VIDEO_STATUS property. This property applies to Participant's video send capability, not capability to receive video. <br> */
    425                    public enum VIDEO_STATUS {
    426
    427                            /** Video status is not (yet) determined. <br>*/
    428                            VIDEO_UNKNOWN(0),
    429
    430                            /** Indicates that this Participant does not have video available.. <br>*/
    431                            VIDEO_NA(1),
    432
    433                            /** 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>*/
    434                            VIDEO_AVAILABLE(2),
    435
    436                            /** Transitional state indicating that the Participant is attempting to initiate video send. <br>*/
    437                            VIDEO_CONNECTING(3),
    438
    439                            /** Indicates that the participant is currently sending video. <br>*/
    440                            STREAMING(4),
    441
    442                            /** Indicates that the participant video send is currently paused. <br>*/
    443                            VIDEO_ON_HOLD(5);
    444
    445                            private static final Map<Integer,VIDEO_STATUS> lookup = new HashMap<Integer,VIDEO_STATUS>();
    446
    447                            static {
    448                                    for(VIDEO_STATUS s : EnumSet.allOf(VIDEO_STATUS.class))
    449                                            lookup.put(s.getId(), s);
    450                            }
    451
    452                            private final int id;
    453
    454                            private VIDEO_STATUS(int value) {
    455                                    this.id = value;
    456                            }
    457
    458                            public int getId() { return id; }
    459
    460                            public static VIDEO_STATUS get(int code) {
    461                                    return lookup.get(code);
    462                            }
    463
    464                            public static VIDEO_STATUS fromString(String s) {
    465                                    for (VIDEO_STATUS p : lookup.values()) {
    466                                            if (p.toString() == s) {
    467                                                    return p;
    468                                            }
    469                                    }
    470                                    return null;
    471                            }
    472                    }
    473
    474                    /**
    475                     */
    476                    public enum DTMF {
    477
    478                            /** */
    479                            DTMF_0(0),
    480
    481                            /** */
    482                            DTMF_1(1),
    483
    484                            /** */
    485                            DTMF_2(2),
    486
    487                            /** */
    488                            DTMF_3(3),
    489
    490                            /** */
    491                            DTMF_4(4),
    492
    493                            /** */
    494                            DTMF_5(5),
    495
    496                            /** */
    497                            DTMF_6(6),
    498
    499                            /** */
    500                            DTMF_7(7),
    501
    502                            /** */
    503                            DTMF_8(8),
    504
    505                            /** */
    506                            DTMF_9(9),
    507
    508                            /** */
    509                            DTMF_STAR(10),
    510
    511                            /** */
    512                            DTMF_POUND(11);
    513
    514                            private static final Map<Integer,DTMF> lookup = new HashMap<Integer,DTMF>();
    515
    516                            static {
    517                                    for(DTMF s : EnumSet.allOf(DTMF.class))
    518                                            lookup.put(s.getId(), s);
    519                            }
    520
    521                            private final int id;
    522
    523                            private DTMF(int value) {
    524                                    this.id = value;
    525                            }
    526
    527                            public int getId() { return id; }
    528
    529                            public static DTMF get(int code) {
    530                                    return lookup.get(code);
    531                            }
    532
    533                            public static DTMF fromString(String s) {
    534                                    for (DTMF p : lookup.values()) {
    535                                            if (p.toString() == s) {
    536                                                    return p;
    537                                            }
    538                                    }
    539                                    return null;
    540                            }
    541                    }
    542
    543                    /**
    544                     *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>
    545                     * @param rank Participant.RANK value to check for. <br>
    546                     * @return result Returns true if local user can set participant's rank to the value given in rank argument. <br>
    547                     */
    548                    public boolean CanSetRankTo( RANK rank) {
    549
    550                            Request request = null;
    551                            try {
    552                                    request = new XCallRequest(19,1);
    553                            } catch (IOException e) {
    554                                    e.printStackTrace();
    555                                    if (skype.errorListener != null)
    556                                            skype.errorListener.OnSkypeKitFatalError();
    557                            }
    558                            request.addParm('O',0,mObjectId);
    559                            request.addParm('e',1,rank.getId());
    560
    561                            Response r = skype.XCall((XCallRequest)request);
    562
    563                            if (r.isErrCall())
    564                                    return false;
    565
    566                            boolean result = false;
    567                            result = r.GetAsBoolean(1);
    568                            return result;
    569                    }
    570
    571                    /**
    572                     *Sets Participant's conversation privileges to the given RANK <br>
    573                     * @param rank Target Participant.RANK value. <br>
    574                     */
    575                    public void SetRankTo( RANK rank) {
    576
    577                            Request request = null;
    578                            try {
    579                                    request = new XCallRequest(19,2);
    580                            } catch (IOException e) {
    581                                    e.printStackTrace();
    582                                    if (skype.errorListener != null)
    583                                            skype.errorListener.OnSkypeKitFatalError();
    584                            }
    585                            request.addParm('O',0,mObjectId);
    586                            request.addParm('e',1,rank.getId());
    587
    588                            skype.XCall((XCallRequest)request);
    589                    }
    590
    591                    /**
    592                     *Initiates live conversation attempt with Participant. <br>
    593                     * @param identityToUse Ring an alternate identity, such as a PSTN number. <br>
    594                     * @param videoCall Enable video. <br>
    595                     * @param nrofRedials Unused. <br>
    596                     * @param redialPeriod Unused. <br>
    597                     * @param autoStartVM Unused. On dialog, if falling on VM, greeting and recording will be automatically started. <br>
    598                     * @param origin When call is initiated from web link, must contain the URI that was used
    599                     */
    600                    public void Ring( String identityToUse, boolean videoCall, int nrofRedials, int redialPeriod, boolean autoStartVM, String origin) {
    601
    602                            Request request = null;
    603                            try {
    604                                    request = new XCallRequest(19,3);
    605                            } catch (IOException e) {
    606                                    e.printStackTrace();
    607                                    if (skype.errorListener != null)
    608                                            skype.errorListener.OnSkypeKitFatalError();
    609                            }
    610                            request.addParm('O',0,mObjectId);
    611                            request.addParm('S',1,identityToUse);
    612                            request.addParm('b',2,videoCall);
    613                            request.addParm('u',3,nrofRedials);
    614                            request.addParm('u',4,redialPeriod);
    615                            request.addParm('b',5,autoStartVM);
    616                            request.addParm('S',6,origin);
    617
    618                            skype.XCall((XCallRequest)request);
    619                    }
    620
    621                    /**
    622                     *Rings this participant, using P_LIVE_IDENTITY property if set. <br>
    623                     */
    624                    public void RingIt() {
    625
    626                            Request request = null;
    627                            try {
    628                                    request = new XCallRequest(19,8);
    629                            } catch (IOException e) {
    630                                    e.printStackTrace();
    631                                    if (skype.errorListener != null)
    632                                            skype.errorListener.OnSkypeKitFatalError();
    633                            }
    634                            request.addParm('O',0,mObjectId);
    635
    636                            skype.XCall((XCallRequest)request);
    637                    }
    638
    639                    /**
    640                     *Sets LIVE_IDENTITY property, an alternate identity to use when ringing, such as a PSTN. <br>
    641                     * @param identityToUse Empty string will reset it to default, i.e IDENTITY property value <br>
    642                     */
    643                    public void SetLiveIdentityToUse( String identityToUse) {
    644
    645                            Request request = null;
    646                            try {
    647                                    request = new XCallRequest(19,7);
    648                            } catch (IOException e) {
    649                                    e.printStackTrace();
    650                                    if (skype.errorListener != null)
    651                                            skype.errorListener.OnSkypeKitFatalError();
    652                            }
    653                            request.addParm('O',0,mObjectId);
    654                            request.addParm('S',1,identityToUse);
    655
    656                            skype.XCall((XCallRequest)request);
    657                    }
    658
    659                    /**
    660                     *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>
    661                     * @return video Returns reference to a constructed video object. <br>
    662                     */
    663                    public Video GetVideo() {
    664
    665                            Request request = null;
    666                            try {
    667                                    request = new XCallRequest(19,4);
    668                            } catch (IOException e) {
    669                                    e.printStackTrace();
    670                                    if (skype.errorListener != null)
    671                                            skype.errorListener.OnSkypeKitFatalError();
    672                            }
    673                            request.addParm('O',0,mObjectId);
    674
    675                            Response r = skype.XCall((XCallRequest)request);
    676
    677                            if (r.isErrCall())
    678                                    return null;
    679
    680                            int oid = 0;
    681                            Video video = null;
    682                            oid = r.GetOid(1);
    683                            if (oid != AbstractDecoder.NULL_VALUE) {
    684                                    video = (Video)skype.factory(Video.moduleID(), oid, skype);
    685                            }
    686                            return video;
    687                    }
    688
    689                    /**
    690                     *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>
    691                     */
    692                    public void Hangup() {
    693
    694                            Request request = null;
    695                            try {
    696                                    request = new XCallRequest(19,5);
    697                            } catch (IOException e) {
    698                                    e.printStackTrace();
    699                                    if (skype.errorListener != null)
    700                                            skype.errorListener.OnSkypeKitFatalError();
    701                            }
    702                            request.addParm('O',0,mObjectId);
    703
    704                            skype.XCall((XCallRequest)request);
    705                    }
    706
    707                    /**
    708                     *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>
    709                     */
    710                    public void Retire() {
    711
    712                            Request request = null;
    713                            try {
    714                                    request = new XCallRequest(19,6);
    715                            } catch (IOException e) {
    716                                    e.printStackTrace();
    717                                    if (skype.errorListener != null)
    718                                            skype.errorListener.OnSkypeKitFatalError();
    719                            }
    720                            request.addParm('O',0,mObjectId);
    721
    722                            skype.XCall((XCallRequest)request);
    723                    }
    724
    725
    726            }