PyXR

c:\projects\bitpim\src \ phones \ com_lgvx8550.py



0001 #!/usr/bin/env python
0002 
0003 ### BITPIM
0004 ###
0005 ### Copyright (C) 2007-2008 Nathan Hjelm <hjelmn@users.sourceforge.net>
0006 ###
0007 ### This program is free software; you can redistribute it and/or modify
0008 ### it under the terms of the BitPim license as detailed in the LICENSE file.
0009 ### $Id: com_lgvx8550.py 4679 2008-08-14 01:01:22Z hjelmn $
0010 
0011 
0012 """
0013 Communicate with the LG VX8550 cell phone.
0014 """
0015 
0016 # BitPim modules
0017 import common
0018 import com_brew
0019 import bpcalendar
0020 import prototypes
0021 import com_lgvx8700
0022 import com_lgvx8500
0023 import p_lgvx8550
0024 import p_brew
0025 import helpids
0026 import copy
0027 import time
0028 import os.path
0029 
0030 DEBUG1=False
0031 #-------------------------------------------------------------------------------
0032 parentphone=com_lgvx8700.Phone
0033 class Phone(parentphone):
0034     desc="LG-VX8550"
0035     helpid=None
0036     protocolclass=p_lgvx8550
0037     serialsname='lgvx8550'
0038 
0039     my_model='VX8550'
0040 
0041     calendarringerlocation='sch/toolsRinger.dat'
0042 
0043     def setDMversion(self):
0044         _fw_version=self.get_firmware_version()[-1]
0045         if self.my_model=='VX8550' and _fw_version>'3':
0046             # VX855V04
0047             self._DMv5 = False
0048             self._DMv6 = True
0049         else:
0050             self._DMv5 = True
0051             self._DMv6 = False
0052 
0053 
0054     # Fundamentals:
0055     #  - get_esn             - same as LG VX-8300
0056     #  - getgroups           - same as LG VX-8700
0057     #  - getwallpaperindices - LGUncountedIndexedMedia
0058     #  - getringtoneindices  - LGUncountedIndexedMedia
0059     #  - DM Version          - 5 (VX855V03 or older), 6 (VX855V04)
0060 
0061     def _get_speeddials(self):
0062         """Return the speed dials dict"""
0063         speeds={}
0064         try:
0065             if self.protocolclass.NUMSPEEDDIALS:
0066                 self.log("Reading speed dials")
0067                 sd=self.readobject(self.protocolclass.speed_file_name,
0068                                    self.protocolclass.speeddials, 'Reading speed dials')
0069                 for _idx,_entry in enumerate(sd.speeddials):
0070                     if _entry.valid():
0071                         speeds.setdefault(_entry.entry, {}).update({ _entry.number: _idx })
0072         except com_brew.BrewNoSuchFileException:
0073             pass
0074         return speeds
0075 
0076     def _build_media_dict(self, fundamentals, media_data, index_name):
0077         """Build & return a dict with keys being the media filenames and
0078         values being the name of the index item (index['name'])
0079         """
0080         _res={}
0081         _media_index=fundamentals.get(index_name, {})
0082         for _item in media_data.items:
0083             _pathname=_item.pathname
0084             if _pathname and not _res.has_key(_pathname):
0085                 # not already in dict, look up the name if any
0086                 _res[_pathname]=None
0087                 for _entry in _media_index.values():
0088                     if _entry.get('filename', None)==_pathname:
0089                         _res[_pathname]=_entry['name']
0090                         break
0091         return _res
0092 
0093     def _get_path_index(self, index_file):
0094         buf = prototypes.buffer(self.getfilecontents(index_file))
0095         _path_file=self.protocolclass.PathIndexFile()
0096         _path_file.readfrombuffer(buf, logtitle="Read path index: " + index_file)
0097         return _path_file
0098 
0099     def _build_ice_dict(self):
0100         # Return an ICE dict for building phone entries
0101         _res={}
0102         _ice=self.readobject(self.protocolclass.ice_file_name,
0103                              self.protocolclass.iceentryfile,
0104                              logtitle='Reading ICE entries')
0105         for _item in _ice.items:
0106             if _item.valid():
0107                 _res[_item.pb_index]=_item.entry_number
0108         return _res
0109 
0110     def getphonebook (self, result):
0111         """Reads the phonebook data.  The L{getfundamentals} information will
0112         already be in result."""
0113         # Read speed dials first -- same file format as the VX-8100
0114         _speeds=self._get_speeddials()
0115 
0116         # Read the emergency contacts list
0117         self.log("Reading ICE entries")
0118         _ices=self._build_ice_dict()
0119 
0120         self.log("Reading phonebook entries")
0121         pb_entries=self.readobject(self.protocolclass.pb_file_name,
0122                                    self.protocolclass.pbfile,
0123                                    logtitle='Reading phonebook entries')
0124 
0125         self.log("Reading phone numbers")
0126         pb_numbers=self.readobject(self.protocolclass.pn_file_name,
0127                                    self.protocolclass.pnfile,
0128                                    logtitle='Reading phonebook numbers')
0129 
0130         self.log("Reading Ringtone IDs")
0131         ring_pathf=self._get_path_index(self.protocolclass.RTPathIndexFile)
0132         _rt_ids=self._build_media_dict(result, ring_pathf, 'ringtone-index')
0133 
0134         self.log("Reading Picture IDs")
0135         picid_pathf=self._get_path_index(self.protocolclass.WPPathIndexFile)
0136         _wp_ids=self._build_media_dict(result, picid_pathf, 'wallpaper-index')
0137 
0138         pbook={}
0139         for _cnt in range(self.protocolclass.NUMPHONEBOOKENTRIES):
0140             pb_entry=pb_entries.items[_cnt]
0141             if not pb_entry.valid():
0142                 continue
0143             try:
0144                 self.log("Parse entry "+`_cnt`+" - " + pb_entry.name)
0145                 pbook[_cnt]=self.extractphonebookentry(pb_entry, pb_numbers,
0146                                                        _speeds, _ices, result,
0147                                                        _rt_ids.get(ring_pathf.items[_cnt].pathname, None),
0148                                                        _wp_ids.get(picid_pathf.items[_cnt].pathname, None))
0149 
0150                 self.progress(_cnt, self.protocolclass.NUMPHONEBOOKENTRIES, pb_entry.name)
0151             except common.PhoneBookBusyException:
0152                 raise
0153             except Exception, e:
0154                 # Something's wrong with this entry, log it and skip
0155                 self.log('Failed to parse entry %d'%_cnt)
0156                 self.log('Exception %s raised'%`e`)
0157                 if __debug__:
0158                     raise
0159             
0160         self.progress(self.protocolclass.NUMPHONEBOOKENTRIES,
0161                       self.protocolclass.NUMPHONEBOOKENTRIES,
0162                       "Phone book read completed")
0163 
0164         result['phonebook']=pbook
0165         cats=[]
0166         for i in result['groups']:
0167             if result['groups'][i]['name']!='No Group':
0168                 cats.append(result['groups'][i]['name'])
0169         result['categories']=cats
0170         return pbook
0171 
0172     def extractphonebookentry(self, entry, numbers, speeds, ices, fundamentals,
0173                               rt_name, wp_name):
0174         """Return a phonebook entry in BitPim format.  This is called from getphonebook."""
0175         res={}
0176         # serials
0177         res['serials']=[ {'sourcetype': self.serialsname,
0178                           'sourceuniqueid': fundamentals['uniqueserial'],
0179                           'serial1': entry.entry_number1,
0180                           'serial2': entry.entry_number1 } ] 
0181 
0182         # only one name
0183         res['names']=[ {'full': entry.name} ]
0184 
0185         # only one category
0186         cat=fundamentals['groups'].get(entry.group, {'name': "No Group"})['name']
0187         if cat!="No Group":
0188             res['categories']=[ {'category': cat} ]
0189 
0190         # emails
0191         res['emails']=[]
0192         for i in entry.emails:
0193             if len(i.email):
0194                 res['emails'].append( {'email': i.email} )
0195         if not len(res['emails']): del res['emails'] # it was empty
0196 
0197         # wallpapers
0198         if entry.wallpaper!=self.protocolclass.NOWALLPAPER:
0199             try:
0200                 if entry.wallpaper == 0x64:
0201                     paper = wp_name
0202                 else:
0203                     paper = fundamentals['wallpaper-index'][entry.wallpaper]['name']
0204 
0205                 if paper is None:
0206                     raise
0207 
0208                 res['wallpapers']=[ {'wallpaper': paper, 'use': 'call'} ]                
0209             except:
0210                 print "can't find wallpaper for index",entry.wallpaper
0211             
0212         # ringtones
0213         if entry.ringtone != self.protocolclass.NORINGTONE:
0214             try:
0215                 if entry.ringtone == 0x64:
0216                     tone = rt_name
0217                 else:
0218                     tone = fundamentals['ringtone-index'][entry.ringtone]['name']
0219 
0220                 if tone is None:
0221                     raise
0222 
0223                 res['ringtones']=[ {'ringtone': tone, 'use': 'call'} ]
0224             except:
0225                 print "can't find ringtone for index",entry.ringtone
0226         # assume we are like the VX-8100 in this regard -- looks correct
0227         res=self._assignpbtypeandspeeddialsbytype(entry, numbers, speeds, res)
0228 
0229         # assign the ICE entry to the associated contact to keep them in sync
0230         res=self._assigniceentry(entry, numbers, ices, res)
0231   
0232         return res
0233 
0234     def _assignpbtypeandspeeddialsbytype(self, entry, numbers, speeds, res):
0235         # for some phones (e.g. vx8100) the speeddial numberindex is really the numbertype (now why would LG want to change this!)
0236         res['numbers']=[]
0237 
0238         for i in range(self.protocolclass.NUMPHONENUMBERS):
0239             if entry.numberindices[i].numberindex >= self.protocolclass.NUMPHONENUMBERENTRIES:
0240                 # invalid number
0241                 continue
0242             _pnentry=numbers.items[entry.numberindices[i].numberindex]
0243             num=_pnentry.phone_number
0244 
0245             if len(num):
0246                 if _pnentry.malformed():
0247                     print "malformed phone number entry encountered"
0248 
0249                 # use the type from the phonebook entry
0250                 num_type = entry.numbertypes[i].numbertype
0251 
0252                 t = self.protocolclass.numbertypetab[num_type]
0253                 if t[-1]=='2':
0254                     t=t[:-1]
0255                 res['numbers'].append({'number': num, 'type': t})
0256                 # if this is a speeddial number set it
0257                 if speeds.has_key(entry.entry_number0) and \
0258                    speeds[entry.entry_number0].has_key(num_type):
0259                     res['numbers'][i]['speeddial']=speeds[entry.entry_number0][num_type]
0260         return res
0261 
0262     def _assigniceentry(self, entry, numbers, ices, res):
0263         if ices.has_key(entry.entry_number0):
0264             # this contact entry is an ICE entry
0265             res['ice']=[ { 'iceindex': ices[entry.entry_number0] } ]
0266         return res
0267 
0268     def _get_next_pb_id(self):
0269         """Return the next available pbentry ID"""
0270         return self.readobject(self.protocolclass.pb_recordid_filename,
0271                                self.protocolclass.RecordIdEntry,
0272                                logtitle='Reading record_id').idnum
0273 
0274     def _save_next_pb_id(self, idnum):
0275         """Save the next pbentry ID"""
0276         self.writeobject(self.protocolclass.pb_recordid_filename,
0277                          self.protocolclass.RecordIdEntry(idnum=idnum),
0278                          logtitle='Writing record_id',
0279                          uselocalfs=DEBUG1)
0280 
0281     def savephonebook (self, data):
0282         "Saves out the phonebook"
0283         self.savegroups (data)
0284 
0285         ring_pathf=self.protocolclass.PathIndexFile()
0286         picid_pathf=self.protocolclass.PathIndexFile()
0287 
0288         # the pbentry.dat will be overwritten so there is no need to delete entries
0289         pbook = data.get('phonebook', {})
0290         keys = pbook.keys ()
0291         keys.sort ()
0292 
0293         _rt_index=data.get('ringtone-index', {})
0294         _wp_index=data.get('wallpaper-index', {})
0295 
0296         entry_num0 = 0
0297         entry_num1 = self._get_next_pb_id()
0298         pb_entries = self.protocolclass.pbfile(model_name=self.my_model)
0299         pn_entries = self.protocolclass.pnfile()
0300 
0301         ice_entries = self.protocolclass.iceentryfile()
0302         for i in range(self.protocolclass.NUMEMERGENCYCONTACTS):
0303             ice_entries.items.append (self.protocolclass.iceentry())
0304 
0305         speeddials={}
0306 
0307         for i in keys:
0308             pb_entries.items.append(self.make_entry (pn_entries, speeddials, ice_entries,
0309                                                      entry_num0, entry_num1, pbook[i],
0310                                                      data, ring_pathf,_rt_index,
0311                                                      picid_pathf, _wp_index))
0312             entry_num0 += 1
0313             if entry_num0 >= self.protocolclass.NUMPHONEBOOKENTRIES:
0314                 self.log ("Maximum number of phonebook entries reached")
0315                 break
0316             if entry_num1==0xffffffff:
0317                 entry_num1=0
0318             else:
0319                 entry_num1+=1
0320 
0321         # write phonebook entries
0322         self.log ("Writing phonebook entries")
0323         self.writeobject(self.protocolclass.pb_file_name,
0324                          pb_entries,
0325                          logtitle='Writing phonebook entries',
0326                          uselocalfs=DEBUG1)
0327         # write phone numbers
0328         self.log ("Writing phone numbers")
0329         self.writeobject(self.protocolclass.pn_file_name,
0330                          pn_entries, logtitle='Writing phonebook numbers',
0331                          uselocalfs=DEBUG1)
0332         # write ringtone index
0333         self.log('Writing ringtone ID')
0334         self.writeobject(self.protocolclass.RTPathIndexFile,
0335                          ring_pathf, logtitle='Writing ringtone paths',
0336                          uselocalfs=DEBUG1)
0337         # write wallpaper index
0338         self.log('Writing picture ID')
0339         self.writeobject(self.protocolclass.WPPathIndexFile,
0340                          picid_pathf, logtitle='Writing wallpaper paths',
0341                          uselocalfs=DEBUG1)
0342 
0343         # write ICE index
0344         self.log('Writing ICE entries')
0345         self.writeobject(self.protocolclass.ice_file_name,
0346                          ice_entries, logtitle='Writing ICE entries',
0347                          uselocalfs=DEBUG1)
0348 
0349         # update speed dials
0350         req=self.protocolclass.speeddials()
0351         # slot 0 is always unused
0352         req.speeddials.append(self.protocolclass.speeddial())
0353         # if empty, slot 1 is for voicemail
0354         if speeddials.has_key(1):
0355             req.speeddials.append(self.protocolclass.speeddial(entry=speeddials[1]['entry'],
0356                                                                number=speeddials[1]['type']))
0357         else:
0358             req.speeddials.append(self.protocolclass.speeddial(entry=1000,
0359                                                                number=6))
0360         for i in range(2, self.protocolclass.NUMSPEEDDIALS):
0361             sd=self.protocolclass.speeddial()
0362             if speeddials.has_key(i):
0363                 sd.entry=speeddials[i]['entry']
0364                 sd.number=speeddials[i]['type']
0365             req.speeddials.append(sd)
0366 
0367         self.log('Writing speed dials')
0368         self.writeobject(self.protocolclass.speed_file_name,
0369                          req, logtitle='Writing speed dials data',
0370                          uselocalfs=DEBUG1)
0371 
0372         # update the next pbentries ID
0373         self._save_next_pb_id(entry_num1)
0374         data["rebootphone"]=True
0375 
0376         return data
0377 
0378     def make_pn_entry (self, phone_number, number_type, pn_id, pbpn_id, pe_id):
0379         """ Create a non-blank pnfileentry frome a phone number string """
0380         if len(phone_number) == 0:
0381             raise
0382         
0383         new_entry = self.protocolclass.pnfileentry(entry_tag=self.protocolclass.PB_NUMBER_SOR)
0384         new_entry.pn_id = pn_id
0385         new_entry.pe_id = pe_id
0386         new_entry.phone_number = phone_number
0387         new_entry.ntype = number_type
0388         new_entry.pn_order = pbpn_id
0389 
0390         return new_entry
0391 
0392     def make_ice_entry (self, ice_id, pb_id):
0393         """ Create a iceentry from a pb_id and ice_id """
0394         new_entry = self.protocolclass.iceentry()
0395         
0396         new_entry.entry_assigned = 1
0397         new_entry.entry_number = ice_id
0398         new_entry.pb_index = pb_id
0399 
0400         return new_entry
0401 
0402     def make_entry (self, pn_entries, speeddials, ice_entries,
0403                     entry_num0, entry_num1, pb_entry, data,
0404                     ring_pathf, rt_index, picid_pathf, wp_index):
0405         """ Create a pbfileentry from a bitpim phonebook entry """
0406         new_entry = self.protocolclass.pbfileentry(entry_tag=self.protocolclass.PB_ENTRY_SOR)
0407         # entry IDs
0408         new_entry.entry_number0 = entry_num0
0409         new_entry.entry_number1 = entry_num1
0410 
0411         for key in pb_entry:
0412             if key in ('emails', 'numbertypes'):
0413                 l = getattr (new_entry, key)
0414                 for item in pb_entry[key]:
0415                     l.append(item)
0416             elif key == 'numbers':
0417                 l = getattr (new_entry, 'numberindices')
0418                 for i in range(0, self.protocolclass.NUMPHONENUMBERS):
0419                     new_pn_id = len (pn_entries.items)
0420                     if new_pn_id == self.protocolclass.NUMPHONENUMBERENTRIES:
0421                         # this state should not be possible. should this raise an exception?
0422                         self.log ("Maximum number of phone numbers reached")
0423                         break
0424 
0425                     try:
0426                         pn_entries.items.append(self.make_pn_entry (pb_entry[key][i],pb_entry['numbertypes'][i], new_pn_id, i, entry_num0))
0427                         l.append (new_pn_id)
0428                     except:
0429                         l.append (0xffff)
0430             elif key == 'speeddials':
0431                 for _sd,_num_type in zip(pb_entry['speeddials'], pb_entry['numbertypes']):
0432                     if _sd is not None:
0433                         speeddials[_sd]={ 'entry': entry_num0,
0434                                           'type': _num_type }
0435             elif key == 'ice':
0436                 # In Case of Emergency
0437                 _ice = pb_entry['ice']
0438                 if _ice is not None and len(_ice) > 0:
0439                     _ice_entry = _ice[0]['iceindex']
0440                     ice_entries.items[_ice_entry] = self.make_ice_entry (_ice_entry, entry_num0)
0441             elif key == 'ringtone':
0442                 new_entry.ringtone = self._findmediainindex(data['ringtone-index'], pb_entry['ringtone'], pb_entry['name'], 'ringtone')
0443                 try:
0444                     _filename = rt_index[new_entry.ringtone]['filename']
0445                     ring_pathf.items.append(self.protocolclass.PathIndexEntry(pathname=_filename))
0446                     new_entry.ringtone = 0x64
0447                 except:
0448                     ring_pathf.items.append(self.protocolclass.PathIndexEntry())
0449             elif key == 'wallpaper':
0450                 new_entry.wallpaper = self._findmediainindex(data['wallpaper-index'], pb_entry['wallpaper'], pb_entry['name'], 'wallpaper')
0451                 try:
0452                     _filename = wp_index[new_entry.wallpaper]['filename']
0453                     picid_pathf.items.append(self.protocolclass.PathIndexEntry(pathname=_filename))
0454                     new_entry.wallpaper = 0x64
0455                 except:
0456                     picid_pathf.items.append(self.protocolclass.PathIndexEntry())
0457             elif key in new_entry.getfields():
0458                 setattr (new_entry, key, pb_entry[key])
0459 
0460         return new_entry
0461 
0462     def getcalendar(self,result):
0463         res={}
0464         # Read exceptions file first
0465         exceptions = self.getexceptions()
0466 
0467         try:
0468             buf = prototypes.buffer(self.getfilecontents(self.calendarringerlocation))
0469             ringersf = self.protocolclass.scheduleringerfile()
0470             ringersf.readfrombuffer (buf)
0471         except:
0472             self.log ("unable to read schedule ringer path file")
0473         
0474         # Now read schedule
0475         try:
0476             buf=prototypes.buffer(self.getfilecontents(self.calendarlocation))
0477             if len(buf.getdata())<3:
0478                 # file is empty, and hence same as non-existent
0479                 raise com_brew.BrewNoSuchFileException()
0480             sc=self.protocolclass.schedulefile()
0481             sc.readfrombuffer(buf, logtitle="Calendar")
0482             for event in sc.events:
0483                 # the vx8100 has a bad entry when the calender is empty
0484                 # stop processing the calender when we hit this record
0485                 if event.pos==0: #invalid entry
0486                     continue
0487                 entry=bpcalendar.CalendarEntry()
0488                 try: # delete events are still in the calender file but have garbage dates
0489                     self.getcalendarcommon(entry, event)
0490                 except ValueError:
0491                     continue
0492                 try:
0493                     if (event.ringtone >= 100):   # MIC Ringer is downloaded to phone or microSD
0494                         entry.ringtone = common.basename(ringersf.ringerpaths[event.ringtone-100].path)
0495                     else:                         # MIC Ringer is built-in
0496                         entry.ringtone=self.builtinringtones[event.ringtone]
0497                 except:
0498                     self.log ("Setting default ringer for event\n")
0499                     # hack, not having a phone makes it hard to figure out the best approach
0500                     if entry.alarm==None:
0501                         entry.ringtone='No Ring'
0502                     else:
0503                         entry.ringtone='Loud Beeps'
0504                 # check for exceptions and remove them
0505                 if event.repeat[3] and exceptions.has_key(event.pos):
0506                     for year, month, day in exceptions[event.pos]:
0507                         entry.suppress_repeat_entry(year, month, day)
0508                 res[entry.id]=entry
0509 
0510             assert sc.numactiveitems==len(res)
0511         except com_brew.BrewNoSuchFileException:
0512             pass # do nothing if file doesn't exist
0513         result['calendar']=res
0514         return result
0515 
0516     def _scheduleextras(self, data, fwversion):
0517         data.serial_number = '000000ca-00000000-00000000-' + fwversion
0518         data.unknown3 = 0x01fb
0519         
0520     def savecalendar(self, dict, merge):
0521         # ::TODO::
0522         # what will be written to the files
0523         eventsf     = self.protocolclass.schedulefile()
0524         exceptionsf = self.protocolclass.scheduleexceptionfile()
0525         ringersf    = self.protocolclass.scheduleringerfile()
0526         # what are we working with
0527         cal=dict['calendar']
0528         newcal={}
0529         #sort into start order, makes it possible to see if the calendar has changed
0530         keys=[(x.start, k) for k,x in cal.items()]
0531         keys.sort()
0532         # apply limiter
0533         keys=keys[:self.protocolclass.NUMCALENDARENTRIES]
0534         # number of entries
0535         eventsf.numactiveitems=len(keys)
0536         ringersf.numringers = 0
0537         pos = 0
0538         # get phone firmware version for serial number
0539         try:
0540             req = p_brew.firmwarerequest()
0541             res = self.sendbrewcommand(req, self.protocolclass.firmwareresponse)
0542             _fwversion = res.firmware
0543         except:
0544             _fwversion = '00000000'
0545 
0546         # play with each entry
0547         for (_,k) in keys:
0548             # entry is what we will return to user
0549             entry=cal[k]
0550             data=self.protocolclass.scheduleevent()
0551             # using the packetsize() method here will fill the LIST with default entries
0552             data.pos = pos * data.packet_size + 2
0553             self._schedulecommon(entry, data)
0554             alarm_set=self.setalarm(entry, data)
0555             if alarm_set:
0556                 if entry.ringtone=="No Ring" and not entry.vibrate:
0557                     alarm_name="Low Beep Once"
0558                 else:
0559                     alarm_name=entry.ringtone
0560             else: # set alarm to "No Ring" gets rid of alarm icon on phone
0561                 alarm_name="No Ring"
0562             for i in dict['ringtone-index']:
0563                 self.log ('ringtone ' + str(i) + ': ' + dict['ringtone-index'][i]['name'] + ' alarm-name = ' + alarm_name)  
0564                 if dict['ringtone-index'][i]['name']==alarm_name:
0565                     if dict['ringtone-index'][i].get('filename', None):
0566                         data.ringtone = 100 + ringersf.numringers
0567                         ringersf.ringerpaths.append(dict['ringtone-index'][i]['filename'])
0568                         ringersf.numringers = ringersf.numringers + 1
0569                     else:
0570                         # builtin ringer
0571                         data.ringtone=i      # Set to proper index
0572                     break
0573             # check for exceptions and add them to the exceptions list
0574             self._scheduleexceptions(entry, data, exceptionsf)
0575             self._scheduleextras(data, _fwversion)
0576             # put entry in nice shiny new dict we are building
0577             entry=copy.copy(entry)
0578             newcal[data.pos]=entry
0579             eventsf.events.append(data)            
0580             pos = pos + 1
0581 
0582         buf=prototypes.buffer()
0583         eventsf.writetobuffer(buf, logtitle="New Calendar")
0584         self.writefile(self.calendarlocation, buf.getvalue())
0585         self.log("Your phone has to be rebooted due to the calendar changing")
0586         dict["rebootphone"]=True
0587 
0588         buf=prototypes.buffer()
0589         exceptionsf.writetobuffer(buf, logtitle="Writing calendar exceptions")
0590         self.writefile(self.calendarexceptionlocation, buf.getvalue())
0591 
0592         buf = prototypes.buffer()
0593         ringersf.writetobuffer(buf, logtitle="Writing calendar ringers")
0594         self.writefile(self.calendarringerlocation, buf.getvalue())
0595 
0596         # fix passed in dict
0597         dict['calendar']=newcal
0598 
0599         return dict
0600 
0601 #-------------------------------------------------------------------------------
0602 parentprofile=com_lgvx8500.Profile
0603 class Profile(parentprofile):
0604     protocolclass=Phone.protocolclass
0605     serialsname=Phone.serialsname
0606 
0607     BP_Calendar_Version=3
0608     phone_manufacturer='LG Electronics Inc'
0609     phone_model='VX8550'
0610     # inside screen resoluation
0611     WALLPAPER_WIDTH=176
0612     WALLPAPER_HEIGHT=220
0613 
0614     imageorigins={}
0615     imageorigins.update(common.getkv(parentprofile.stockimageorigins, "images"))
0616     imageorigins.update(common.getkv(parentprofile.stockimageorigins, "video"))
0617     imageorigins.update(common.getkv(parentprofile.stockimageorigins, "images(sd)"))
0618     imageorigins.update(common.getkv(parentprofile.stockimageorigins, "video(sd)"))
0619 
0620     # our targets are the same for all origins
0621     imagetargets={}
0622     imagetargets.update(common.getkv(parentprofile.stockimagetargets, "fullscreen",
0623                                       {'width': 238, 'height': 246, 'format': "JPEG"}))
0624     imagetargets.update(common.getkv(parentprofile.stockimagetargets, "wallpaper",
0625                                       {'width': 240, 'height': 274, 'format': "JPEG"}))
0626     imagetargets.update(common.getkv(parentprofile.stockimagetargets, "pictureid",
0627                                       {'width': 120, 'height': 100, 'format': "JPEG"}))
0628 
0629     _supportedsyncs=(
0630         ('phonebook', 'read', None),  # all phonebook reading
0631         ('calendar', 'read', None),   # all calendar reading
0632         ('wallpaper', 'read', None),  # all wallpaper reading
0633         ('ringtone', 'read', None),   # all ringtone reading
0634         ('call_history', 'read', None),# all call history list reading
0635         ('sms', 'read', None),         # all SMS list reading
0636         ('memo', 'read', None),        # all memo list reading
0637         ('phonebook', 'write', 'OVERWRITE'),  # only overwriting phonebook
0638         ('calendar', 'write', 'OVERWRITE'),   # only overwriting calendar
0639         ('wallpaper', 'write', 'MERGE'),      # merge and overwrite wallpaper
0640         ('wallpaper', 'write', 'OVERWRITE'),
0641         ('ringtone', 'write', 'MERGE'),      # merge and overwrite ringtone
0642         ('ringtone', 'write', 'OVERWRITE'),
0643         ('sms', 'write', 'OVERWRITE'),        # all SMS list writing
0644         ('memo', 'write', 'OVERWRITE'),       # all memo list writing
0645         ('t9_udb', 'write', 'OVERWRITE'),
0646         )
0647     if __debug__:
0648         _supportedsyncs+=(
0649         ('t9_udb', 'read', 'OVERWRITE'),
0650         )
0651 
0652 
0653     def convertphonebooktophone(self, helper, data):
0654         """Converts the data to what will be used by the phone
0655 
0656         @param data: contains the dict returned by getfundamentals
0657                      as well as where the results go"""
0658         results={}
0659 
0660         self.normalisegroups(helper, data)
0661 
0662         for pbentry in data['phonebook']:
0663             if len(results)==self.protocolclass.NUMPHONEBOOKENTRIES:
0664                 break
0665             e={} # entry out
0666             entry=data['phonebook'][pbentry] # entry in
0667             try:
0668                 # serials
0669                 serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', 0)
0670                 serial2=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial2', serial1)
0671 
0672                 e['serial1']=serial1
0673                 e['serial2']=serial2
0674                 for ss in entry["serials"]:
0675                     if ss["sourcetype"]=="bitpim":
0676                         e['bitpimserial']=ss
0677                 assert e['bitpimserial']
0678 
0679                 # name
0680                 e['name']=helper.getfullname(entry.get('names', []),1,1,32)[0]
0681 
0682                 # ice
0683                 e['ice']=entry.get('ice', None)
0684 
0685                 # categories/groups
0686                 cat=helper.makeone(helper.getcategory(entry.get('categories', []),0,1,32), None)
0687                 if cat is None:
0688                     e['group']=0
0689                 else:
0690                     key,value=self._getgroup(cat, data['groups'])
0691                     if key is not None:
0692                         e['group']=key
0693                     else:
0694                         # sorry no space for this category
0695                         e['group']=0
0696 
0697                 # email addresses
0698                 emails=helper.getemails(entry.get('emails', []) ,0,self.protocolclass.NUMEMAILS,48)
0699                 e['emails']=helper.filllist(emails, self.protocolclass.NUMEMAILS, "")
0700 
0701                 # phone numbers
0702                 # there must be at least one email address or phonenumber
0703                 minnumbers=1
0704                 if len(emails): minnumbers=0
0705                 numbers=helper.getnumbers(entry.get('numbers', []),minnumbers,self.protocolclass.NUMPHONENUMBERS)
0706                 e['numbertypes']=[]
0707                 e['numbers']=[]
0708                 e['speeddials']=[]
0709                 for numindex in range(len(numbers)):
0710                     num=numbers[numindex]
0711                     # deal with type
0712                     b4=len(e['numbertypes'])
0713                     type=num['type']
0714                     for i,t in enumerate(self.protocolclass.numbertypetab):
0715                         if type==t:
0716                             # some voodoo to ensure the second home becomes home2
0717                             if i in e['numbertypes'] and t[-1]!='2':
0718                                 type+='2'
0719                                 continue
0720                             e['numbertypes'].append(i)
0721                             break
0722                         if t=='none': # conveniently last entry
0723                             e['numbertypes'].append(i)
0724                             break
0725                     if len(e['numbertypes'])==b4:
0726                         # we couldn't find a type for the number
0727                         helper.add_error_message('Number %s (%s/%s) not supported and ignored.'%
0728                                                  (num['number'], e['name'], num['type']))
0729                         continue 
0730                     # deal with number
0731                     number=self.phonize(num['number'])
0732                     if len(number)==0:
0733                         # no actual digits in the number
0734                         continue
0735                     if len(number)>24: # get this number from somewhere sensible
0736                         # ::TODO:: number is too long and we have to either truncate it or ignore it?
0737                         number=number[:24] # truncate for moment
0738                     e['numbers'].append(number)
0739                     # deal with speed dial
0740                     sd=num.get("speeddial", None)
0741                     if sd is not None and \
0742                        sd>=self.protocolclass.FIRSTSPEEDDIAL and \
0743                        sd<=self.protocolclass.LASTSPEEDDIAL:
0744                         e['speeddials'].append(sd)
0745                     else:
0746                         e['speeddials'].append(None)
0747 
0748                 if len(e['numbers'])<minnumbers:
0749                     # we couldn't find any numbers
0750                     # for this entry, so skip it, entries with no numbers cause error
0751                     helper.add_error_message("Name: %s. No suitable numbers or emails found" % e['name'])
0752                     continue 
0753                 e['numbertypes']=helper.filllist(e['numbertypes'], self.protocolclass.NUMPHONENUMBERS, 0)
0754                 e['numbers']=helper.filllist(e['numbers'], self.protocolclass.NUMPHONENUMBERS, "")
0755                 e['speeddials']=helper.filllist(e['speeddials'], self.protocolclass.NUMPHONENUMBERS, None)
0756 
0757                 # ringtones, wallpaper
0758                 e['ringtone']=helper.getringtone(entry.get('ringtones', []), 'call', None)
0759                 e['wallpaper']=helper.getwallpaper(entry.get('wallpapers', []), 'call', None)
0760 
0761                 results[pbentry]=e
0762                 
0763             except helper.ConversionFailed:
0764                 continue
0765 
0766         data['phonebook']=results
0767         return data
0768 

Generated by PyXR 0.9.4