Package phones ::
Module com_samsungscha950
|
|
1
2
3
4
5
6
7
8
9
10 """Communicate with the Samsung SCH-A950 Phone"""
11
12
13 import calendar
14 import datetime
15 import sha
16 import time
17
18 import wx
19
20
21 import bpcalendar
22 import call_history
23 import common
24 import commport
25 import com_brew
26 import com_phone
27 import datetime
28 import fileinfo
29 import memo
30 import nameparser
31 import prototypes
32 import pubsub
33 import p_samsungscha950
34 import sqlite2_file
35 import sms
36 import helpids
37
38 -class Phone(com_phone.Phone, com_brew.BrewProtocol):
39 desc='SCH-A950'
40 helpid=helpids.ID_PHONE_SAMSUNGSCHA950
41 protocolclass=p_samsungscha950
42 serialsname='scha950'
43
44 ringtone_noring_range='range_tones_preloaded_el_15'
45 ringtone_default_range='range_tones_preloaded_el_01'
46 builtin_ringtones={
47 'VZW Default Tone': ringtone_default_range,
48 'Melody 1': 'range_tones_preloaded_el_02',
49 'Melody 2': 'range_tones_preloaded_el_03',
50 'Bell 1': 'range_tones_preloaded_el_04',
51 'Bell 2': 'range_tones_preloaded_el_05',
52 'Beep Once': 'range_tones_preloaded_el_06',
53 'No Ring': ringtone_noring_range,
54 }
55 builtin_sounds={
56 'Birthday': 'range_sound_preloaded_el_birthday',
57 'Crowd Roar': 'range_sound_preloaded_el_crowed_roar',
58 'Train': 'range_sound_preloaded_el_train',
59 'Rainforest': 'range_sound_preloaded_el_rainforest',
60 'Clapping': 'range_sound_preloaded_el_clapping',
61
62 'Sound Beep Once': 'range_sound_preloaded_el_beep_once',
63 'Sound No Ring': 'range_sound_preloaded_el_no_rings',
64 }
65 builtin_wallpapers={
66 'Wallpaper 1': 'range_f_wallpaper_preloaded_el_01',
67 'Wallpaper 2': 'range_f_wallpaper_preloaded_el_02',
68 'Wallpaper 3': 'range_f_wallpaper_preloaded_el_03',
69 'Wallpaper 4': 'range_f_wallpaper_preloaded_el_04',
70 'Wallpaper 5': 'range_f_wallpaper_preloaded_el_05',
71 'Wallpaper 6': 'range_f_wallpaper_preloaded_el_06',
72 'Wallpaper 7': 'range_f_wallpaper_preloaded_el_07',
73 'Wallpaper 8': 'range_f_wallpaper_preloaded_el_08',
74 'Wallpaper 9': 'range_f_wallpaper_preloaded_el_09',
75 }
76 builtin_groups={
77 1: 'Business',
78 2: 'Colleague',
79 3: 'Family',
80 4: 'Friends'
81 }
82
83 - def __init__(self, logtarget, commport):
91
92
100
103
129
228
242
244
245 for _key,_value in self.builtin_ringtones.items():
246 if range==_value:
247 return _key
248
249 for _key,_value in self.builtin_sounds.items():
250 if range==_value:
251 return _key
252
253 if not fundamentals.has_key('ringtone-range'):
254 self._read_ringtone_range(fundamentals)
255 for _key,_value in fundamentals['ringtone-range'].items():
256 if _value==range:
257 return _key
258
260 """Gets information fundamental to interopating with the phone and UI.
261
262 Currently this is:
263
264 - 'uniqueserial' a unique serial number representing the phone
265 - 'groups' the phonebook groups
266 - 'wallpaper-index' map index numbers to names
267 - 'ringtone-index' map index numbers to ringtone names
268
269 This method is called before we read the phonebook data or before we
270 write phonebook data.
271 """
272
273
274 self.log("Retrieving fundamental phone information")
275 self.log("Phone serial number")
276 results['uniqueserial']=sha.new(self.get_esn()).hexdigest()
277 results['groups']=self.get_groups()
278 results['ringtone-index']=self.get_ringtone_index()
279 results['wallpaper-index']=self.get_wallpaper_index()
280 return results
281
282
296
301
302 - def _get_del_new_list(self, index_key, media_key, merge, fundamentals,
303 ignored_origins=()):
304 """Return a list of media being deleted and being added"""
305 _index=fundamentals.get(index_key, {})
306 _media=fundamentals.get(media_key, {})
307 _index_file_list=[_entry['name'] for _,_entry in _index.items() \
308 if _entry.has_key('filename') and \
309 _entry.get('origin', None) not in ignored_origins]
310 _bp_file_list=[_entry['name'] for _,_entry in _media.items() \
311 if _entry.get('origin', None) not in ignored_origins]
312 if merge:
313
314 _del_list=[]
315 _new_list=_bp_file_list
316 else:
317
318 _del_list=[x for x in _index_file_list if x not in _bp_file_list]
319 _new_list=_bp_file_list
320 return _del_list, _new_list
321
323 for _key,_entry in index_dict.items():
324 if _entry.get('name', None)==name:
325 if item_key:
326
327 return _entry.get(item_key, None)
328 else:
329
330 return _key
331
332 - def _del_files(self, index_key, _del_list, fundamentals):
333 """Delete specified media files, need to be in OBEX mode"""
334 _index=fundamentals.get(index_key, {})
335 for _file in _del_list:
336 _file_name=self._item_from_index(_file, 'filename', _index)
337 if _file_name:
338 try:
339 self.rmfile(_file_name)
340 except Exception, e:
341 self.log('Failed to delete file %s: %s'%(_file_name, str(e)))
342
343 - def _replace_files(self, index_key, media_key, new_list, fundamentals):
344 """Replace existing files with new contents using BREW"""
345 _index=fundamentals.get(index_key, {})
346 _media=fundamentals.get(media_key, {})
347 for _file in new_list:
348 _data=self._item_from_index(_file, 'data', _media)
349 if not _data:
350 self.log('Failed to write file %s due to no data'%_file)
351 continue
352 _file_name=self._item_from_index(_file, 'filename', _index)
353 if _file_name:
354
355 _stat=self.statfile(_file_name)
356 if _stat and _stat['size']!=len(_data):
357
358 try:
359 self.writefile(_file_name, _data)
360 except:
361 self.log('Failed to write BREW file '+_file_name)
362 if __debug__:
363 raise
364
365 - def _add_files(self, index_key, media_key,
366 new_list, fundamentals):
367 """Add new file using BREW"""
368 _index=fundamentals.get(index_key, {})
369 _media=fundamentals.get(media_key, {})
370 _res=[]
371 for _file in new_list:
372 _data=self._item_from_index(_file, 'data', _media)
373 if not _data:
374 self.log('Failed to write file %s due to no data'%_file)
375 continue
376 if self._item_from_index(_file, None, _index) is None:
377
378 _origin=self._item_from_index(_file, 'origin', _media)
379 if _origin=='ringers':
380 _path=self.protocolclass.RT_PATH
381 elif _origin=='sounds':
382 _path=self.protocolclass.SND_PATH
383 elif _origin=='images':
384 _path=self.protocolclass.PIC_PATH
385 else:
386 selg.log('File %s has unknown origin, skip!'%_file)
387 continue
388 _file_name=_path+'/'+_file
389 try:
390 self.writefile(_file_name, _data)
391 _res.append(_file)
392 except:
393 self.log('Failed to write file '+_file_name)
394 if __debug__:
395 raise
396 return _res
397
420
421
423 """Save ringtones to the phone"""
424 self.log('Writing ringtones to the phone')
425 try:
426 _del_list, _new_list=self._get_del_new_list('ringtone-index',
427 'ringtone',
428 merge,
429 fundamentals)
430 if __debug__:
431 self.log('Delete list: '+','.join(_del_list))
432 self.log('New list: '+','.join(_new_list))
433 self._replace_files('ringtone-index', 'ringtone',
434 _new_list, fundamentals)
435 self._del_files('ringtone-index',
436 _del_list, fundamentals)
437 self._add_files('ringtone-index', 'ringtone',
438 _new_list, fundamentals)
439 self._update_media_index(self.protocolclass.WRingtoneIndexFile,
440 self.protocolclass.WRingtoneIndexEntry,
441 [self.protocolclass.RT_PATH,
442 self.protocolclass.RT_PATH2],
443 self.protocolclass.RT_EXCLUDED_FILES,
444 self.protocolclass.RT_INDEX_FILE_NAME)
445 self._update_media_index(self.protocolclass.WSoundsIndexFile,
446 self.protocolclass.WSoundsIndexEntry,
447 [self.protocolclass.SND_PATH,
448 self.protocolclass.SND_PATH2],
449 self.protocolclass.SND_EXCLUDED_FILES,
450 self.protocolclass.SND_INDEX_FILE_NAME)
451 fundamentals['rebootphone']=True
452 except:
453 if __debug__:
454 raise
455 return fundamentals
456
457
462
464
465 """Save ringtones to the phone"""
466 self.log('Writing wallpapers to the phone')
467 try:
468 _del_list, _new_list=self._get_del_new_list('wallpaper-index',
469 'wallpapers',
470 merge,
471 fundamentals)
472 if __debug__:
473 self.log('Delete list: '+','.join(_del_list))
474 self.log('New list: '+','.join(_new_list))
475 self._replace_files('wallpaper-index', 'wallpapers',
476 _new_list, fundamentals)
477 self._del_files('wallpaper-index',
478 _del_list, fundamentals)
479 self._add_files('wallpaper-index', 'wallpapers',
480 _new_list, fundamentals)
481 self._update_media_index(self.protocolclass.WPictureIndexFile,
482 self.protocolclass.WPictureIndexEntry,
483 [self.protocolclass.PIC_PATH,
484 self.protocolclass.PIC_PATH2],
485 self.protocolclass.PIC_EXCLUDED_FILES,
486 self.protocolclass.PIC_INDEX_FILE_NAME)
487 fundamentals['rebootphone']=True
488 except:
489 if __debug__:
490 raise
491 return fundamentals
492
493
498
512
514 self.log('Deleting existing calendar entries')
515 _cal_index=self._read_calendar_index()
516 for _idx in range(_cal_index.numofevents):
517 _cal_file_name='%s%04d'%(self.protocolclass.CAL_FILE_NAME_PREFIX,
518 _cal_index.events[_idx].index)
519 try:
520 self.rmfile(_cal_file_name)
521 except:
522 self.log('Failed to delete file: '+_cal_file_name)
523 return _cal_index.next_index
524
547
549 _cal_index=self._read_calendar_index()
550
551 for _idx in range(_cal_index.numofevents):
552 _cal_index.events[_idx].index=0
553 for _idx in range(_cal_index.numofactiveevents):
554 _cal_index.activeevents[_idx].index=0
555
556 _old_next_index=_cal_index.next_index
557 _num_entries=next_index-_old_next_index
558 _cal_index.next_index=next_index
559 _cal_index.numofevents=_num_entries
560 _cal_index.numofactiveevents=_num_entries
561 _cnt=0
562 for _idx in range(_old_next_index, next_index):
563 _cal_index.events[_cnt].index=_idx
564 _cal_index.activeevents[_cnt].index=_idx
565 _cnt+=1
566 self.writeobject(self.protocolclass.CAL_INDEX_FILE_NAME,
567 _cal_index,
568 'Writing Calendar Index File')
569
578
579
595
597 self.log('Deleting existing memo entries')
598 _file_index=self._read_calendar_index()
599 for _idx in range(_file_index.numofnotes):
600 _file_name='%s%04d'%(self.protocolclass.NP_FILE_NAME_PREFIX,
601 _file_index.notes[_idx].index)
602 try:
603 self.rmfile(_file_name)
604 except:
605 self.log('Failed to delete file: '+_file_name)
606 return _file_index.next_index
607
635
637 _file_index=self._read_calendar_index()
638
639 for _idx in range(_file_index.numofnotes):
640 _file_index.notes[_idx].index=0
641
642 _old_next_index=_file_index.next_index
643 _num_entries=next_index-_old_next_index
644 _file_index.next_index=next_index
645 _file_index.numofnotes=_num_entries
646 _cnt=0
647 for _idx in range(_old_next_index, next_index):
648 _file_index.notes[_cnt].index=_idx
649 _cnt+=1
650 self.writeobject(self.protocolclass.CAL_INDEX_FILE_NAME,
651 _file_index,
652 logtitle='Writing calendar/memo file index')
653
654 - def savememo(self, fundamentals, merge):
661
662
663 my_model='SCH-A950/DM'
664 my_manufacturer='SAMSUNG'
665 detected_model='A950'
694 @classmethod
695 - def detectphone(_, coms, likely_ports, res, _module, _log):
696 if not likely_ports:
697
698 return None
699 for port in likely_ports:
700 if not res.has_key(port):
701 res[port]={ 'mode_modem': None, 'mode_brew': None,
702 'manufacturer': None, 'model': None,
703 'firmware_version': None, 'esn': None,
704 'firmwareresponse': None }
705 try:
706 if res[port]['mode_brew']==False or \
707 res[port]['model']:
708
709
710 continue
711 p=_module.Phone(_log, commport.CommConnection(_log, port, timeout=1))
712 if res[port]['mode_brew'] is None:
713 res[port]['mode_brew']=p.is_mode_brew()
714 if res[port]['mode_brew']:
715 p.check_my_phone(res[port])
716 p.comm.close()
717 except:
718 if __debug__:
719 raise
720
721
723
724 for _key in ('ringtone-range', 'wallpaper-range'):
725 if fundamentals.has_key(_key):
726 del fundamentals[_key]
727
745
747 self.log('Reading phonebook contacts')
748 _file_cnt=0
749 _res={}
750 while True:
751 _file_name='%s%04d'%(self.protocolclass.PB_ENTRY_FILE_PREFIX,
752 _file_cnt)
753 if self.exists(_file_name):
754 self._extract_entries(_file_name, _res, fundamentals)
755 _file_cnt+=1
756 else:
757 break
758 fundamentals['phonebook']=_res
759 fundamentals['categories']=[x['name'] for _,x in \
760 fundamentals.get('groups', {}).items()]
761 self._del_private_dicts(fundamentals)
762 return fundamentals
763
769
792
794
795 _wp_range=fundamentals.get('wallpaper-range', {})
796 if _wp_range.has_key(wp):
797
798 return
799
800 _wp_index=fundamentals.get('wallpaper-index', {})
801
802 _filename=self._get_wp_filename(wp, _wp_index)
803 if not _filename:
804
805 return
806
807 _newfilename=self._rescale_and_cache(wp, _filename, idx, fundamentals)
808 if _newfilename:
809
810 _wp_range[wp]='/ff/'+_newfilename
811 fundamentals['wallpaper-range']=_wp_range
812
814
815 return fundamentals.get('wallpaper-range', {}).get(wallpaper, None)
816
818 self.log('Writing phonebook contacts')
819 self._read_ringtone_range(fundamentals)
820 _pb_dict=fundamentals.get('phonebook', {})
821
822 _pb_list=[(nameparser.getfullname(_entry['names'][0]), _key) \
823 for _key,_entry in _pb_dict.items()]
824 _pb_list.sort()
825 _req=self.protocolclass.ss_pb_clear_req()
826 _rp=self.sendbrewcommand(_req, self.protocolclass.ss_pb_clear_resp)
827 if _rp.flg:
828 self.log('Failed to clear phonebook')
829 self._del_private_dicts(fundamentals)
830 return fundamentals
831 _req=self.protocolclass.ss_pb_write_req()
832 _total_cnt=len(_pb_list)
833 _cnt=1
834 for _name,_key in _pb_list:
835 try:
836 _entry=_pb_dict[_key]
837
838 _wp=_entry.get('wallpapers', [{}])[0].get('wallpaper', None)
839 if _wp:
840 self._add_wp_cache(_wp, _cnt, fundamentals)
841
842 _pbentry=self.pbentryclass(self, _entry, fundamentals)
843 _req.entry=_pbentry.pb
844 _cnt+=1
845 self.progress(_cnt, _total_cnt,
846 'Writing entry" %s'%_req.entry.name)
847 _resp=self.sendbrewcommand(_req,
848 self.protocolclass.ss_pb_write_resp)
849 except:
850 self.log('Failed to write entry')
851 if __debug__:
852 raise
853 fundamentals['rebootphone']=True
854 self._del_private_dicts(fundamentals)
855 return fundamentals
856
857
874 - def _get_ch(self, call_list, folder, res):
896
897 - def getcallhistory(self, fundamentals):
898
899 res={}
900 _incoming_list, _outgoing_list, _missed_list=self._get_ch_index()
901 self._get_ch(_incoming_list,
902 call_history.CallHistoryEntry.Folder_Incoming, res)
903 self._get_ch(_outgoing_list,
904 call_history.CallHistoryEntry.Folder_Outgoing, res)
905 self._get_ch(_missed_list,
906 call_history.CallHistoryEntry.Folder_Missed, res)
907 fundamentals['call_history']=res
908
909
920
925
934
957
967
968 - def _read_sms(self, filename, res, fundamentals):
981
982 - def getsms(self, fundamentals):
994
995
996 -class CalendarEntry(object):
997 """Transient class to handle calendar data being sent to, retrieved from
998 the phone.
999 """
1000
1001 REP_NONE=0
1002 REP_ONCE=0
1003 REP_DAILY=2
1004 REP_WEEKLY=5
1005 REP_MONTHLY=6
1006 REP_YEARLY=7
1007
1008 ALARM_ONTIME=0
1009 ALARM_5M=1
1010 ALARM_10M=2
1011 ALARM_15M=3
1012 ALARM_30M=4
1013 ALARM_1HR=5
1014 ALARM_3HR=6
1015 ALARM_5HR=7
1016 ALARM_1D=8
1017
1018 ALERT_TONE=0
1019 ALERT_VIBRATE=1
1020 ALERT_LIGHT=2
1021
1022 TZ_EST=0
1023 TZ_EDT=1
1024 TZ_CST=2
1025 TZ_CDT=3
1026 TZ_MST=4
1027 TZ_MDT=5
1028 TZ_PST=6
1029 TZ_PDT=7
1030 TZ_AKST=8
1031 TZ_AKDT=9
1032 TZ_HAST=10
1033 TZ_HADT=11
1034 TZ_GMT=12
1035 - def __init__(self, phone, value, fundamentals):
1036 self.phone=phone
1037 self.fundamentals=fundamentals
1038 self.cal=phone.protocolclass.CalEntry()
1039 if isinstance(value, bpcalendar.CalendarEntry):
1040 self._build(value)
1041 elif isinstance(value, prototypes.buffer):
1042 self.cal.readfrombuffer(value)
1043 else:
1044 raise TypeError('Expecting type bpcalendar.CalendarEntry or prototypes.buffer')
1045
1046 - def writetobuffer(self, buf, logtitle=None):
1047 self.cal.writetobuffer(buf, logtitle=logtitle)
1048
1049
1050 _build_repeat_dict={
1051 bpcalendar.RepeatEntry.daily: REP_DAILY,
1052 bpcalendar.RepeatEntry.weekly: REP_WEEKLY,
1053 bpcalendar.RepeatEntry.monthly: REP_MONTHLY,
1054 bpcalendar.RepeatEntry.yearly: REP_YEARLY,
1055 }
1056 _build_alarm_dict={
1057 0: ALARM_ONTIME,
1058 5: ALARM_5M,
1059 10: ALARM_10M,
1060 15: ALARM_15M,
1061 30: ALARM_30M,
1062 60: ALARM_1HR,
1063 180: ALARM_3HR,
1064 300: ALARM_5HR,
1065 1440: ALARM_1D,
1066 }
1067 _build_tz_dict={
1068 0: TZ_GMT,
1069 18000: TZ_EST,
1070 21600: TZ_CST,
1071 25200: TZ_MST,
1072 28800: TZ_PST,
1073 32400: TZ_AKST,
1074 36000: TZ_HAST,
1075 }
1076 - def _build_duration(self, entry):
1077 return (datetime.datetime(*entry.end)-\
1078 datetime.datetime(*entry.start)).seconds
1079 - def _build_repeat(self, entry):
1080 rep=entry.repeat
1081 if not rep:
1082 return self.REP_ONCE
1083 return self._build_repeat_dict.get(rep.repeat_type, self.REP_ONCE)
1084 - def _build_alarm(self, entry):
1085 _keys=self._build_alarm_dict.keys()
1086 _keys.sort()
1087 _alarm=entry.alarm
1088 for k in _keys:
1089 if _alarm<=k:
1090 return self._build_alarm_dict[k]
1091 return self.ALARM_ONTIME
1092 - def _build_alert(self, entry):
1093 if entry.vibrate:
1094 return self.ALERT_VIBRATE
1095 return self.ALERT_TONE
1096 _tz_code=None
1097 - def _build_tz(self):
1105
1106 - def _build(self, entry):
1107
1108 self.cal.titlelen=len(entry.desc_loc)
1109 self.cal.title=entry.desc_loc
1110 self.cal.start=entry.start
1111 self.cal.exptime=entry.end[3:5]
1112 self.cal.repeat=self._build_repeat(entry)
1113 self.cal.alarm=self._build_alarm(entry)
1114 self.cal.alert=self._build_alert(entry)
1115 self.cal.duration=self._build_duration(entry)
1116 self.cal.timezone=self._build_tz()
1117 _now=self.phone._time_now()
1118 self.cal.creationtime=_now
1119 self.cal.modifiedtime=_now
1120 _ringtone=self.phone.get_ringtone_range(entry.ringtone,
1121 self.fundamentals)
1122 self.cal.ringtonelen=len(_ringtone)
1123 self.cal.ringtone=_ringtone
1124
1125
1127 return (datetime.datetime(*self.cal.start)+\
1128 datetime.timedelta(seconds=self.cal.duration)).timetuple()[:5]
1130 for _value,_code in self._build_alarm_dict.items():
1131 if self.cal.alarm==_code:
1132 return _value
1134 if self.cal.repeat==self.REP_ONCE:
1135 return None
1136 _rep_type=None
1137 for _type, _code in self._build_repeat_dict.items():
1138 if self.cal.repeat==_code:
1139 _rep_type=_type
1140 break
1141 if not _rep_type:
1142 return None
1143 _rep=bpcalendar.RepeatEntry(_rep_type)
1144 if _rep_type==_rep.daily:
1145 _rep.interval=1
1146 elif _rep_type==_rep.weekly:
1147 _rep.interval=1
1148 elif _rep_type==_rep.monthly:
1149 _rep.interval2=1
1150 _rep.dow=0
1151 return _rep
1152
1153 - def getvalue(self):
1168
1169
1170 -class PBEntry(object):
1171
1172 - def __init__(self, phone, data, fundamentals):
1173 self.phone=phone
1174 self.fundamentals=fundamentals
1175 if isinstance(data, phone.protocolclass.PBEntry):
1176 self.pb=data
1177 elif isinstance(data, dict):
1178
1179 self.pb=phone.protocolclass.ss_pb_entry()
1180 self._build(data)
1181 else:
1182 raise TypeError('Should be PBEntry or phone dict')
1183
1184 - def writetobuffer(self, buf, logtitle=None):
1185 self.pb.writetobuffer(buf, logtitle=logtitle)
1186
1187
1188 _pb_type_dict={
1189 'home': 'home',
1190 'office': 'work',
1191 'cell': 'cell',
1192 'fax': 'fax',
1193 }
1194 - def _build_number(self, number, ringtone, primary):
1195
1196 _num_type=self._pb_type_dict.get(number['type'], None)
1197 if not _num_type:
1198
1199 return
1200
1201 if _num_type=='cell' and self.pb.cell.number:
1202 _num_type='cell2'
1203
1204 _entry=self.phone.protocolclass.ss_number_entry()
1205 _entry.number=number['number']
1206 _sd=number.get('speeddial', None)
1207 if ringtone:
1208 _rt=self.phone.get_ringtone_range(ringtone, self.fundamentals)
1209 else:
1210 _rt=None
1211 if _sd is not None:
1212 _entry.speeddial=_sd
1213 if _rt is not None:
1214 _entry.ringtone=_rt
1215 if primary:
1216 _entry.primary=1
1217
1218 setattr(self.pb, _num_type, _entry)
1219
1220 - def _build_email(self, emails):
1221
1222 if len(emails) and emails[0].get('email', None):
1223
1224 self.pb.email=emails[0]['email']
1225 if len(emails)>1 and emails[1].get('email', None):
1226
1227 self.pb.email2=emails[1]['email']
1228
1229 - def _build_group(self, cat):
1230
1231 if not cat:
1232 return
1233 _cat_list=self.fundamentals.get('groups', {})
1234 for _key,_cat in _cat_list.items():
1235 if _key and _cat.get('name', None)==cat:
1236 self.pb.group=_key
1237 break
1238
1239 - def _build_wallpaper(self, wallpaper):
1240
1241 if not wallpaper:
1242 return
1243 _wp=self.phone.get_wallpaper_range(wallpaper, self.fundamentals)
1244 if _wp:
1245 self.pb.wallpaper=_wp
1246
1247 - def _build(self, entry):
1248
1249 self.pb.name=nameparser.getfullname(entry['names'][0])
1250
1251 _ringtone=entry.get('ringtones', [{}])[0].get('ringtone', None)
1252
1253 _primary=True
1254 for _number in entry.get('numbers', []):
1255 self._build_number(_number, _ringtone, _primary)
1256 _primary=False
1257
1258 self._build_email(entry.get('emails', []))
1259
1260 self._build_group(entry.get('categories', [{}])[0].get('category', None))
1261
1262 self._build_wallpaper(entry.get('wallpapers', [{}])[0].get('wallpaper', None))
1263
1264
1266
1267 if self.pb.has_email:
1268 entry['emails']=[{ 'email': self.pb.email }]
1269 if self.pb.has_email2:
1270 entry.setdefault('emails', []).append({ 'email': self.pb.email2 })
1271 _number_type_dict={
1272 'cell': (Phone.protocolclass.PB_FLG_CELL, 'cell'),
1273 'home': (Phone.protocolclass.PB_FLG_HOME, 'home'),
1274 'work': (Phone.protocolclass.PB_FLG_WORK, 'office'),
1275 'fax': (Phone.protocolclass.PB_FLG_FAX, 'fax'),
1276 'cell2': (Phone.protocolclass.PB_FLG_CELL2, 'cell'),
1277 }
1279
1280 entry['numbers']=[]
1281 for _key,_info_list in self._number_type_dict.items():
1282 if self.pb.info&_info_list[0]:
1283 _num_entry=getattr(self.pb, _key)
1284 _number={ 'number': _num_entry.number,
1285 'type': _info_list[1] }
1286 if _num_entry.has_speeddial:
1287 _number['speeddial']=_num_entry.speeddial
1288 if _num_entry.has_ringtone and \
1289 not entry.has_key('ringtones'):
1290 _ringtone=self.phone.ringtone_name_from_range(
1291 _num_entry.ringtone, self.fundamentals)
1292 if _ringtone:
1293 entry['ringtones']=[{ 'ringtone': _ringtone,
1294 'use': 'call' }]
1295 if _num_entry.is_primary:
1296
1297 entry['numbers']=[_number]+entry['numbers']
1298 else:
1299 entry['numbers'].append(_number)
1301 if not self.pb.has_group:
1302
1303 return
1304 _groups=self.fundamentals.get('groups', {})
1305 if _groups.has_key(self.pb.group):
1306 entry['categories']=[{ 'category': _groups[self.pb.group]['name'] }]
1308 if not self.pb.has_wallpaper:
1309 return
1310 _idx=self.pb.wallpaper.rfind('$')+1
1311 _wp=self.pb.wallpaper[_idx:]
1312 entry['wallpapers']=[{ 'wallpaper': _wp,
1313 'use': 'call' }]
1314 - def getvalue(self):
1315 _entry={}
1316 _p_class=self.phone.protocolclass
1317 _entry['names']=[{ 'full': self.pb.name }]
1318 self._extract_emails(_entry, _p_class)
1319 self._extract_numbers(_entry, _p_class)
1320 self._extract_group(_entry, _p_class)
1321 self._extract_wallpaper(_entry, _p_class)
1322 return _entry
1323
1324
1325 parentprofile=com_phone.Profile
1327 serialsname=Phone.serialsname
1328 WALLPAPER_WIDTH=176
1329 WALLPAPER_HEIGHT=220
1330
1331 autodetect_delay=3
1332 usbids=( ( 0x04e8, 0x6640, 2),)
1333 deviceclasses=("serial",)
1334 BP_Calendar_Version=3
1335
1336 phone_manufacturer=Phone.my_manufacturer
1337 phone_model=Phone.my_model
1338
1339 RINGTONE_LIMITS= {
1340 'MAXSIZE': 100000
1341 }
1342 WALLPAPER_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789 ._:"
1343 RINGTONE_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789 ._:"
1344
1347
1348 _supportedsyncs=(
1349 ('phonebook', 'read', None),
1350 ('phonebook', 'write', 'OVERWRITE'),
1351 ('calendar', 'read', None),
1352 ('calendar', 'write', 'OVERWRITE'),
1353 ('ringtone', 'read', None),
1354 ('ringtone', 'write', 'MERGE'),
1355 ('wallpaper', 'read', None),
1356 ('wallpaper', 'write', None),
1357 ('memo', 'read', None),
1358 ('memo', 'write', 'OVERWRITE'),
1359 ('call_history', 'read', None),
1360 ('sms', 'read', None),
1361 )
1362
1363 - def QueryAudio(self, origin, currentextension, afi):
1364 _max_size=self.RINGTONE_LIMITS['MAXSIZE']
1365 setattr(afi, 'MAXSIZE', _max_size)
1366
1367 if afi.format in ("MIDI", "QCP", "PMD"):
1368 return currentextension, afi
1369
1370 if afi.format=="MP3":
1371 if afi.channels==1 and 8<=afi.bitrate<=64 and 16000<=afi.samplerate<=22050:
1372 return currentextension, afi
1373
1374 return ("mp3", fileinfo.AudioFileInfo(afi, **{'format': 'MP3',
1375 'channels': 2,
1376 'bitrate': 48,
1377 'samplerate': 44100,
1378 'MAXSIZE': _max_size }))
1379
1380
1381 imageorigins={}
1382 imageorigins.update(common.getkv(parentprofile.stockimageorigins, "images"))
1385
1386
1387 imagetargets={}
1388 imagetargets.update(common.getkv(parentprofile.stockimagetargets, "wallpaper",
1389 {'width': 176, 'height': 186, 'format': "JPEG"}))
1390 imagetargets.update(common.getkv(parentprofile.stockimagetargets, "outsidelcd",
1391 {'width': 128, 'height': 96, 'format': "JPEG"}))
1392 imagetargets.update(common.getkv(parentprofile.stockimagetargets, "fullscreen",
1393 {'width': 176, 'height': 220, 'format': "JPEG"}))
1396
1399
1400 field_color_data={
1401 'phonebook': {
1402 'name': {
1403 'first': 1, 'middle': 1, 'last': 1, 'full': 1,
1404 'nickname': 0, 'details': 1 },
1405 'number': {
1406 'type': 5, 'speeddial': 5, 'number': 5,
1407 'details': 5,
1408 'ringtone': False, 'wallpaper': False },
1409 'email': 2,
1410 'email_details': {
1411 'emailspeeddial': False, 'emailringtone': False,
1412 'emailwallpaper': False },
1413 'address': {
1414 'type': 0, 'company': 0, 'street': 0, 'street2': 0,
1415 'city': 0, 'state': 0, 'postalcode': 0, 'country': 0,
1416 'details': 0 },
1417 'url': 0,
1418 'memo': 0,
1419 'category': 1,
1420 'wallpaper': 1,
1421 'ringtone': 1,
1422 'storage': 0,
1423 },
1424 'calendar': {
1425 'description': True, 'location': True, 'allday': False,
1426 'start': True, 'end': True, 'priority': False,
1427 'alarm': True, 'vibrate': True,
1428 'repeat': True,
1429 'memo': False,
1430 'category': False,
1431 'wallpaper': False,
1432 'ringtone': True,
1433 },
1434 'memo': {
1435 'subject': False,
1436 'date': False,
1437 'secret': False,
1438 'category': False,
1439 'memo': True,
1440 },
1441 'todo': {
1442 'summary': False,
1443 'status': False,
1444 'due_date': False,
1445 'percent_complete': False,
1446 'completion_date': False,
1447 'private': False,
1448 'priority': False,
1449 'category': False,
1450 'memo': False,
1451 },
1452 }
1453