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 * Wrapper class that includes voicemail-specific methods and properties. In the Skype Conversation API, Voicemail is actually something of a misnomer for what would be more accurately called Voice Message.
016 *
017 * The traditional Voicemail use case involves recording a voice message when an incoming call does not get answered in a pre-determined amount of time. In the Skype Conversation API, voicemail does not depend on a call going unanswered - you can post a voice message asynchronously into any dialog conversation at any time.
018 *
019 * In fact, a high-level action flow directing unanswered incoming live sessions to voicemail is not something provided by the Conversation API - implementation of this use case is largely up to your UI.
020 *
021 * The fact that your UI must retrieve incoming Voicemails by monitoring changes to a Conversation instance's Messages illustrates this conceptual difference between traditional voicemail and voice messages. The message type Message.POSTED_VOICE_MESSAGE indicates that a Message instance should be handled as a voice message instead of by displaying its body text in the Conversation UI. Message.GetVoiceMessage enables you to retrieve the associated Voicemail instance; Voicemail.StartPlayback enables you to listen to the message audio.
022 *
023 * To put it another way, the object chain goes like this:
024 * @code
025 * Contact->Conversation->Message->Voicemail
026 * </CODE>
027 *
028 * There are three basic types of Voicemail objects:
029 * - INCOMING - received voice messages that can be retrieved from Message objects;
030 * - OUTGOING - outbound voice messages that can be created with Conversation.StartVoiceMessage;
031 * - GREETING - voice messages that represent auto-answer greetings, either recorded by the user (CUSTOM_GREETING) or included as part of SkypeKit (DEFAULT_GREETING). This is the audio that gets played back to sender of the voice message before he can start recording his voice message.
032 *
033 * Before trying to send out a voicemail, you should ensure that target Contact has the capability to receive them. Use Contact.GetCapabilityStatus to check for Contact.CAPABILITY_CAN_BE_SENT_VM.
034 *
035 * Recording and Sending a Voice Message
036 *
037 * The first step is to obtain a dialog Conversation with the target Contact. In that conversation, you can initiate the outgoing voice message with Conversation.StartVoiceMessage
038 *
039 * Note that this call does not return an actual Voicemail object. To catch when an object gets created, you will need to check Conversation.P_ACTIVE_VM_ID property updates.
040 *
041 * After invoking Conversation.StartVoiceMessage, SkypeKit instantiates a Voicemail instance for the target Contact's greeting (with type CUSTOM_GREETING or DEFAULT_GREETING). At this point, the Conversation.P_ACTIVE_VM_ID property update fires, newVM contains a reference to the greeting, and playback of the greeting for the sender starts automatically.
042 *
043 * Once the greeting playback finishes, SkypeKit instantiates a second Voicemail instance for the outgoing voice message. At this point, the Conversation.P_ACTIVE_VM_ID property update fires again, newVM now contains a reference to the outgoing message, and recording starts automatically. If you want to include notification and/or error handling for whether this message was sent successfully, you should make a copy of newVM now.
044 *
045 * Once the user finishes (or abandons) recording of their message, they want to either send the message or to cancel it. To send the message, use Conversation.PostVoiceMessage; to cancel the message, use Conversation.LeaveLiveSession.
046 *
047 * Both of these actions results in the Conversation.P_ACTIVE_VM_ID property update firing for a third time, setting the value to NULL. However, the Voicemail object will actually continue its existence past this point. Saving a reference to the message's Voicemail object when you start recording it enables you to keep receiving Voicemail property updates. This in turn enables your UI to check whether voice message send succeeded or failed.
048 *
049 * The relevant terminal state Voicemail.P_STATUS property values are:
050 * - Voicemail.CANCELLED - recording and/or sending of this message was cancelled
051 * - Voicemail.UPLOADED - message sent
052 * - Voicemail.FAILED - message could not be sent
053 *
054 * Receiving and Playing Back a Voice Message
055 *
056 * On the remote side, the Voicemail appears as a Message object of type Message.POSTED_VOICE_MESSAGE. The message's author property contains the Skype Name of the Voicemail originator, and its BodyXml property contains the message length and title text in following format:
057 *
058 * @code
059 * <voicemail alt="Sent voicemail to people in this conversation."><message length="5" ></message></voicemail>
060 * </CODE>
061 *
062 * Receiver side UI can then retrieve the Voicemail object from the message with Message.GetVoiceMessage and
063 * start local playback with Message.StartPlayback.
064 */
065 public final class Voicemail extends SidObject {
066 public enum Type implements EnumConverting {
067 INCOMING (1),
068 DEFAULT_GREETING(4),
069 CUSTOM_GREETING (2),
070 OUTGOING (3);
071 private final int key;
072 Type(int key) {
073 this.key = key;
074 };
075 public int getId() { return key; }
076 public EnumConverting getDefault() { return INCOMING; }
077 public EnumConverting convert(int from) { return Type.get(from); }
078 public EnumConverting[] getArray(final int size) { return new Type[size]; }
079 public static Type get(int from) {
080 switch (from) {
081 case 1: return INCOMING;
082 case 4: return DEFAULT_GREETING;
083 case 2: return CUSTOM_GREETING;
084 case 3: return OUTGOING;
085 }
086 return INCOMING;
087 }
088 public static final int INCOMING_VALUE = 1;
089 public static final int DEFAULT_GREETING_VALUE = 4;
090 public static final int CUSTOM_GREETING_VALUE = 2;
091 public static final int OUTGOING_VALUE = 3;
092 }
093 public enum Status implements EnumConverting {
094 NOTDOWNLOADED (1),
095 DOWNLOADING (2),
096 UNPLAYED (3),
097 BUFFERING (4),
098 PLAYING (5),
099 PLAYED (6),
100 BLANK (7),
101 RECORDING (8),
102 RECORDED (9),
103 UPLOADING (10),
104 UPLOADED (11),
105 DELETING (12),
106 FAILED (13),
107 DELETING_FAILED(14),
108 CHECKING (15),
109 CANCELLED (16);
110 private final int key;
111 Status(int key) {
112 this.key = key;
113 };
114 public int getId() { return key; }
115 public EnumConverting getDefault() { return NOTDOWNLOADED; }
116 public EnumConverting convert(int from) { return Status.get(from); }
117 public EnumConverting[] getArray(final int size) { return new Status[size]; }
118 public static Status get(int from) {
119 switch (from) {
120 case 1: return NOTDOWNLOADED;
121 case 2: return DOWNLOADING;
122 case 3: return UNPLAYED;
123 case 4: return BUFFERING;
124 case 5: return PLAYING;
125 case 6: return PLAYED;
126 case 7: return BLANK;
127 case 8: return RECORDING;
128 case 9: return RECORDED;
129 case 10: return UPLOADING;
130 case 11: return UPLOADED;
131 case 12: return DELETING;
132 case 13: return FAILED;
133 case 14: return DELETING_FAILED;
134 case 15: return CHECKING;
135 case 16: return CANCELLED;
136 }
137 return NOTDOWNLOADED;
138 }
139 public static final int NOTDOWNLOADED_VALUE = 1;
140 public static final int DOWNLOADING_VALUE = 2;
141 public static final int UNPLAYED_VALUE = 3;
142 public static final int BUFFERING_VALUE = 4;
143 public static final int PLAYING_VALUE = 5;
144 public static final int PLAYED_VALUE = 6;
145 public static final int BLANK_VALUE = 7;
146 public static final int RECORDING_VALUE = 8;
147 public static final int RECORDED_VALUE = 9;
148 public static final int UPLOADING_VALUE = 10;
149 public static final int UPLOADED_VALUE = 11;
150 public static final int DELETING_VALUE = 12;
151 public static final int FAILED_VALUE = 13;
152 public static final int DELETING_FAILED_VALUE = 14;
153 public static final int CHECKING_VALUE = 15;
154 public static final int CANCELLED_VALUE = 16;
155 }
156 public enum FailureReason implements EnumConverting {
157 MISC_ERROR (1),
158 CONNECT_ERROR (2),
159 NO_VOICEMAIL_CAPABILITY (3), NO_SUCH_VOICEMAIL (4),
160 FILE_READ_ERROR (5),
161 FILE_WRITE_ERROR (6),
162 RECORDING_ERROR (7),
163 PLAYBACK_ERROR (8),
164 NO_PERMISSION (9),
165 /** receiver turned off voicemail */
166 RECEIVER_DISABLED_VOICEMAIL(10),
167 /** receiver has not authorized you and privacy is not set to anyone */
168 SENDER_NOT_AUTHORIZED (11),
169 /** receiver blocked sender */
170 SENDER_BLOCKED (12);
171 private final int key;
172 FailureReason(int key) {
173 this.key = key;
174 };
175 public int getId() { return key; }
176 public EnumConverting getDefault() { return MISC_ERROR; }
177 public EnumConverting convert(int from) { return FailureReason.get(from); }
178 public EnumConverting[] getArray(final int size) { return new FailureReason[size]; }
179 public static FailureReason get(int from) {
180 switch (from) {
181 case 1: return MISC_ERROR;
182 case 2: return CONNECT_ERROR;
183 case 3: return NO_VOICEMAIL_CAPABILITY;
184 case 4: return NO_SUCH_VOICEMAIL;
185 case 5: return FILE_READ_ERROR;
186 case 6: return FILE_WRITE_ERROR;
187 case 7: return RECORDING_ERROR;
188 case 8: return PLAYBACK_ERROR;
189 case 9: return NO_PERMISSION;
190 case 10: return RECEIVER_DISABLED_VOICEMAIL;
191 case 11: return SENDER_NOT_AUTHORIZED;
192 case 12: return SENDER_BLOCKED;
193 }
194 return MISC_ERROR;
195 }
196 public static final int MISC_ERROR_VALUE = 1;
197 public static final int CONNECT_ERROR_VALUE = 2;
198 public static final int NO_VOICEMAIL_CAPABILITY_VALUE = 3;
199 public static final int NO_SUCH_VOICEMAIL_VALUE = 4;
200 public static final int FILE_READ_ERROR_VALUE = 5;
201 public static final int FILE_WRITE_ERROR_VALUE = 6;
202 public static final int RECORDING_ERROR_VALUE = 7;
203 public static final int PLAYBACK_ERROR_VALUE = 8;
204 public static final int NO_PERMISSION_VALUE = 9;
205 public static final int RECEIVER_DISABLED_VOICEMAIL_VALUE = 10;
206 public static final int SENDER_NOT_AUTHORIZED_VALUE = 11;
207 public static final int SENDER_BLOCKED_VALUE = 12;
208 }
209 private final static byte[] P_TYPE_req = {(byte) 90,(byte) 71,(byte) 100,(byte) 93,(byte) 7};
210 private final static byte[] P_PARTNER_HANDLE_req = {(byte) 90,(byte) 71,(byte) 101,(byte) 93,(byte) 7};
211 private final static byte[] P_PARTNER_DISPLAY_NAME_req = {(byte) 90,(byte) 71,(byte) 102,(byte) 93,(byte) 7};
212 private final static byte[] P_STATUS_req = {(byte) 90,(byte) 71,(byte) 103,(byte) 93,(byte) 7};
213 private final static byte[] P_FAILURE_REASON_req = {(byte) 90,(byte) 71,(byte) 104,(byte) 93,(byte) 7};
214 private final static byte[] P_SUBJECT_req = {(byte) 90,(byte) 71,(byte) 105,(byte) 93,(byte) 7};
215 private final static byte[] P_TIMESTAMP_req = {(byte) 90,(byte) 71,(byte) 106,(byte) 93,(byte) 7};
216 private final static byte[] P_DURATION_req = {(byte) 90,(byte) 71,(byte) 107,(byte) 93,(byte) 7};
217 private final static byte[] P_ALLOWED_DURATION_req = {(byte) 90,(byte) 71,(byte) 108,(byte) 93,(byte) 7};
218 private final static byte[] P_PLAYBACK_PROGRESS_req = {(byte) 90,(byte) 71,(byte) 109,(byte) 93,(byte) 7};
219 private final static byte[] P_CONVERSATION_req = {(byte) 90,(byte) 71,(byte) 190,(byte) 6,(byte) 93,(byte) 7};
220 private final static byte[] P_CHAT_MSG_GUID_req = {(byte) 90,(byte) 71,(byte) 191,(byte) 6,(byte) 93,(byte) 7};
221 /** Properties of the Voicemail class */
222 public enum Property implements PropertyEnumConverting {
223 P_UNKNOWN (0,0,null,0,null),
224 P_TYPE (100, 1, P_TYPE_req, 0, Type.get(0)),
225 P_PARTNER_HANDLE (101, 2, P_PARTNER_HANDLE_req, 0, null),
226 P_PARTNER_DISPLAY_NAME(102, 3, P_PARTNER_DISPLAY_NAME_req, 0, null),
227 P_STATUS (103, 4, P_STATUS_req, 0, Status.get(0)),
228 P_FAILURE_REASON (104, 5, P_FAILURE_REASON_req, 0, FailureReason.get(0)),
229 P_SUBJECT (105, 6, P_SUBJECT_req, 0, null),
230 P_TIMESTAMP (106, 7, P_TIMESTAMP_req, 0, null),
231 P_DURATION (107, 8, P_DURATION_req, 0, null),
232 P_ALLOWED_DURATION (108, 9, P_ALLOWED_DURATION_req, 0, null),
233 P_PLAYBACK_PROGRESS (109, 10, P_PLAYBACK_PROGRESS_req, 0, null),
234 P_CONVERSATION (830, 11, P_CONVERSATION_req, 18, null),
235 P_CHAT_MSG_GUID (831, 12, P_CHAT_MSG_GUID_req, 0, null);
236 private final int key;
237 private final int idx;
238 private final byte[] req;
239 private final int mod;
240 private final EnumConverting enumConverter;
241 Property(int key, int idx, byte[] req, int mod, EnumConverting converter) {
242 this.key = key;
243 this.idx = idx;
244 this.req = req;
245 this.mod = mod;
246 this.enumConverter = converter;
247 };
248 public boolean isCached() { return idx > 0; }
249 public int getIdx() { return idx; }
250 public int getId() { return key; }
251 public byte[] getRequest() { return req; }
252 public EnumConverting getDefault() { return P_UNKNOWN; }
253 public int getModuleId() { return mod; }
254 public EnumConverting getEnumConverter() { return enumConverter; }
255 public EnumConverting convert(final int from) { return Property.get(from); }
256 public EnumConverting[] getArray(final int size) { return new Property[size]; }
257 public static Property get(final int from) {
258 switch (from) {
259 case 100: return P_TYPE;
260 case 101: return P_PARTNER_HANDLE;
261 case 102: return P_PARTNER_DISPLAY_NAME;
262 case 103: return P_STATUS;
263 case 104: return P_FAILURE_REASON;
264 case 105: return P_SUBJECT;
265 case 106: return P_TIMESTAMP;
266 case 107: return P_DURATION;
267 case 108: return P_ALLOWED_DURATION;
268 case 109: return P_PLAYBACK_PROGRESS;
269 case 830: return P_CONVERSATION;
270 case 831: return P_CHAT_MSG_GUID;
271 }
272 return P_UNKNOWN;
273 }
274 public static final int P_TYPE_VALUE = 100;
275 public static final int P_PARTNER_HANDLE_VALUE = 101;
276 public static final int P_PARTNER_DISPLAY_NAME_VALUE = 102;
277 public static final int P_STATUS_VALUE = 103;
278 public static final int P_FAILURE_REASON_VALUE = 104;
279 public static final int P_SUBJECT_VALUE = 105;
280 public static final int P_TIMESTAMP_VALUE = 106;
281 public static final int P_DURATION_VALUE = 107;
282 public static final int P_ALLOWED_DURATION_VALUE = 108;
283 public static final int P_PLAYBACK_PROGRESS_VALUE = 109;
284 public static final int P_CONVERSATION_VALUE = 830;
285 public static final int P_CHAT_MSG_GUID_VALUE = 831;
286 }
287 private final static byte[] startRecording_req = {(byte) 90,(byte) 82,(byte) 7,(byte) 3};
288 /** Start recording your own auto-answer greeting message (leave message after the beep...) only. Recording of outgoing Voicemail messages start automatically (using Conversation.StartVoiceMessage) after playback of the remote side greeting message has finished. */
289 public void startRecording() {
290 try {
291 sidDoRequest(startRecording_req)
292 .endOneWay();
293 } catch(IOException e) {
294 mSidRoot.sidOnFatalError(e);
295 }
296 }
297 private final static byte[] stopRecording_req = {(byte) 90,(byte) 82,(byte) 7,(byte) 4};
298 /** Stop recording of your own auto-answer greeting message only. To stop recording of and send an outgoing Voicemail, use Conversation.PostVoiceMessage. */
299 public void stopRecording() {
300 try {
301 sidDoRequest(stopRecording_req)
302 .endOneWay();
303 } catch(IOException e) {
304 mSidRoot.sidOnFatalError(e);
305 }
306 }
307 private final static byte[] startPlayback_req = {(byte) 90,(byte) 82,(byte) 7,(byte) 5};
308 /** Initiates playback of a voice message */
309 public void startPlayback() {
310 try {
311 sidDoRequest(startPlayback_req)
312 .endOneWay();
313 } catch(IOException e) {
314 mSidRoot.sidOnFatalError(e);
315 }
316 }
317 private final static byte[] stopPlayback_req = {(byte) 90,(byte) 82,(byte) 7,(byte) 6};
318 /** Terminates playback of a voice message */
319 public void stopPlayback() {
320 try {
321 sidDoRequest(stopPlayback_req)
322 .endOneWay();
323 } catch(IOException e) {
324 mSidRoot.sidOnFatalError(e);
325 }
326 }
327 private final static byte[] delete_req = {(byte) 90,(byte) 82,(byte) 7,(byte) 7};
328 /** first from server, and then the local copy */
329 public void delete() {
330 try {
331 sidDoRequest(delete_req) .endOneWay();
332 } catch(IOException e) {
333 mSidRoot.sidOnFatalError(e);
334 }
335 }
336 private final static byte[] cancel_req = {(byte) 90,(byte) 82,(byte) 7,(byte) 8};
337 /** Canceling recording of your own auto-answer greeting message. To stop recording of and cancel an outgoing Voicemail, use Conversation.LeaveLiveSession. */
338 public void cancel() {
339 try {
340 sidDoRequest(cancel_req)
341 .endOneWay();
342 } catch(IOException e) {
343 mSidRoot.sidOnFatalError(e);
344 }
345 }
346 private final static byte[] checkPermission_req = {(byte) 90,(byte) 82,(byte) 7,(byte) 13};
347 /** check if we can send voicemail (unauth,blocked,no priv etc cases). only OUTGOING * @return result
348 */
349 public boolean checkPermission() {
350 try {
351 return sidDoRequest(checkPermission_req)
352 .endRequest().getBoolParm(1, true);
353 } catch(IOException e) {
354 mSidRoot.sidOnFatalError(e);
355 return false
356 ;}
357 }
358 /***
359 * generic multiget of a list of Property
360 * @param requested the list of requested properties of Voicemail
361 * @return SidGetResponding
362 */
363 public SidGetResponding sidMultiGet(Property[] requested) {
364 return super.sidMultiGet(requested);
365 }
366 /***
367 * generic multiget of list of Property for a list of Voicemail
368 * @param requested the list of requested properties
369 * @return SidGetResponding[] can be casted to (Voicemail[]) if all properties are cached
370 */
371 static public SidGetResponding[] sidMultiGet(Property[] requested, Voicemail[] objects) {
372 return SidObject.sidMultiGet(requested, objects);
373 }
374 public Type getType() {
375 synchronized(this) {
376 if ((mSidCached & 0x1) != 0)
377 return mType;
378 }
379 return (Type) sidRequestEnumProperty(Property.P_TYPE);
380 }
381 /** registered username of the other party */
382 public String getPartnerHandle() {
383 synchronized(this) {
384 if ((mSidCached & 0x2) != 0)
385 return mPartnerHandle;
386 }
387 return sidRequestStringProperty(Property.P_PARTNER_HANDLE);
388 }
389 /** user's display name of the other party */
390 public String getPartnerDisplayName() {
391 synchronized(this) {
392 if ((mSidCached & 0x4) != 0)
393 return mPartnerDisplayName;
394 }
395 return sidRequestStringProperty(Property.P_PARTNER_DISPLAY_NAME);
396 }
397 public Status getStatus() {
398 synchronized(this) {
399 if ((mSidCached & 0x8) != 0)
400 return mStatus;
401 }
402 return (Status) sidRequestEnumProperty(Property.P_STATUS);
403 }
404 public FailureReason getFailureReason() {
405 synchronized(this) {
406 if ((mSidCached & 0x10) != 0)
407 return mFailureReason;
408 }
409 return (FailureReason) sidRequestEnumProperty(Property.P_FAILURE_REASON);
410 }
411 /** DEPRECATED: subject line */
412 public String getSubject() {
413 synchronized(this) {
414 if ((mSidCached & 0x20) != 0)
415 return mSubject;
416 }
417 return sidRequestStringProperty(Property.P_SUBJECT);
418 }
419 /** timestamp of creation */
420 public int getTimestamp() {
421 synchronized(this) {
422 if ((mSidCached & 0x40) != 0)
423 return mTimestamp;
424 }
425 return sidRequestUintProperty(Property.P_TIMESTAMP);
426 }
427 /** duration in seconds */
428 public int getDuration() {
429 synchronized(this) {
430 if ((mSidCached & 0x80) != 0)
431 return mDuration;
432 }
433 return sidRequestUintProperty(Property.P_DURATION);
434 }
435 /** max allowed duration in seconds */
436 public int getAllowedDuration() {
437 synchronized(this) {
438 if ((mSidCached & 0x100) != 0)
439 return mAllowedDuration;
440 }
441 return sidRequestUintProperty(Property.P_ALLOWED_DURATION);
442 }
443 /** VM playback progress in seconds */
444 public int getPlaybackProgress() {
445 synchronized(this) {
446 if ((mSidCached & 0x200) != 0)
447 return mPlaybackProgress;
448 }
449 return sidRequestUintProperty(Property.P_PLAYBACK_PROGRESS);
450 }
451 /** CONVERSATION_ID of corresponding conversation */
452 public Conversation getConversation() {
453 synchronized(this) {
454 if ((mSidCached & 0x400) != 0)
455 return mConversation;
456 }
457 return (Conversation) sidRequestObjectProperty(Property.P_CONVERSATION);
458 }
459 /** GUID of the message that the VM is tied to */
460 public byte[] getChatMsgGuid() {
461 synchronized(this) {
462 if ((mSidCached & 0x800) != 0)
463 return mChatMsgGuid;
464 }
465 return sidRequestBinaryProperty(Property.P_CHAT_MSG_GUID);
466 }
467 public String sidGetStringProperty(final PropertyEnumConverting prop) {
468 switch(prop.getId()) {
469 case 101:
470 return mPartnerHandle;
471 case 102:
472 return mPartnerDisplayName;
473 case 105:
474 return mSubject;
475 }
476 return "";
477 }
478 public SidObject sidGetObjectProperty(final PropertyEnumConverting prop) {
479 assert(prop.getId() == 830);
480 return mConversation;
481 }
482 public int sidGetIntProperty(final PropertyEnumConverting prop) {
483 switch(prop.getId()) {
484 case 106:
485 return mTimestamp;
486 case 107:
487 return mDuration;
488 case 108:
489 return mAllowedDuration;
490 case 109:
491 return mPlaybackProgress;
492 }
493 return 0;
494 }
495 public EnumConverting sidGetEnumProperty(final PropertyEnumConverting prop) {
496 switch(prop.getId()) {
497 case 100:
498 return mType;
499 case 103:
500 return mStatus;
501 case 104:
502 return mFailureReason;
503 }
504 return null;
505 }
506 public byte[] sidGetBinaryProperty(final PropertyEnumConverting prop) {
507 assert(prop.getId() == 831);
508 return mChatMsgGuid;
509 }
510 public String getPropertyAsString(final int prop) {
511 switch (prop) {
512 case 100: return getType().toString();
513 case 101: return getPartnerHandle();
514 case 102: return getPartnerDisplayName();
515 case 103: return getStatus().toString();
516 case 104: return getFailureReason().toString();
517 case 105: return getSubject();
518 case 106: return Integer.toString(getTimestamp());
519 case 107: return Integer.toString(getDuration());
520 case 108: return Integer.toString(getAllowedDuration());
521 case 109: return Integer.toString(getPlaybackProgress());
522 case 830: return Integer.toString(getConversation().getOid());
523 case 831: return "<binary>";
524 }
525 return "<unkown>";
526 }
527 public String getPropertyAsString(final Property prop) {
528 return getPropertyAsString(prop.getId());
529 }
530 protected void sidOnChangedProperty(final int propertyId, final int value, final String svalue) {
531 final Property property = Property.get(propertyId);
532 if (property == Property.P_UNKNOWN) return;
533 final int idx = property.getIdx();
534 if (idx != 0) {
535 int bit = 1<<((idx-1)%32);
536 synchronized (this) {
537 mSidCached|=bit;
538 switch (propertyId) {
539 case 100: mType = Type.get(value); break;
540 case 101:
541 if (svalue != null) mPartnerHandle = svalue;
542 else mSidCached &=~bit;
543 break;
544 case 102:
545 if (svalue != null) mPartnerDisplayName = svalue;
546 else mSidCached &=~bit;
547 break;
548 case 103: mStatus = Status.get(value); break;
549 case 104: mFailureReason = FailureReason.get(value); break;
550 case 105:
551 if (svalue != null) mSubject = svalue;
552 else mSidCached &=~bit;
553 break;
554 case 106: mTimestamp = value; break;
555 case 107: mDuration = value; break;
556 case 108: mAllowedDuration = value; break;
557 case 109: mPlaybackProgress = value; break;
558 default: mSidCached|=bit; break;
559 }
560 }
561 }
562 VoicemailListener listener = ((Skype) mSidRoot).getVoicemailListener();
563 if (listener != null)
564 listener.onPropertyChange(this, property, value, svalue);
565 }
566 public void sidSetProperty(final PropertyEnumConverting prop, final String newValue) {
567 final int propId = prop.getId();
568 switch(propId) {
569 case 101:
570 mSidCached |= 0x2;
571 mPartnerHandle= newValue;
572 break;
573 case 102:
574 mSidCached |= 0x4;
575 mPartnerDisplayName= newValue;
576 break;
577 case 105:
578 mSidCached |= 0x20;
579 mSubject= newValue;
580 break;
581 }
582 }
583 public void sidSetProperty(final PropertyEnumConverting prop, final SidObject newValue) {
584 final int propId = prop.getId();
585 assert(propId == 830);
586 mSidCached |= 0x400;
587 mConversation= (Conversation) newValue;
588 }
589 public void sidSetProperty(final PropertyEnumConverting prop, final int newValue) {
590 final int propId = prop.getId();
591 switch(propId) {
592 case 100:
593 mSidCached |= 0x1;
594 mType= Type.get(newValue);
595 break;
596 case 103:
597 mSidCached |= 0x8;
598 mStatus= Status.get(newValue);
599 break;
600 case 104:
601 mSidCached |= 0x10;
602 mFailureReason= FailureReason.get(newValue);
603 break;
604 case 106:
605 mSidCached |= 0x40;
606 mTimestamp= newValue;
607 break;
608 case 107:
609 mSidCached |= 0x80;
610 mDuration= newValue;
611 break;
612 case 108:
613 mSidCached |= 0x100; mAllowedDuration= newValue;
614 break;
615 case 109:
616 mSidCached |= 0x200;
617 mPlaybackProgress= newValue;
618 break;
619 }
620 }
621 public void sidSetProperty(final PropertyEnumConverting prop, final byte[] newValue) {
622 final int propId = prop.getId();
623 assert(propId == 831);
624 mSidCached |= 0x800;
625 mChatMsgGuid= newValue;
626 }
627 public Type mType;
628 public String mPartnerHandle;
629 public String mPartnerDisplayName;
630 public Status mStatus;
631 public FailureReason mFailureReason;
632 public String mSubject;
633 public int mTimestamp;
634 public int mDuration;
635 public int mAllowedDuration;
636 public int mPlaybackProgress;
637 public Conversation mConversation;
638 public byte[] mChatMsgGuid;
639 public int moduleId() {
640 return 7;
641 }
642
643 public Voicemail(final int oid, final SidRoot root) {
644 super(oid, root, 12);
645 }
646 }