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            }