0001 ### BITPIM 0002 ### 0003 ### Copyright (C) 2005 Joe Pham <djpham@bitpim.org> 0004 ### 0005 ### This program is free software; you can redistribute it and/or modify 0006 ### it under the terms of the BitPim license as detailed in the LICENSE file. 0007 ### 0008 ### $Id: com_lgvx9800.py 4305 2007-07-16 04:05:25Z djpham $ 0009 0010 """Communicate with the LG VX9800 cell phone 0011 """ 0012 0013 # standard modules 0014 import re 0015 import time 0016 import cStringIO 0017 import sha 0018 0019 # my modules 0020 import common 0021 import commport 0022 import copy 0023 import com_lgvx4400 0024 import p_brew 0025 import p_lgvx9800 0026 import com_lgvx8100 0027 import com_brew 0028 import com_phone 0029 import com_lg 0030 import prototypes 0031 import bpcalendar 0032 import call_history 0033 import sms 0034 import memo 0035 import playlist 0036 import helpids 0037 0038 class Phone(com_lgvx8100.Phone): 0039 "Talk to the LG VX9800 cell phone" 0040 0041 desc="LG-VX9800" 0042 helpid=helpids.ID_PHONE_LGVX9800 0043 protocolclass=p_lgvx9800 0044 serialsname='lgvx9800' 0045 my_model='VX9800' 0046 0047 builtinringtones= ('Low Beep Once', 'Low Beeps', 'Loud Beep Once', 'Loud Beeps', 'VZW Default Tone') + \ 0048 tuple(['Ringtone '+`n` for n in range(1,11)]) + \ 0049 ('No Ring',) 0050 0051 ringtonelocations= ( 0052 # type index-file size-file directory-to-use lowest-index-to-use maximum-entries type-major icon index_offset 0053 ( 'ringers', 'dload/my_ringtone.dat', 'dload/my_ringtonesize.dat', 'brew/16452/lk/mr', 100, 150, 0x201, 1, 0), 0054 # the sound index file uses the same index as the ringers, bitpim does not support this (yet) 0055 ( 'sounds', 'dload/mysound.dat', 'dload/mysoundsize.dat', 'brew/16452/ms', 100, 150, 0x402, 0, 151), 0056 ) 0057 0058 calendarlocation="sch/schedule.dat" 0059 calendarexceptionlocation="sch/schexception.dat" 0060 calenderrequiresreboot=0 0061 memolocation="sch/memo.dat" 0062 0063 builtinwallpapers = () # none 0064 0065 wallpaperlocations= ( 0066 ( 'images', 'dload/image.dat', 'dload/imagesize.dat', 'brew/16452/mp', 100, 50, 0, 0, 0), 0067 ( 'video', 'dload/video.dat', None, 'brew/16452/mf', 1000, 50, 0x0304, 0, 0), 0068 ) 0069 0070 # for removable media (miniSD cards) 0071 _rs_path='mmc1/' 0072 _rs_ringers_path=_rs_path+'ringers' 0073 _rs_images_path=_rs_path+'images' 0074 media_info={ 'ringers': { 0075 'localpath': 'brew/16452/lk/mr', 0076 'rspath': _rs_ringers_path, 0077 'vtype': protocolclass.MEDIA_TYPE_RINGTONE, 0078 'icon': protocolclass.MEDIA_RINGTONE_DEFAULT_ICON, 0079 'index': 100, # starting index 0080 'maxsize': 155, 0081 'indexfile': 'dload/my_ringtone.dat', 0082 'sizefile': 'dload/my_ringtonesize.dat', 0083 'dunno': 0, 'date': False, 0084 }, 0085 'sounds': { 0086 'localpath': 'brew/16452/ms', 0087 'rspath': None, 0088 'vtype': protocolclass.MEDIA_TYPE_SOUND, 0089 'icon': protocolclass.MEDIA_IMAGE_DEFAULT_ICON, 0090 'index': 100, 0091 'maxsize': 155, 0092 'indexfile': 'dload/mysound.dat', 0093 'sizefile': 'dload/mysoundsize.dat', 0094 'dunno': 0, 'date': False }, 0095 'images': { 0096 'localpath': 'brew/16452/mp', 0097 'rspath': _rs_images_path, 0098 'vtype': protocolclass.MEDIA_TYPE_IMAGE, 0099 'icon': protocolclass.MEDIA_IMAGE_DEFAULT_ICON, 0100 'index': 100, 0101 'maxsize': 155, 0102 'indexfile': 'dload/image.dat', 0103 'sizefile': 'dload/imagesize.dat', 0104 'dunno': 0, 'date': False }, 0105 'video': { 0106 'localpath': 'brew/16452/mf', 0107 'rspath': None, 0108 'vtype': protocolclass.MEDIA_TYPE_VIDEO, 0109 'icon': protocolclass.MEDIA_VIDEO_DEFAULT_ICON, 0110 'index': 1000, 0111 'maxsize': 155, 0112 'indexfile': 'dload/video.dat', 0113 'sizefile': 'dload/videosize.dat', 0114 'dunno': 0, 'date': True }, 0115 } 0116 0117 def __init__(self, logtarget, commport): 0118 com_lgvx8100.Phone.__init__(self, logtarget, commport) 0119 p_brew.PHONE_ENCODING=self.protocolclass.PHONE_ENCODING 0120 self.mode=self.MODENONE 0121 0122 def get_esn(self, data=None): 0123 # return the ESN of this phone 0124 return self.get_brew_esn() 0125 0126 def get_detect_data(self, res): 0127 com_lgvx8100.Phone.get_detect_data(self, res) 0128 res[self.esn_file_key]=self.get_esn() 0129 0130 # Fundamentals: 0131 # - get_esn - same as LG VX-8300 0132 # - getgroups - same as LG VX-8100 0133 # - getwallpaperindices - LGNewIndexedMedia2 0134 # - getrintoneindices - LGNewIndexedMedia2 0135 # - DM Version - N/A 0136 0137 # Media stuff--------------------------------------------------------------- 0138 def _is_rs_file(self, filename): 0139 return filename.startswith(self._rs_path) 0140 0141 def getmedia(self, maps, results, key): 0142 origins={} 0143 # signal that we are using the new media storage that includes the origin and timestamp 0144 origins['new_media_version']=1 0145 0146 for type, indexfile, sizefile, directory, lowestindex, maxentries, typemajor, def_icon, idx_ofs in maps: 0147 media={} 0148 for item in self.getindex(indexfile): 0149 data=None 0150 timestamp=None 0151 try: 0152 stat_res=self.statfile(item.filename) 0153 if stat_res!=None: 0154 timestamp=stat_res['date'][0] 0155 if not self._is_rs_file(item.filename): 0156 data=self.getfilecontents(item.filename, True) 0157 except (com_brew.BrewNoSuchFileException,com_brew.BrewBadPathnameException,com_brew.BrewNameTooLongException): 0158 self.log("It was in the index, but not on the filesystem") 0159 except com_brew.BrewAccessDeniedException: 0160 # firmware wouldn't let us read this file, just mark it then 0161 self.log('Failed to read file: '+item.filename) 0162 data='' 0163 except: 0164 if __debug__: 0165 raise 0166 self.log('Failed to read file: '+item.filename) 0167 data='' 0168 if data!=None: 0169 media[common.basename(item.filename)]={ 'data': data, 'timestamp': timestamp} 0170 origins[type]=media 0171 0172 results[key]=origins 0173 return results 0174 0175 def _mark_files(self, local_files, rs_files, local_dir): 0176 # create empty local files as markers for remote files 0177 _empty_files=[common.basename(x) for x,_entry in local_files.items() \ 0178 if not _entry['size']] 0179 _remote_files=[common.basename(x) for x in rs_files] 0180 for _file in _remote_files: 0181 if _file not in _empty_files: 0182 # mark this one 0183 self.writefile(local_dir+'/'+_file, '') 0184 for _file in _empty_files: 0185 if _file not in _remote_files: 0186 # remote file no longer exists, del the marker 0187 self.rmfile(local_dir+'/'+_file) 0188 0189 def _write_index_file(self, type): 0190 _info=self.media_info.get(type, None) 0191 if not _info: 0192 return 0193 _files={} 0194 _local_dir=_info['localpath'] 0195 _rs_dir=_info['rspath'] 0196 _vtype=_info['vtype'] 0197 _icon=_info['icon'] 0198 _index=_info['index'] 0199 _maxsize=_info['maxsize'] 0200 _dunno=_info['dunno'] 0201 indexfile=_info['indexfile'] 0202 sizefile=_info['sizefile'] 0203 _need_date=_info['date'] 0204 try: 0205 _files=self.listfiles(_local_dir) 0206 except (com_brew.BrewNoSuchDirectoryException, 0207 com_brew.BrewBadPathnameException): 0208 pass 0209 try: 0210 if _rs_dir: 0211 _rs_files=self.listfiles(_rs_dir) 0212 if type=='ringers': 0213 self._mark_files(_files, _rs_files, _local_dir) 0214 _files.update(_rs_files) 0215 except (com_brew.BrewNoSuchDirectoryException, 0216 com_brew.BrewBadPathnameException): 0217 # dir does not exist, no media files available 0218 pass 0219 # del all the markers (empty files) ringers 0220 if type=='ringers': 0221 _keys=_files.keys() 0222 for _key in _keys: 0223 if not _files[_key]['size']: 0224 del _files[_key] 0225 # dict of all indices 0226 _idx_keys={} 0227 for _i in xrange(_index, _index+_maxsize): 0228 _idx_keys[_i]=True 0229 # assign existing indices 0230 for _item in self.getindex(indexfile): 0231 if _files.has_key(_item.filename): 0232 _files[_item.filename]['index']=_item.index 0233 _idx_keys[_item.index]=False 0234 # available new indices 0235 _idx_keys_list=[k for k,x in _idx_keys.items() if x] 0236 _idx_keys_list.sort() 0237 _idx_cnt=0 0238 # assign new indices 0239 _file_list=[x for x in _files if not _files[x].get('index', None)] 0240 _file_list.sort() 0241 if len(_file_list)>len(_idx_keys_list): 0242 _file_list=_file_list[:len(_idx_keys_list)] 0243 for i in _file_list: 0244 _files[i]['index']=_idx_keys_list[_idx_cnt] 0245 _idx_cnt+=1 0246 # (index, file name) list for writing 0247 _res_list=[(x['index'],k) for k,x in _files.items() if x.get('index', None)] 0248 _res_list.sort() 0249 _res_list.reverse() 0250 # writing the index file 0251 ifile=self.protocolclass.indexfile() 0252 _file_size=0 0253 for index,idx in _res_list: 0254 _fs_size=_files[idx]['size'] 0255 ie=self.protocolclass.indexentry() 0256 ie.index=index 0257 ie.type=_vtype 0258 ie.filename=idx 0259 if _need_date: 0260 # need to fill in the date value 0261 _stat=self.statfile(_files[idx]['name']) 0262 if _stat: 0263 ie.date=_stat['datevalue']-time.timezone 0264 ie.dunno=_dunno 0265 ie.icon=_icon 0266 ie.size=_fs_size 0267 ifile.items.append(ie) 0268 if not self._is_rs_file(idx): 0269 _file_size+=_fs_size 0270 buf=prototypes.buffer() 0271 ifile.writetobuffer(buf, logtitle="Index file "+indexfile) 0272 self.log("Writing index file "+indexfile+" for type "+type+" with "+`len(_res_list)`+" entries.") 0273 self.writefile(indexfile, buf.getvalue()) 0274 # writing the size file 0275 if sizefile: 0276 szfile=self.protocolclass.sizefile() 0277 szfile.size=_file_size 0278 buf=prototypes.buffer() 0279 szfile.writetobuffer(buf, logtitle="Updated size file for "+type) 0280 self.log("You are using a total of "+`_file_size`+" bytes for "+type) 0281 self.writefile(sizefile, buf.getvalue()) 0282 0283 def savemedia(self, mediakey, mediaindexkey, maps, results, merge, reindexfunction): 0284 """Actually saves out the media 0285 0286 @param mediakey: key of the media (eg 'wallpapers' or 'ringtones') 0287 @param mediaindexkey: index key (eg 'wallpaper-index') 0288 @param maps: list index files and locations 0289 @param results: results dict 0290 @param merge: are we merging or overwriting what is there? 0291 @param reindexfunction: the media is re-indexed at the end. this function is called to do it 0292 """ 0293 0294 # take copies of the lists as we modify them 0295 wp=results[mediakey].copy() # the media we want to save 0296 wpi=results[mediaindexkey].copy() # what is already in the index files 0297 0298 # remove builtins 0299 for k in wpi.keys(): 0300 if wpi[k].get('origin', "")=='builtin': 0301 del wpi[k] 0302 0303 # build up list into init 0304 init={} 0305 for type,_,_,_,lowestindex,_,typemajor,_,_ in maps: 0306 init[type]={} 0307 for k in wpi.keys(): 0308 if wpi[k]['origin']==type: 0309 index=k 0310 name=wpi[k]['name'] 0311 fullname=wpi[k]['filename'] 0312 vtype=wpi[k]['vtype'] 0313 icon=wpi[k]['icon'] 0314 data=None 0315 del wpi[k] 0316 for w in wp.keys(): 0317 # does wp contain a reference to this same item? 0318 if wp[w]['name']==name and wp[w]['origin']==type: 0319 data=wp[w]['data'] 0320 del wp[w] 0321 if not merge and data is None: 0322 # delete the entry 0323 continue 0324 ## assert index>=lowestindex 0325 init[type][index]={'name': name, 'data': data, 'filename': fullname, 'vtype': vtype, 'icon': icon} 0326 0327 # init now contains everything from wallpaper-index 0328 # wp contains items that we still need to add, and weren't in the existing index 0329 assert len(wpi)==0 0330 print init.keys() 0331 0332 # now look through wallpapers and see if anything was assigned a particular 0333 # origin 0334 for w in wp.keys(): 0335 o=wp[w].get("origin", "") 0336 if o is not None and len(o) and o in init: 0337 idx=-1 0338 while idx in init[o]: 0339 idx-=1 0340 init[o][idx]=wp[w] 0341 del wp[w] 0342 0343 # wp will now consist of items that weren't assigned any particular place 0344 # so put them in the first available space 0345 for type,_,_,_,lowestindex,maxentries,typemajor,def_icon,_ in maps: 0346 # fill it up 0347 for w in wp.keys(): 0348 if len(init[type])>=maxentries: 0349 break 0350 idx=-1 0351 while idx in init[type]: 0352 idx-=1 0353 init[type][idx]=wp[w] 0354 del wp[w] 0355 0356 # time to write the files out 0357 for type, indexfile, sizefile, directory, lowestindex, maxentries,typemajor,def_icon,_ in maps: 0358 # get the index file so we can work out what to delete 0359 names=[init[type][x]['name'] for x in init[type]] 0360 for item in self.getindex(indexfile): 0361 if common.basename(item.filename) not in names and \ 0362 not self._is_rs_file(item.filename): 0363 self.log(item.filename+" is being deleted") 0364 self.rmfile(item.filename) 0365 # fixup the indices 0366 fixups=[k for k in init[type].keys() if k<lowestindex] 0367 fixups.sort() 0368 for f in fixups: 0369 for ii in xrange(lowestindex, lowestindex+maxentries): 0370 # allocate an index 0371 if ii not in init[type]: 0372 init[type][ii]=init[type][f] 0373 del init[type][f] 0374 break 0375 # any left over? 0376 fixups=[k for k in init[type].keys() if k<lowestindex] 0377 for f in fixups: 0378 self.log("There is no space in the index for "+type+" for "+init[type][f]['name']) 0379 del init[type][f] 0380 # write each entry out 0381 for idx in init[type].keys(): 0382 entry=init[type][idx] 0383 filename=entry.get('filename', directory+"/"+entry['name']) 0384 entry['filename']=filename 0385 fstat=self.statfile(filename) 0386 if 'data' not in entry: 0387 # must be in the filesystem already 0388 if fstat is None: 0389 self.log("Entry "+entry['name']+" is in index "+indexfile+" but there is no data for it and it isn't in the filesystem. The index entry will be removed.") 0390 del init[type][idx] 0391 continue 0392 # check len(data) against fstat->length 0393 data=entry['data'] 0394 if data is None: 0395 assert merge 0396 continue # we are doing an add and don't have data for this existing entry 0397 if fstat is not None and len(data)==fstat['size']: 0398 self.log("Not writing "+filename+" as a file of the same name and length already exists.") 0399 else: 0400 self.writefile(filename, data) 0401 # write out index 0402 self._write_index_file(type) 0403 return reindexfunction(results) 0404 0405 # Phonebook stuff----------------------------------------------------------- 0406 def savephonebook(self, data): 0407 "Saves out the phonebook" 0408 res=com_lgvx8100.Phone.savephonebook(self, data) 0409 # fix up the Wallpaper ID issue 0410 _wp_paths=self.protocolclass.wallpaper_id_file() 0411 _path_entry=self.protocolclass.wallpaper_id() 0412 # clear out all entries 0413 for i in range(self.protocolclass.NUMPHONEBOOKENTRIES): 0414 _wp_paths.items.append(_path_entry) 0415 # go through each entry and update the wallpaper path 0416 _buf=prototypes.buffer(self.getfilecontents( 0417 self.protocolclass.pb_file_name)) 0418 _pb_entries=self.protocolclass.pbfile() 0419 _pb_entries.readfrombuffer(_buf, logtitle="Read phonebook file "+self.protocolclass.pb_file_name) 0420 _wp_index=res.get('wallpaper-index', {}) 0421 for _entry in _pb_entries.items: 0422 try: 0423 if _entry.wallpaper==0 or _entry.wallpaper==0xffff: 0424 # no picture ID assigned 0425 continue 0426 _filename=_wp_index[_entry.wallpaper]['filename'] 0427 if _filename: 0428 _path_str=_filename+'\x00' 0429 _path=self.protocolclass.wallpaper_id() 0430 _path.path=_path_str 0431 _wp_paths.items[_entry.entrynumber]=_path 0432 except: 0433 if __debug__: 0434 raise 0435 _buf=prototypes.buffer() 0436 _wp_paths.writetobuffer(_buf, logtitle="Updated wallpaper ids "+self.protocolclass.wallpaper_id_file_name) 0437 self.writefile(self.protocolclass.wallpaper_id_file_name, 0438 _buf.getvalue()) 0439 0440 # SMS Stuff----------------------------------------------------------------- 0441 def _readsms(self): 0442 res={} 0443 # go through the sms directory looking for messages 0444 for item in self.listfiles("sms").values(): 0445 folder=None 0446 for f,pat in self.protocolclass.SMS_PATTERNS.items(): 0447 if pat.match(item['name']): 0448 folder=f 0449 break 0450 if folder: 0451 buf=prototypes.buffer(self.getfilecontents(item['name'], True)) 0452 self.logdata("SMS message file " +item['name'], buf.getdata()) 0453 if folder=='Inbox': 0454 sf=self.protocolclass.sms_in() 0455 sf.readfrombuffer(buf, logtitle="SMS inbox item") 0456 entry=self._getinboxmessage(sf) 0457 res[entry.id]=entry 0458 elif folder=='Sent': 0459 sf=self.protocolclass.sms_out() 0460 sf.readfrombuffer(buf, logtitle="SMS sent item") 0461 entry=self._getoutboxmessage(sf) 0462 res[entry.id]=entry 0463 elif folder=='Saved': 0464 sf=self.protocolclass.sms_saved() 0465 sf.readfrombuffer(buf, logtitle="SMS saved item") 0466 if sf.inboxmsg: 0467 entry=self._getinboxmessage(sf.inbox) 0468 else: 0469 entry=self._getoutboxmessage(sf.outbox) 0470 entry.folder=entry.Folder_Saved 0471 res[entry.id]=entry 0472 return res 0473 0474 # Playlist stuff------------------------------------------------------------ 0475 def _read_pl_list(self, file_name): 0476 _buf=prototypes.buffer(self.getfilecontents(file_name)) 0477 _pl_index=self.protocolclass.playlistfile() 0478 _pl_index.readfrombuffer(_buf, logtitle="Read playlist "+file_name) 0479 _songs=[x.name[self.protocolclass.mp3_dir_len:] for x in _pl_index.items] 0480 _entry=playlist.PlaylistEntry() 0481 if file_name.endswith(self.protocolclass.pl_extension): 0482 _entry.name=file_name[self.protocolclass.pl_dir_len:\ 0483 -self.protocolclass.pl_extension_len] 0484 else: 0485 _entry.name=file_name[self.protocolclass.pl_dir_len:] 0486 _entry.songs=_songs 0487 return _entry 0488 0489 def getplaylist(self, result): 0490 # return the mp3 playlists if available 0491 # first, read the list of all mp3 songs 0492 _mp3_list=[] 0493 try: 0494 _files=self.listfiles(self.protocolclass.mp3_dir) 0495 _file_list=_files.keys() 0496 _file_list.sort() 0497 _mp3_list=[x[self.protocolclass.mp3_dir_len:] for x in _file_list ] 0498 except: 0499 if __debug__: 0500 raise 0501 result[playlist.masterlist_key]=_mp3_list 0502 # then read the playlist 0503 _pl_list=[] 0504 try: 0505 _files=self.listfiles(self.protocolclass.pl_dir) 0506 _file_list=_files.keys() 0507 _file_list.sort() 0508 for _f in _file_list: 0509 _pl_list.append(self._read_pl_list(_f)) 0510 except: 0511 if __debug__: 0512 raise 0513 result[playlist.playlist_key]=_pl_list 0514 return result 0515 0516 def _write_playlists(self, pl, all_songs): 0517 for _pl_item in pl: 0518 try: 0519 _pl_file=self.protocolclass.playlistfile() 0520 for _song in _pl_item.songs: 0521 _song_name=self.protocolclass.mp3_dir+'/'+_song 0522 if all_songs.has_key(_song_name): 0523 _entry=self.protocolclass.playlistentry() 0524 _entry.name=_song_name 0525 _pl_file.items.append(_entry) 0526 if len(_pl_file.items): 0527 # don't write out an empty list 0528 _buf=prototypes.buffer() 0529 _file_name=self.protocolclass.pl_dir+'/'+_pl_item.name+\ 0530 self.protocolclass.pl_extension 0531 _pl_file.writetobuffer(_buf, logtitle="Updating playlist "+_file_name) 0532 self.writefile(_file_name, _buf.getvalue()) 0533 except: 0534 if __debug__: 0535 raise 0536 0537 def saveplaylist(self, result, merge): 0538 # check to see if the pl_dir exist 0539 if not self.exists(self.protocolclass.pl_dir): 0540 self.log('Playlist dir does not exist. Bail') 0541 return result 0542 # get the list of available mp3 files 0543 _all_songs=self.listfiles(self.protocolclass.mp3_dir) 0544 # delete all existing playlists 0545 _files=self.listfiles(self.protocolclass.pl_dir) 0546 for _f in _files: 0547 try: 0548 self.rmfile(_f) 0549 except: 0550 if __debug__: 0551 raise 0552 # update the new playlists 0553 self._write_playlists(result.get(playlist.playlist_key, []), 0554 _all_songs) 0555 return result 0556 0557 #------------------------------------------------------------------------------- 0558 parentprofile=com_lgvx8100.Profile 0559 class Profile(parentprofile): 0560 protocolclass=Phone.protocolclass 0561 serialsname=Phone.serialsname 0562 0563 BP_Calendar_Version=3 0564 phone_manufacturer='LG Electronics Inc' 0565 phone_model='VX9800' 0566 0567 WALLPAPER_WIDTH=320 0568 WALLPAPER_HEIGHT=256 0569 MAX_WALLPAPER_BASENAME_LENGTH=32 0570 WALLPAPER_FILENAME_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789()_ .-" 0571 WALLPAPER_CONVERT_FORMAT="jpg" 0572 0573 # the 9800 uses "W" for wait in the dialstring, it does not support "T" 0574 DIALSTRING_CHARS="[^0-9PW#*]" 0575 0576 MAX_RINGTONE_BASENAME_LENGTH=32 0577 RINGTONE_FILENAME_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789()_ .-" 0578 0579 # there is an origin named 'aod' - no idea what it is for except maybe 0580 # 'all other downloads' 0581 0582 # the vx8100 supports bluetooth for connectivity to the PC, define the "bluetooth_mgd_id" 0583 # to enable bluetooth discovery during phone detection 0584 # the bluetooth address starts with LG's the three-octet OUI, all LG phone 0585 # addresses start with this, it provides a way to identify LG bluetooth devices 0586 # during phone discovery 0587 # OUI=Organizationally Unique Identifier 0588 # see http://standards.ieee.org/regauth/oui/index.shtml for more info 0589 bluetooth_mfg_id="001256" 0590 0591 # the 8100 doesn't have seperate origins - they are all dumped in "images" 0592 imageorigins={} 0593 imageorigins.update(common.getkv(parentprofile.stockimageorigins, "images")) 0594 imageorigins.update(common.getkv(parentprofile.stockimageorigins, "video")) 0595 def GetImageOrigins(self): 0596 return self.imageorigins 0597 0598 ringtoneorigins=('ringers', 'sounds') 0599 excluded_ringtone_origins=('sounds') 0600 excluded_wallpaper_origins=('video') 0601 0602 # our targets are the same for all origins 0603 imagetargets={} 0604 imagetargets.update(common.getkv(parentprofile.stockimagetargets, "wallpaper", 0605 {'width': 320, 'height': 230, 'format': "JPEG"})) 0606 imagetargets.update(common.getkv(parentprofile.stockimagetargets, "outsidelcd", 0607 {'width': 320, 'height': 198, 'format': "JPEG"})) 0608 0609 def GetTargetsForImageOrigin(self, origin): 0610 return self.imagetargets 0611 0612 0613 def __init__(self): 0614 parentprofile.__init__(self) 0615 0616 _supportedsyncs=( 0617 ('phonebook', 'read', None), # all phonebook reading 0618 ('calendar', 'read', None), # all calendar reading 0619 ('wallpaper', 'read', None), # all wallpaper reading 0620 ('ringtone', 'read', None), # all ringtone reading 0621 ('call_history', 'read', None),# all call history list reading 0622 ('sms', 'read', None), # all SMS list reading 0623 ('memo', 'read', None), # all memo list reading 0624 ('phonebook', 'write', 'OVERWRITE'), # only overwriting phonebook 0625 ('calendar', 'write', 'OVERWRITE'), # only overwriting calendar 0626 ('wallpaper', 'write', 'MERGE'), # merge and overwrite wallpaper 0627 ('wallpaper', 'write', 'OVERWRITE'), 0628 ('ringtone', 'write', 'MERGE'), # merge and overwrite ringtone 0629 ('ringtone', 'write', 'OVERWRITE'), 0630 ('sms', 'write', 'OVERWRITE'), # all SMS list writing 0631 ('memo', 'write', 'OVERWRITE'), # all memo list writing 0632 ('playlist', 'read', 'OVERWRITE'), 0633 ('playlist', 'write', 'OVERWRITE'), 0634 ) 0635
Generated by PyXR 0.9.4