001    package com.skype.api;
002    
003    import com.skype.ipc.SidRoot;
004    import com.skype.ipc.SidObject;
005    import com.skype.ipc.EnumConverting;
006    import com.skype.ipc.PropertyEnumConverting;
007    import com.skype.ipc.Decoding;
008    import com.skype.ipc.Encoding;
009    import com.skype.ipc.Encoding;
010    import java.io.IOException;
011    import com.skype.ipc.PropertyEnumConverting;
012    import com.skype.ipc.SidGetResponding;
013    
014    /**
015     * This class contains basic video control functionality for live conversations with video. Basically, Video objects represent specific Participant's video state in a live Conversation. The Video class can represent both local (outgoing) and remote (incoming) video streams. Note that as of SkypeKit SDK version 3.2, this class no longer handles video rendering in the UI. Currently available SkypeKit runtimes do not support multi-party video. The API however is designed with future compatibility in mind, so the Video class is attached to Participant class rather than Conversation class. Once multi-party video will become available for SkypeKit, the logic should go like this: 
016     * 
017     * Let there be 4-way live conversation C and participants P1, P2, P3 and P4. P1 is the local user. Remote participants P2 and P3 are capable of sending video. Remote user P4 is not capable of sending video. You would then end up with 4 video objects: V1, V2, V3 and V0. 
018     * 
019     *  - C->P1->V1-> outgoing video stream 
020     *  - C->P2->V2-> incoming video stream 1 
021     *  - C->P3->V3-> incoming video stream 2 
022     *  - C->P4-> no video object as participant P4 does not advertise supporting video 
023     *  - V0-> local webcam preview - this is not attached to any particular conversation, however the corresponding video object can be retrieved with Skype.GetPreviewVideo method. 
024     * 
025     * As getting from a live conversation to running video streams involves three classes, it can be somewhat less than obvious. The basic state transition logic goes like this: 
026     * 
027     * You start out with a Conversation, that suddenly becomes live 
028     * 
029     * CONVERSATION.LOCAL_LIVESTATUS = IM_LIVE 
030     * At this point you have access to participant list of that conversation. The next step will be to catch Partcipant property changes for PARTICIPANT.VIDEO_STATUS to see if any of the people in conversation have Video available. Note that you should not make assumptions on when this availability happens. Remote users may switch their video on-off as they please. 
031     * 
032     * PARTICIPANT.VIDEO_STATUS = VIDEO_AVAILABLE 
033     * If you get to VIDEO_AVAILABLE (not necessarily for all Participants), you can retrieve Video object, with Participant.GetVideo method. 
034     * 
035     * Now you will need to handle Video.STATUS property changes. In case of successful video call, the sequence of Video.STATUS and Participant.VIDEO_STATUS changes for each Participant and Video object should look like this: 
036     * 
037     *  - Video.STATUS = AVAILABLE 
038     *  - Video.STATUS = STARTING 
039     *  - Video.STATUS = CHECKING_SUBSCRIPTION 
040     *  - Video.STATUS = STARTING 
041     * 
042     * Participant.VIDEO_STATUS = VIDEO_CONNECTING 
043     *  - Video.STATUS = RUNNING 
044     *  - Participant.VIDEO_STATUS = STREAMING 
045     * Both Video.STATUS == RUNNING and Participant.VIDEO_STATUS == STREAMING are indicative that the video for that particular participant is up and running, and your UI should update itself accordingly. 
046     * 
047     * NB! Note that it is not enough to check for Video.STATUS property updates. By the time you obtain the Video object in your client, it may already it may already have progressed to a further status. You should always check the status property immediately after obtaining the Video object. 
048     */
049    public final class Video extends SidObject {
050            public enum Status implements EnumConverting {
051                    NOT_AVAILABLE             (0),
052                    AVAILABLE                 (1),
053                    STARTING                  (2),
054                    REJECTED                  (3),
055                    RUNNING                   (4),
056                    STOPPING                  (5),
057                    PAUSED                    (6),
058                    NOT_STARTED               (7),
059                    HINT_IS_VIDEOCALL_RECEIVED(8),
060                    UNKNOWN                   (9),
061                    RENDERING                 (10),
062                    CHECKING_SUBSCRIPTION     (11),
063                    SWITCHING_DEVICE          (12);
064                    private final int key;
065                    Status(int key) {
066                            this.key = key;
067                    };
068                    public int getId()   { return key; }
069                    public EnumConverting getDefault() { return NOT_AVAILABLE; }
070                    public EnumConverting convert(int from) { return Status.get(from); }
071                    public EnumConverting[] getArray(final int size) { return new Status[size]; }
072                    public static Status get(int from) {
073                            switch (from) {
074                            case  0: return NOT_AVAILABLE;
075                            case  1: return AVAILABLE;
076                            case  2: return STARTING;
077                            case  3: return REJECTED;
078                            case  4: return RUNNING;
079                            case  5: return STOPPING;
080                            case  6: return PAUSED;
081                            case  7: return NOT_STARTED;
082                            case  8: return HINT_IS_VIDEOCALL_RECEIVED;
083                            case  9: return UNKNOWN;
084                            case 10: return RENDERING;
085                            case 11: return CHECKING_SUBSCRIPTION;
086                            case 12: return SWITCHING_DEVICE;
087                            }
088                            return NOT_AVAILABLE;
089                    }
090                    public static final int NOT_AVAILABLE_VALUE              =  0;
091                    public static final int AVAILABLE_VALUE                  =  1;
092                    public static final int STARTING_VALUE                   =  2;
093                    public static final int REJECTED_VALUE                   =  3;
094                    public static final int RUNNING_VALUE                    =  4;
095                    public static final int STOPPING_VALUE                   =  5;
096                    public static final int PAUSED_VALUE                     =  6;
097                    public static final int NOT_STARTED_VALUE                =  7;
098                    public static final int HINT_IS_VIDEOCALL_RECEIVED_VALUE =  8;
099                    public static final int UNKNOWN_VALUE                    =  9;
100                    public static final int RENDERING_VALUE                  = 10;
101                    public static final int CHECKING_SUBSCRIPTION_VALUE      = 11;
102                    public static final int SWITCHING_DEVICE_VALUE           = 12;
103            }
104            public enum MediaType implements EnumConverting {
105                    MEDIA_SCREENSHARING(1),
106                    MEDIA_VIDEO        (0);
107                    private final int key;
108                    MediaType(int key) {
109                            this.key = key;
110                    };
111                    public int getId()   { return key; }
112                    public EnumConverting getDefault() { return MEDIA_SCREENSHARING; }
113                    public EnumConverting convert(int from) { return MediaType.get(from); }
114                    public EnumConverting[] getArray(final int size) { return new MediaType[size]; }
115                    public static MediaType get(int from) {
116                            switch (from) {
117                            case 1: return MEDIA_SCREENSHARING;
118                            case 0: return MEDIA_VIDEO;
119                            }
120                            return MEDIA_SCREENSHARING;
121                    }
122                    public static final int MEDIA_SCREENSHARING_VALUE = 1;
123                    public static final int MEDIA_VIDEO_VALUE         = 0;
124            }
125            public enum VideoDeviceCapability implements EnumConverting {
126                    VIDEOCAP_HQ_CAPABLE      (0),
127                    VIDEOCAP_HQ_CERTIFIED    (1),
128                    VIDEOCAP_REQ_DRIVERUPDATE(2),
129                    VIDEOCAP_USB_HIGHSPEED   (3);
130                    private final int key;
131                    VideoDeviceCapability(int key) {
132                            this.key = key;
133                    };
134                    public int getId()   { return key; }
135                    public EnumConverting getDefault() { return VIDEOCAP_HQ_CAPABLE; }
136                    public EnumConverting convert(int from) { return VideoDeviceCapability.get(from); }
137                    public EnumConverting[] getArray(final int size) { return new VideoDeviceCapability[size]; }
138                    public static VideoDeviceCapability get(int from) {
139                            switch (from) {
140                            case 0: return VIDEOCAP_HQ_CAPABLE;
141                            case 1: return VIDEOCAP_HQ_CERTIFIED;
142                            case 2: return VIDEOCAP_REQ_DRIVERUPDATE;
143                            case 3: return VIDEOCAP_USB_HIGHSPEED;
144                            }
145                            return VIDEOCAP_HQ_CAPABLE;
146                    }
147                    public static final int VIDEOCAP_HQ_CAPABLE_VALUE       = 0;
148                    public static final int VIDEOCAP_HQ_CERTIFIED_VALUE     = 1;
149                    public static final int VIDEOCAP_REQ_DRIVERUPDATE_VALUE = 2;
150                    public static final int VIDEOCAP_USB_HIGHSPEED_VALUE    = 3;
151            }
152            private final static byte[] P_STATUS_req = {(byte) 90,(byte) 71,(byte) 130,(byte) 1,(byte) 93,(byte) 11};
153            private final static byte[] P_ERROR_req = {(byte) 90,(byte) 71,(byte) 131,(byte) 1,(byte) 93,(byte) 11};
154            private final static byte[] P_DEBUG_INFO_req = {(byte) 90,(byte) 71,(byte) 132,(byte) 1,(byte) 93,(byte) 11};
155            private final static byte[] P_DIMENSIONS_req = {(byte) 90,(byte) 71,(byte) 133,(byte) 1,(byte) 93,(byte) 11};
156            private final static byte[] P_MEDIA_TYPE_req = {(byte) 90,(byte) 71,(byte) 134,(byte) 1,(byte) 93,(byte) 11};
157            private final static byte[] P_CONVO_ID_req = {(byte) 90,(byte) 71,(byte) 208,(byte) 8,(byte) 93,(byte) 11};
158            private final static byte[] P_DEVICE_PATH_req = {(byte) 90,(byte) 71,(byte) 209,(byte) 8,(byte) 93,(byte) 11};
159            /** Properties of the Video class */
160            public enum Property implements PropertyEnumConverting {
161                    P_UNKNOWN    (0,0,null,0,null),
162                    P_STATUS     (130, 1, P_STATUS_req, 0, Status.get(0)),          P_ERROR      (131, 2, P_ERROR_req, 0, null),
163                    P_DEBUG_INFO (132, 3, P_DEBUG_INFO_req, 0, null),
164                    P_DIMENSIONS (133, 4, P_DIMENSIONS_req, 0, null),
165                    P_MEDIA_TYPE (134, 5, P_MEDIA_TYPE_req, 0, MediaType.get(0)),
166                    P_CONVO_ID   (1104, 6, P_CONVO_ID_req, 18, null),
167                    P_DEVICE_PATH(1105, 7, P_DEVICE_PATH_req, 0, null);
168                    private final int    key;
169                    private final int    idx;
170                    private final byte[] req;
171                    private final int    mod;
172                    private final EnumConverting enumConverter;
173                    Property(int key, int idx, byte[] req, int mod, EnumConverting converter) {
174                            this.key = key;
175                            this.idx = idx;
176                            this.req = req;
177                            this.mod = mod;
178                            this.enumConverter = converter;
179                    };
180                    public boolean  isCached()    { return idx > 0;   }
181                    public int      getIdx()      { return idx;       }
182                    public int      getId()       { return key;       }
183                    public byte[]   getRequest()  { return req;       }
184                    public EnumConverting getDefault()  { return P_UNKNOWN; }
185                    public int      getModuleId() { return mod;       }
186                    public EnumConverting getEnumConverter()    { return enumConverter;   }
187                    public EnumConverting convert(final int from) { return Property.get(from); }
188                    public EnumConverting[] getArray(final int size) { return new Property[size]; }
189                    public static Property get(final int from) {
190                            switch (from) {
191                            case  130: return P_STATUS;
192                            case  131: return P_ERROR;
193                            case  132: return P_DEBUG_INFO;
194                            case  133: return P_DIMENSIONS;
195                            case  134: return P_MEDIA_TYPE;
196                            case 1104: return P_CONVO_ID;
197                            case 1105: return P_DEVICE_PATH;
198                            }
199                            return P_UNKNOWN;
200                    }
201                    public static final int P_STATUS_VALUE      =  130;
202                    public static final int P_ERROR_VALUE       =  131;
203                    public static final int P_DEBUG_INFO_VALUE  =  132;
204                    public static final int P_DIMENSIONS_VALUE  =  133;
205                    public static final int P_MEDIA_TYPE_VALUE  =  134;
206                    public static final int P_CONVO_ID_VALUE    = 1104;
207                    public static final int P_DEVICE_PATH_VALUE = 1105;
208            }
209            /** Setupkey SETUPKEY_VIDEO_DEVICE type:string  <br>Selected video device name <br>This is account-specific setup key. It can only be used while an account is logged in. <br> */
210            public static final String VIDEO_DEVICE = "Lib/Video/Device";
211            
212            /** Setupkey SETUPKEY_VIDEO_DEVICE_PATH type:string  <br>Currently selected video device path. <br>This is account-specific setup key. It can only be used while an account is logged in. <br> */
213            public static final String VIDEO_DEVICE_PATH = "Lib/Video/DevicePath";
214            
215            /** Setupkey SETUPKEY_VIDEO_AUTOSEND type:int  <br>Setting this to 1 starts sending video automatically when call starts <br>This is account-specific setup key. It can only be used while an account is logged in. <br> */
216            public static final String VIDEO_AUTOSEND = "Lib/Video/AutoSend";
217            
218            /** Setupkey SETUPKEY_VIDEO_DISABLE type:int  <br>Setting this to 1 disables all video functionality. <br>This setup key is machine-specific and affects all local accounts. <br> */
219            public static final String VIDEO_DISABLE = "*Lib/Video/Disable";
220            
221            /** Setupkey SETUPKEY_VIDEO_RECVPOLICY type:string default value:"contacts" <br>noone | contacts | callpolicy <br>This is account-specific setup key. It can only be used while an account is logged in. <br> */
222            public static final String VIDEO_RECVPOLICY = "Lib/Video/RecvPolicy";
223            
224            /** Setupkey SETUPKEY_VIDEO_ADVERTPOLICY type:string default value:"contacts" <br>noone | contacts | everyone <br>This is account-specific setup key. It can only be used while an account is logged in. <br> */
225            public static final String VIDEO_ADVERTPOLICY = "Lib/Video/AdvertPolicy";
226            
227            private final static byte[] setScreen_req = {(byte) 90,(byte) 82,(byte) 11,(byte) 1};
228            /**
229             * setScreen
230             * @param windowh
231             */
232            public void setScreen(int windowh) {
233                    try {
234                            sidDoRequest(setScreen_req)
235                            .addUintParm(1, windowh)
236                            .endOneWay();
237                    } catch(IOException e) {
238                            mSidRoot.sidOnFatalError(e);
239                    }
240            }
241            private final static byte[] start_req = {(byte) 90,(byte) 82,(byte) 11,(byte) 2};
242            /** This method starts either video send or video receive, depending on whether the video object is sender or receiver. In case of desktop video, the receiver side needs to instantiate a renderer object and associate it with the receiveing video (Video.SetRemoteRendererId).   */
243            public void start() {
244                    try {
245                            sidDoRequest(start_req)
246                            .endOneWay();
247                    } catch(IOException e) {
248                            mSidRoot.sidOnFatalError(e);
249                    }
250            }
251            private final static byte[] stop_req = {(byte) 90,(byte) 82,(byte) 11,(byte) 3};
252            /** This method stops either video send or video receive, depending on whether the video object is sender or receiver. In case of desktop video, the receiver side needs to dis-associate the video object from the renderer, by calling Video.SetRemoteRendererId(0).   */
253            public void stop() {
254                    try {
255                            sidDoRequest(stop_req)
256                            .endOneWay();
257                    } catch(IOException e) {
258                            mSidRoot.sidOnFatalError(e);
259                    }
260            }
261            private final static byte[] submitCaptureRequest_req = {(byte) 90,(byte) 82,(byte) 11,(byte) 11};
262            public class SubmitCaptureRequestResponse {
263                    public boolean ret;
264                    public int requestId;
265            };
266            
267            /**
268             * submitCaptureRequest
269             * @return SubmitCaptureRequestResponse
270             * <br> - ret
271             * <br> - requestId
272             */
273            public SubmitCaptureRequestResponse submitCaptureRequest() {
274                    try {
275                            Decoding decoder = sidDoRequest(submitCaptureRequest_req)
276                            .endRequest();
277                            SubmitCaptureRequestResponse result = new SubmitCaptureRequestResponse();
278                            result.ret = decoder.getBoolParm(1, false);
279                            result.requestId = decoder.getUintParm(2, true);
280                            return result;
281                    } catch(IOException e) {
282                            mSidRoot.sidOnFatalError(e);
283                            return null
284                    ;}
285            }
286            private final static byte[] setScreenCaptureRectangle_req = {(byte) 90,(byte) 82,(byte) 11,(byte) 5};
287            /** This method has no known effect in current version.  * @param x0
288             * @param y0
289             * @param width
290             * @param height
291             * @param monitorNumber
292             * @param windowHandle
293             */
294            public void setScreenCaptureRectangle(int x0, int y0, int width, int height, int monitorNumber, int windowHandle) {
295                    try {
296                            sidDoRequest(setScreenCaptureRectangle_req)
297                            .addIntParm(1, x0)
298                            .addIntParm(2, y0)
299                            .addUintParm(3, width)
300                            .addUintParm(4, height)
301                            .addIntParm(5, monitorNumber)
302                            .addUintParm(6, windowHandle)
303                            .endOneWay();
304                    } catch(IOException e) {
305                            mSidRoot.sidOnFatalError(e);
306                    }
307            }
308            private final static byte[] setRenderRectangle_req = {(byte) 90,(byte) 82,(byte) 11,(byte) 6};
309            /**
310             * setRenderRectangle
311             * @param x0
312             * @param y0
313             * @param width
314             * @param height
315             */
316            public void setRenderRectangle(int x0, int y0, int width, int height) {
317                    try {
318                            sidDoRequest(setRenderRectangle_req)
319                            .addIntParm(1, x0)
320                            .addIntParm(2, y0)
321                            .addUintParm(3, width)
322                            .addUintParm(4, height)
323                            .endOneWay();
324                    } catch(IOException e) {
325                            mSidRoot.sidOnFatalError(e);
326                    }
327            }
328            private final static byte[] setRemoteRendererId_req = {(byte) 90,(byte) 82,(byte) 11,(byte) 14};
329            /**
330             * setRemoteRendererId
331             * @param id
332             */
333            public void setRemoteRendererId(int id) {
334                    try {
335                            sidDoRequest(setRemoteRendererId_req)
336                            .addUintParm(1, id)
337                            .endOneWay();
338                    } catch(IOException e) {
339                            mSidRoot.sidOnFatalError(e);
340                    }
341            }
342            private final static byte[] selectVideoSource_req = {(byte) 90,(byte) 82,(byte) 11,(byte) 7};
343            /** This method has no effect in current version.  * @param mediaType
344             * @param webcamName
345             * @param devicePath
346             * @param updateSetup
347             */
348            public void selectVideoSource(MediaType mediaType, String webcamName, String devicePath, boolean updateSetup) {
349                    try {
350                            sidDoRequest(selectVideoSource_req)
351                            .addEnumParm(1, mediaType)
352                            .addStringParm(2, webcamName)
353                            .addStringParm(3, devicePath)
354                            .addBoolParm(4, updateSetup)
355                            .endOneWay();
356                    } catch(IOException e) {
357                            mSidRoot.sidOnFatalError(e);
358                    }
359            }
360            private final static byte[] getCurrentVideoDevice_req = {(byte) 90,(byte) 82,(byte) 11,(byte) 10};
361            public class GetCurrentVideoDeviceResponse {
362                    public MediaType mediatype;
363                    public String deviceName;
364                    public String devicePath;
365            };
366            
367            /**
368             * getCurrentVideoDevice
369             * @return GetCurrentVideoDeviceResponse
370             * <br> - mediatype
371             * <br> - deviceName
372             * <br> - devicePath
373             */
374            public GetCurrentVideoDeviceResponse getCurrentVideoDevice() {          try {
375                            Decoding decoder = sidDoRequest(getCurrentVideoDevice_req)
376                            .endRequest();
377                            GetCurrentVideoDeviceResponse result = new GetCurrentVideoDeviceResponse();
378                            result.mediatype = (MediaType) decoder.getEnumParm(1, MediaType.get(0), false);
379                            result.deviceName = decoder.getStringParm(2, false);
380                            result.devicePath = decoder.getStringParm(3, true);
381                            return result;
382                    } catch(IOException e) {
383                            mSidRoot.sidOnFatalError(e);
384                            return null
385                    ;}
386            }
387            /***
388             * generic multiget of a list of Property
389             * @param requested the list of requested properties of Video
390             * @return SidGetResponding
391             */
392            public SidGetResponding sidMultiGet(Property[] requested) {
393                    return super.sidMultiGet(requested);
394            }
395            /***
396             * generic multiget of list of Property for a list of Video
397             * @param requested the list of requested properties
398             * @return SidGetResponding[] can be casted to (Video[]) if all properties are cached
399             */
400            static public SidGetResponding[] sidMultiGet(Property[] requested, Video[] objects) {
401                    return SidObject.sidMultiGet(requested, objects);
402            }
403            /** Video.STATUS */
404            public Status getStatus() {
405                    synchronized(this) {
406                            if ((mSidCached & 0x1) != 0)
407                                    return mStatus;
408                    }
409                    return (Status) sidRequestEnumProperty(Property.P_STATUS);
410            }
411            /** 'errorcode errortext'  */
412            public String getError() {
413                    synchronized(this) {
414                            if ((mSidCached & 0x2) != 0)
415                                    return mError;
416                    }
417                    return sidRequestStringProperty(Property.P_ERROR);
418            }
419            /** space-separated string of tokens */
420            public String getDebugInfo() {
421                    synchronized(this) {
422                            if ((mSidCached & 0x4) != 0)
423                                    return mDebugInfo;
424                    }
425                    return sidRequestStringProperty(Property.P_DEBUG_INFO);
426            }
427            /** This property does not currently work, always containing an empty string. For desktop video, you can get the frame dimensions from the video frame buffers API instead - the buffer struct retrieved with ipc.getFrame() or ipc.getNewFrame() has width and height fields, which you can then use in your UI. With RTP video solutions, you already have the frame sizes in your videohost code. Communicating these to the UI process is currently up to you.  */
428            public String getDimensions() {
429                    synchronized(this) {
430                            if ((mSidCached & 0x8) != 0)
431                                    return mDimensions;
432                    }
433                    return sidRequestStringProperty(Property.P_DIMENSIONS);
434            }
435            /** Indicates whether the video object is streaming webcam video or screensharing session, values: MEDIA_SCREENSHARING, MEDIA_VIDEO  */
436            public MediaType getMediaType() {
437                    synchronized(this) {
438                            if ((mSidCached & 0x10) != 0)
439                                    return mMediaType;
440                    }
441                    return (MediaType) sidRequestEnumProperty(Property.P_MEDIA_TYPE);
442            }
443            /** conference id to be able to identify remote/local video in the same call */
444            public Conversation getConvoId() {
445                    synchronized(this) {
446                            if ((mSidCached & 0x20) != 0)
447                                    return mConvoId;
448                    }
449                    return (Conversation) sidRequestObjectProperty(Property.P_CONVO_ID);
450            }
451            /** device path used by video object */
452            public String getDevicePath() {
453                    synchronized(this) {
454                            if ((mSidCached & 0x40) != 0)
455                                    return mDevicePath;
456                    }
457                    return sidRequestStringProperty(Property.P_DEVICE_PATH);
458            }
459            public String sidGetStringProperty(final PropertyEnumConverting prop) {
460                    switch(prop.getId()) {
461                    case 131:
462                            return mError;
463                    case 132:
464                            return mDebugInfo;
465                    case 133:
466                            return mDimensions;
467                    case 1105:
468                            return mDevicePath;
469                    }
470                    return "";
471            }
472            public SidObject sidGetObjectProperty(final PropertyEnumConverting prop) {
473                    assert(prop.getId() == 1104);
474                    return mConvoId;
475            }
476            public EnumConverting sidGetEnumProperty(final PropertyEnumConverting prop) {
477                    switch(prop.getId()) {
478                    case 130:
479                            return mStatus;
480                    case 134:
481                            return mMediaType;
482                    }
483                    return null;
484            }
485            public String getPropertyAsString(final int prop) {
486                    switch (prop) {
487                    case 130: return getStatus().toString();
488                    case 131: return getError();
489                    case 132: return getDebugInfo();
490                    case 133: return getDimensions();
491                    case 134: return getMediaType().toString();
492                    case 1104: return Integer.toString(getConvoId().getOid());
493                    case 1105: return getDevicePath();
494                    }
495                    return "<unkown>";
496            }
497            public String getPropertyAsString(final Property prop) {
498                    return getPropertyAsString(prop.getId());
499            }
500            protected void sidOnChangedProperty(final int propertyId, final int value, final String svalue) {
501                    final Property property = Property.get(propertyId);
502                    if (property == Property.P_UNKNOWN) return;
503                    final int idx = property.getIdx();
504                    if (idx != 0) {
505                            int bit  = 1<<((idx-1)%32);
506                            synchronized (this) {
507                                    mSidCached|=bit;
508                                    switch (propertyId) {
509                                    case 130: mStatus = Status.get(value); break;
510                                    case 131:
511                                            if (svalue != null) mError = svalue;
512                                            else mSidCached &=~bit;
513                                            break;
514                                    case 132:
515                                            if (svalue != null) mDebugInfo = svalue;
516                                            else mSidCached &=~bit;
517                                            break;
518                                    case 133:
519                                            if (svalue != null) mDimensions = svalue;
520                                            else mSidCached &=~bit;
521                                            break;
522                                    case 134: mMediaType = MediaType.get(value); break;
523                                    case 1105:
524                                            if (svalue != null) mDevicePath = svalue;
525                                            else mSidCached &=~bit;
526                                            break;
527                                    default: mSidCached|=bit; break;
528                                    }
529                            }
530                    }
531                    VideoListener listener = ((Skype) mSidRoot).getVideoListener();
532                    if (listener != null)
533                            listener.onPropertyChange(this, property, value, svalue);
534            }
535            public void sidSetProperty(final PropertyEnumConverting prop, final String newValue) {
536                    final int propId = prop.getId();
537                    switch(propId) {
538                    case 131:
539                            mSidCached |= 0x2;
540                            mError=  newValue;
541                            break;
542                    case 132:
543                            mSidCached |= 0x4;
544                            mDebugInfo=  newValue;
545                            break;
546                    case 133:
547                            mSidCached |= 0x8;
548                            mDimensions=  newValue;
549                            break;
550                    case 1105:
551                            mSidCached |= 0x40;
552                            mDevicePath=  newValue;
553                            break;
554                    }
555            }
556            public void sidSetProperty(final PropertyEnumConverting prop, final SidObject newValue) {
557                    final int propId = prop.getId();
558                    assert(propId == 1104);
559                    mSidCached |= 0x20;
560                    mConvoId= (Conversation) newValue;
561            }
562            public void sidSetProperty(final PropertyEnumConverting prop, final int newValue) {
563                    final int propId = prop.getId();
564                    switch(propId) {
565                    case 130:
566                            mSidCached |= 0x1;
567                            mStatus= Status.get(newValue);
568                            break;
569                    case 134:
570                            mSidCached |= 0x10;
571                            mMediaType= MediaType.get(newValue);
572                            break;
573                    }
574            }
575            public Status       mStatus;
576            public String       mError;
577            public String       mDebugInfo;
578            public String       mDimensions;
579            public MediaType    mMediaType;
580            public Conversation mConvoId;
581            public String       mDevicePath;
582            public int moduleId() {
583                    return 11;
584            }
585            
586            public Video(final int oid, final SidRoot root) {
587                    super(oid, root, 7);
588            }
589    }