Package phones ::
Module com_lgvi125
|
|
1
2
3
4
5
6
7
8
9
10 """Communicate with the LG VI125 cell phone"""
11
12
13 import datetime
14 import re
15 import time
16 import cStringIO
17 import sha
18
19
20 import bpcalendar
21 import common
22 import commport
23 import copy
24 import p_lgvi125
25 import p_brew
26 import com_brew
27 import com_phone
28 import com_lg
29 import prototypes
30 import fileinfo
31 import call_history
32 import sms
33
34 -class Phone(com_phone.Phone,com_brew.BrewProtocol,com_lg.LGPhonebook,com_lg.LGIndexedMedia):
35 "Talk to the LG VI125 cell phone"
36
37 desc="LG-VI125"
38 wallpaperindexfilename="dloadindex/brewImageIndex.map"
39 ringerindexfilename="dloadindex/brewRingerIndex.map"
40 protocolclass=p_lgvi125
41 serialsname='lgvi125'
42
43 imagelocations=(
44
45 ( 10, "dloadindex/brewImageIndex.map", "brew/shared", "images", 30),
46 )
47
48 ringtonelocations=(
49
50 ( 50, "dloadindex/brewRingerIndex.map", "user/sound/ringer", "ringers", 30),
51 )
52
53 builtinimages=('Balloons', 'Soccer', 'Basketball', 'Bird',
54 'Sunflower', 'Puppy', 'Mountain House', 'Beach')
55
56 builtinringtones=( 'Ring 1', 'Ring 2', 'Ring 3', 'Ring 4', 'Ring 5',
57 'Ring 6', 'Alert 1', 'Alert 2', 'Alert 3', 'Alert 4', 'Alert 5',
58 'Alert 6', 'Moon light', 'Bumble Bee', 'Latin', 'Baroque',
59 'Lovable baby', 'LG sound', 'Love Song', 'Badinerie', 'Follow Me',
60 'Head & Shoulder', 'Lake Trance', 'Beethovan', 'Lets Play',
61 'Piano Concerto No.1', 'Pleasure', 'Leichte Kavallerie',
62 'Up & Down Melody', 'Vivaldi - Winter' )
63
64
65 - def __init__(self, logtarget, commport):
75
77 """Gets information fundamental to interopating with the phone and UI.
78
79 Currently this is:
80
81 - 'uniqueserial' a unique serial number representing the phone
82 - 'groups' the phonebook groups
83 - 'wallpaper-index' map index numbers to names
84 - 'ringtone-index' map index numbers to ringtone names
85
86 This method is called before we read the phonebook data or before we
87 write phonebook data.
88 """
89
90
91 self.log("Retrieving fundamental phone information")
92 self.log("Phone serial number")
93 results['uniqueserial']=sha.new(self.getfilecontents("nvm/$SYS.ESN")).hexdigest()
94
95 self.log("Reading group information")
96 buf=prototypes.buffer(self.getfilecontents("pim/pbookgroup.dat"))
97 g=self.protocolclass.pbgroups()
98 g.readfrombuffer(buf)
99 self.logdata("Groups read", buf.getdata(), g)
100 groups={}
101 for i in range(len(g.groups)):
102 if len(g.groups[i].name) and g.groups[i].number!=255:
103 groups[g.groups[i].number]={ 'ring': g.groups[i].ring, 'name': g.groups[i].name }
104 results['groups']=groups
105 self.getwallpaperindices(results)
106 self.getringtoneindices(results)
107 self.log("Fundamentals retrieved")
108 return results
109
111 self._setquicktext(result)
112 result['rebootphone']=True
113 return result
114
115 - def _setquicktext(self, result):
116 sf=self.protocolclass.sms_quick_text()
117 quicktext=result.get('canned_msg', [])
118 count=0
119 for entry in quicktext:
120 if count < self.protocolclass.SMS_CANNED_MAX_ITEMS:
121 sf.msgs.append(entry['text'][:self.protocolclass.SMS_CANNED_MAX_LENGTH-1])
122 count+=1
123 else:
124 break
125 if count!=0:
126
127 buf=prototypes.buffer()
128 sf.writetobuffer(buf)
129 self.logdata("Writing calendar", buf.getvalue(), sf)
130 self.writefile(self.protocolclass.SMS_CANNED_FILENAME, buf.getvalue())
131 return
132
138
172
173 - def _getquicktext(self):
174 quicks=[]
175 try:
176 buf=prototypes.buffer(self.getfilecontents("sms/mediacan000.dat"))
177 sf=self.protocolclass.sms_quick_text()
178 sf.readfrombuffer(buf)
179 self.logdata("SMS quicktext file sms/mediacan000.dat", buf.getdata(), sf)
180 for rec in sf.msgs:
181 if rec.msg!="":
182 quicks.append({ 'text': rec.msg, 'type': sms.CannedMsgEntry.user_type })
183 except com_brew.BrewNoSuchFileException:
184 pass
185 return quicks
186
208
236
238 out=""
239 for i in range(num_septets):
240 tmp = (msg[(i*7)/8].byte<<8) | msg[((i*7)/8) + 1].byte
241 bit_index = 9 - ((i*7) % 8)
242 out += chr((tmp >> bit_index) & 0x7f)
243 return out
244
246 data_len = ((msg[0].byte+1)*8+6)/7
247 seven_bits={}
248 raw={}
249 out={}
250
251
252 for i in range(0, (num_septets*7)/8+8, 7):
253 for k in range(7):
254 raw[i+6-k]=msg[i+k].byte
255
256 for i in range(num_septets+7):
257 tmp = (raw[(i*7)/8]<<8) | raw[((i*7)/8) + 1]
258 bit_index = 9 - ((i*7) % 8)
259 seven_bits[i] = (tmp >> bit_index) & 0x7f
260
261 i=0
262 for i in range(0, num_septets+7, 8):
263 for k in range(8):
264 if(i+7-k-data_len>=0):
265 if i+k<num_septets+7:
266 out[i+7-k-data_len]=seven_bits[i+k]
267 res=""
268 for i in range(num_septets-data_len):
269 res+=chr(out[i])
270 return res
271
273 result=""
274 for i in range(len):
275 if(raw[i].byte==10):
276 result+="0"
277 else:
278 result+="%d" % raw[i].byte
279 return result
280
281 - def getcallhistory(self, result):
282 res={}
283
284 self._readhistoryfile("pim/missed_log.dat", 'Missed', res)
285 self._readhistoryfile("pim/outgoing_log.dat", 'Outgoing', res)
286 self._readhistoryfile("pim/incoming_log.dat", 'Incoming', res)
287 result['call_history']=res
288 return result
289
290 - def _readhistoryfile(self, fname, folder, res):
291 try:
292 buf=prototypes.buffer(self.getfilecontents(fname))
293 ch=self.protocolclass.callhistory()
294 ch.readfrombuffer(buf)
295 self.logdata("Call History", buf.getdata(), ch)
296 for call in ch.calls:
297 if call.number=='' and call.name=='':
298 continue
299 entry=call_history.CallHistoryEntry()
300 entry.folder=folder
301 if call.duration:
302 entry.duration=call.duration
303 entry.datetime=((call.GPStime))
304 if call.number=='':
305 entry.number=call.name
306 else:
307 entry.number=call.number
308 res[entry.id]=entry
309 except com_brew.BrewNoSuchFileException:
310 pass
311 return
312
315
318
320 """Reads the phonebook data. The L{getfundamentals} information will
321 already be in result."""
322
323 pbook={}
324
325
326
327 self.mode=self.MODENONE
328 self.setmode(self.MODEBREW)
329 self.log("Reading number of phonebook entries")
330 req=self.protocolclass.pbinforequest()
331 res=self.sendpbcommand(req, self.protocolclass.pbinforesponse)
332 numentries=res.numentries
333 if numentries<0 or numentries>1000:
334 self.log("The phone is lying about how many entries are in the phonebook so we are doing it the hard way")
335 numentries=0
336 firstserial=None
337 loop=xrange(0,1000)
338 hardway=True
339 else:
340 self.log("There are %d entries" % (numentries,))
341 loop=xrange(0, numentries)
342 hardway=False
343
344 self.sendpbcommand(self.protocolclass.pbinitrequest(), self.protocolclass.pbinitresponse)
345 problemsdetected=False
346 dupecheck={}
347 for i in loop:
348 if hardway:
349 numentries+=1
350 req=self.protocolclass.pbreadentryrequest()
351 res=self.sendpbcommand(req, self.protocolclass.pbreadentryresponse)
352 self.log("Read entry "+`i`+" - "+res.entry.name)
353 entry=self.extractphonebookentry(res.entry, result)
354 if hardway and firstserial is None:
355 firstserial=res.entry.serial1
356 pbook[i]=entry
357 if res.entry.serial1 in dupecheck:
358 self.log("Entry %s has same serial as entry %s. This will cause problems." % (`entry`, dupecheck[res.entry.serial1]))
359 problemsdetected=True
360 else:
361 dupecheck[res.entry.serial1]=entry
362 self.progress(i, numentries, res.entry.name)
363
364 req=self.protocolclass.pbnextentryrequest()
365 res=self.sendpbcommand(req, self.protocolclass.pbnextentryresponse)
366 if hardway:
367
368 if res.serial==firstserial or res.serial==0:
369 break
370
371 self.progress(numentries, numentries, "Phone book read completed")
372
373 if problemsdetected:
374 self.log("There are duplicate serial numbers. See above for details.")
375 raise common.IntegrityCheckFailed(self.desc, "Data in phonebook is inconsistent. There are multiple entries with the same serial number. See the log.")
376
377 result['phonebook']=pbook
378 cats=[]
379 for i in result['groups']:
380 if result['groups'][i]['name']!='No Group':
381 cats.append(result['groups'][i]['name'])
382 result['categories']=cats
383 print "returning keys",result.keys()
384 return pbook
385
387 groups=data['groups']
388 keys=groups.keys()
389 keys.sort()
390
391 g=self.protocolclass.pbgroups()
392 sg=self.protocolclass.pbseqgroups()
393 for k in keys:
394 e=self.protocolclass.pbgroup()
395 e.number=k
396 e.unknown1=48
397 e.ring=groups[k]['ring']
398 e.unknown7=0
399 e.unknown8=0
400 e.name=groups[k]['name']
401 g.groups.append(e)
402
403 e=self.protocolclass.pbseqgroup()
404 e.number=k
405 e.unknown=48
406 sg.seqgroups.append(e)
407
408 for k in xrange(k+1,20):
409 e=self.protocolclass.pbseqgroup()
410 e.number=0
411 e.unknown=0
412 sg.seqgroups.append(e)
413
414 groupnums=[]
415 for k in range(self.protocolclass.NUMMAPGROUPS):
416 groupnums.append(-1);
417
418 for k in data['phonebook'].keys():
419 groupnums[data['phonebook'][k]['serial1']]=data['phonebook'][k]['group']
420
421 mg=self.protocolclass.pbmapgroups()
422 for k in range(len(groupnums)):
423 e=self.protocolclass.pbmapgroup()
424 if (groupnums[k]==-1):
425 e.number=255
426 e.unknown=255
427 else:
428 e.number=groupnums[k]
429 e.unknown=48
430 mg.mapgroups.append(e)
431
432 buffer=prototypes.buffer()
433 g.writetobuffer(buffer)
434 self.logdata("New group file", buffer.getvalue(), g)
435 self.writefile("pim/pbookgroup.dat", buffer.getvalue())
436
437 buffer=prototypes.buffer()
438 sg.writetobuffer(buffer)
439 self.logdata("New seqgroup file", buffer.getvalue(), sg)
440 self.writefile("pim/pbookseqgroup.dat", buffer.getvalue())
441
442 buffer=prototypes.buffer()
443 mg.writetobuffer(buffer)
444 self.logdata("New mapgroup file", buffer.getvalue(), mg)
445 self.writefile("pim/pbookmapgroup.dat", buffer.getvalue())
446
448 "Saves out the phonebook"
449 self.savegroups(data)
450
451 progressmax=len(data['phonebook'].keys())
452
453
454
455
456
457
458 serialupdates=[]
459 existingpbook={}
460 self.mode=self.MODENONE
461 self.setmode(self.MODEBREW)
462 self.setmode(self.MODEPHONEBOOK)
463
464 req=self.protocolclass.pbinforequest()
465 res=self.sendpbcommand(req, self.protocolclass.pbinforesponse)
466 numexistingentries=res.numentries
467 if numexistingentries<0 or numexistingentries>1000:
468 self.log("The phone is lying about how many entries are in the phonebook so we are doing it the hard way")
469 numexistingentries=0
470 firstserial=None
471 loop=xrange(0,1000)
472 hardway=True
473 else:
474 self.log("There are %d existing entries" % (numexistingentries,))
475 progressmax+=numexistingentries
476 loop=xrange(0, numexistingentries)
477 hardway=False
478 progresscur=0
479
480 self.sendpbcommand(self.protocolclass.pbinitrequest(), self.protocolclass.pbinitresponse)
481 for i in loop:
482
483 if hardway:
484 numexistingentries+=1
485 progressmax+=1
486 req=self.protocolclass.pbreadentryrequest()
487 res=self.sendpbcommand(req, self.protocolclass.pbreadentryresponse)
488
489 entry={ 'number': res.entry.serial1, 'serial1': res.entry.serial1,
490 'serial2': res.entry.serial2, 'name': res.entry.name}
491 assert entry['serial1']==entry['serial2']
492 self.log("Reading entry "+`i`+" - "+entry['name'])
493 if hardway and firstserial is None:
494 firstserial=res.entry.serial1
495 existingpbook[i]=entry
496 self.progress(progresscur, progressmax, "existing "+entry['name'])
497
498 req=self.protocolclass.pbnextentryrequest()
499 res=self.sendpbcommand(req, self.protocolclass.pbnextentryresponse)
500 progresscur+=1
501 if hardway:
502
503 if res.serial==firstserial or res.serial==0:
504 break
505
506
507
508 pbook=data['phonebook']
509 dellist=[]
510 for i in range(0, numexistingentries):
511 ii=existingpbook[i]
512 serial=ii['serial1']
513 item=self._findserial(serial, pbook)
514 if item is None:
515 dellist.append(i)
516
517 progressmax+=len(dellist)
518
519
520 for i in dellist:
521 progresscur+=1
522 numexistingentries-=1
523 ii=existingpbook[i]
524 self.log("Deleting entry "+`i`+" - "+ii['name'])
525 req=self.protocolclass.pbdeleteentryrequest()
526 req.entrynumber=ii['serial1']
527 req.serial1=ii['serial1']
528 req.serial2=ii['serial2']
529 self.sendpbcommand(req, self.protocolclass.pbdeleteentryresponse)
530 self.progress(progresscur, progressmax, "Deleting "+ii['name'])
531
532 del existingpbook[i]
533
534
535 counter=0
536
537 keys=existingpbook.keys()
538 existingserials=[]
539 keys.sort()
540 for i in keys:
541 progresscur+=1
542 ii=pbook[self._findserial(existingpbook[i]['serial1'], pbook)]
543 self.log("Rewriting entry "+`i`+" - "+ii['name'])
544 self.progress(progresscur, progressmax, "Rewriting "+ii['name'])
545 entry=self.makeentry(counter, ii, data)
546 counter+=1
547 existingserials.append(existingpbook[i]['serial1'])
548 req=self.protocolclass.pbupdateentryrequest()
549 req.entry=entry
550 res=self.sendpbcommand(req, self.protocolclass.pbupdateentryresponse)
551 serialupdates.append( ( ii["bitpimserial"],
552 {'sourcetype': self.serialsname, 'serial1': res.serial1, 'serial2': res.serial1,
553 'sourceuniqueid': data['uniqueserial']})
554 )
555 assert ii['serial1']==res.serial1
556
557
558 keys=pbook.keys()
559 keys.sort()
560 for i in keys:
561 ii=pbook[i]
562 print "looking for "+`ii['serial1']`+" "+`ii['name']`
563 if ii['serial1'] in existingserials:
564 continue
565 print "found new"
566 progresscur+=1
567 entry=self.makeentry(counter, ii, data)
568 counter+=1
569 self.log("Appending entry "+ii['name'])
570 self.progress(progresscur, progressmax, "Writing "+ii['name'])
571 req=self.protocolclass.pbappendentryrequest()
572 req.entry=entry
573 res=self.sendpbcommand(req, self.protocolclass.pbappendentryresponse)
574 serialupdates.append( ( ii["bitpimserial"],
575 {'sourcetype': self.serialsname, 'serial1': res.newserial, 'serial2': res.newserial,
576 'sourceuniqueid': data['uniqueserial']})
577 )
578 data["serialupdates"]=serialupdates
579
580 return data
581
582
584 """Searches dict to find entry with matching serial. If not found,
585 returns None"""
586 for i in dict:
587 if dict[i]['serial1']==serial:
588 return i
589 return None
590
592 "turn all negative keys into positive ones for index"
593 res={}
594 keys=d.keys()
595 keys.sort()
596 keys.reverse()
597 for k in keys:
598 if k<0:
599 for c in range(999999):
600 if c not in keys and c not in res:
601 break
602 res[c]=d[k]
603 else:
604 res[k]=d[k]
605 return res
606
608 """Return a phonebook entry in BitPim format. This is called from getphonebook."""
609 res={}
610
611 res['serials']=[ {'sourcetype': self.serialsname, 'serial1': entry.serial1, 'serial2': entry.serial2,
612 'sourceuniqueid': fundamentals['uniqueserial']} ]
613
614 res['names']=[ {'full': entry.name} ]
615
616 cat=fundamentals['groups'].get(entry.group, {'name': "No Group"})['name']
617 if cat!="No Group":
618 res['categories']=[ {'category': cat} ]
619
620 res['emails']=[]
621 for i in entry.emails:
622 if len(i.email):
623 res['emails'].append( {'email': i.email} )
624 if not len(res['emails']): del res['emails']
625
626 if 'url' in entry.getfields() and len(entry.url):
627 res['urls']=[ {'url': entry.url} ]
628
629 if 'memo' in entry.getfields() and len(entry.memo):
630 res['memos']=[ {'memo': entry.memo } ]
631
632
633 res['ringtones']=[]
634 if 'ringtone' in entry.getfields() and entry.ringtone!=self.protocolclass.NORINGTONE:
635 try:
636 tone=fundamentals['ringtone-index'][entry.ringtone]['name']
637 res['ringtones'].append({'ringtone': tone, 'use': 'call'})
638 except:
639 print "can't find ringtone for index",entry.ringtone
640 if len(res['ringtones'])==0:
641 del res['ringtones']
642 res=self._assignpbtypeandspeeddials(entry, res)
643 return res
644
661
676
677 - def makeentry(self, counter, entry, data):
678 """Creates pbentry object
679
680 @param counter: The new entry number
681 @param entry: The phonebook object (as returned from convertphonebooktophone) that we
682 are using as the source
683 @param data: The main dictionary, which we use to get access to media indices amongst
684 other things
685 """
686 e=self.protocolclass.pbentry()
687 e.avatar=0
688
689 for k in entry:
690
691
692 if k in ('emails', 'numbers', 'numbertypes', 'numberspeeddials'):
693 l=getattr(e,k)
694 for item in entry[k]:
695 l.append(item)
696 elif k=='ringtone':
697 e.ringtone=self._findmediainindex(data['ringtone-index'], entry['ringtone'], entry['name'], 'ringtone')
698 elif k in e.getfields():
699
700 setattr(e,k,entry[k])
701
702 e.unknown7=0
703 e.group=0
704 e.unknown12=1
705 return e
706
708 req=p_brew.memoryconfigrequest()
709 respc=p_brew.memoryconfigresponse
710
711 for baud in 0, 38400, 115200:
712 if baud:
713 if not self.comm.setbaudrate(baud):
714 continue
715 try:
716 self.sendbrewcommand(req, respc, callsetmode=False)
717 return True
718 except com_phone.modeignoreerrortypes:
719 pass
720 return False
721
722 brew_version_txt_key='ams_version.txt'
723 brew_version_file='ams/version.txt'
724 lgpbinfo_key='lgpbinfo'
725 esn_file_key='esn_file'
726 esn_file='nvm/$SYS.ESN'
727 my_model='VI125'
762
764
765 try:
766 if data is None:
767 s=self.getfilecontents(self.esn_file)
768 else:
769 s=data
770 if s:
771 s=s[85:89]
772 return '%02X%02X%02X%02X'%(ord(s[3]), ord(s[2]),
773 ord(s[1]), ord(s[0]))
774 except:
775 if __debug__:
776 raise
777
790
791 @classmethod
792 - def detectphone(_, coms, likely_ports, res, _module, _log):
793 if not likely_ports:
794
795 return None
796 for port in likely_ports:
797 if not res.has_key(port):
798 res[port]={ 'mode_modem': None, 'mode_brew': None,
799 'manufacturer': None, 'model': None,
800 'firmware_version': None, 'esn': None,
801 'firmwareresponse': None }
802 try:
803 if res[port]['mode_brew']==False or \
804 res[port]['model']:
805
806
807 continue
808 p=_module.Phone(_log, commport.CommConnection(_log, port, timeout=1))
809 if res[port]['mode_brew'] is None:
810 res[port]['mode_brew']=p.is_mode_brew()
811 if res[port]['mode_brew']:
812 p.get_detect_data(res[port])
813 p.eval_detect_data(res[port])
814 p.comm.close()
815 except:
816 if __debug__:
817 raise
818
819
821
822 try:
823 buf=prototypes.buffer(self.getfilecontents(
824 self.protocolclass.cal_exception_file_name))
825 ex=self.protocolclass.scheduleexceptionfile()
826 ex.readfrombuffer(buf)
827 self.logdata("Calendar exceptions", buf.getdata(), ex)
828 exceptions={}
829 for i in ex.items:
830 exceptions.setdefault(i.pos, []).append( (i.year,i.month,i.day) )
831 except com_brew.BrewNoSuchFileException:
832 exceptions={}
833
834
835 try:
836 buf=prototypes.buffer(self.getfilecontents(
837 self.protocolclass.cal_data_file_name))
838 if len(buf.getdata())<2:
839
840 raise com_brew.BrewNoSuchFileException()
841 sc=self.protocolclass.schedulefile()
842 self.logdata("Calendar", buf.getdata(), sc)
843 sc.readfrombuffer(buf)
844 sc.readfrombuffer(buf)
845 res=self.get_cal(sc, exceptions, result.get('ringtone-index', {}))
846 except com_brew.BrewNoSuchFileException:
847 res={}
848 result['calendar']=res
849 return result
850
852
853
854 voice_files={}
855 if self._cal_has_voice_id:
856 try:
857 file_list=self.getfilesystem(self.protocolclass.cal_dir)
858 for k in file_list.keys():
859 if k.endswith(self.protocolclass.cal_voice_ext):
860 voice_files[int(k[8:11])]=k
861 except:
862 self.log('Failed to list Calendar Voice Files')
863
864 sc=self.protocolclass.schedulefile()
865 sc_ex=self.set_cal(sc, dict.get('calendar', {}),
866 dict.get('ringtone-index', {}),
867 voice_files)
868 buf=prototypes.buffer()
869 sc.writetobuffer(buf)
870 self.writefile(self.protocolclass.cal_data_file_name,
871 buf.getvalue())
872
873 exceptions_file=self.protocolclass.scheduleexceptionfile()
874 for k,l in sc_ex.items():
875 for x in l:
876 _ex=self.protocolclass.scheduleexception()
877 _ex.pos=k
878 _ex.year, _ex.month, _ex.day=x
879 exceptions_file.items.append(_ex)
880 buf=prototypes.buffer()
881 exceptions_file.writetobuffer(buf)
882 self.writefile(self.protocolclass.cal_exception_file_name,
883 buf.getvalue())
884
885 if self._cal_has_voice_id:
886 for k,e in voice_files.items():
887 try:
888 self.rmfile(e)
889 except:
890 self.log('Failed to delete file '+e)
891 return dict
892
893 _repeat_values={
894 protocolclass.CAL_REP_DAILY: bpcalendar.RepeatEntry.daily,
895 protocolclass.CAL_REP_MONFRI: bpcalendar.RepeatEntry.daily,
896 protocolclass.CAL_REP_WEEKLY: bpcalendar.RepeatEntry.weekly,
897 protocolclass.CAL_REP_MONTHLY: bpcalendar.RepeatEntry.monthly,
898 protocolclass.CAL_REP_YEARLY: bpcalendar.RepeatEntry.yearly
899 }
900
916
918 if event.hasvoice:
919 entry.voice=event.voiceid
920
921 - def _build_cal_entry(self, event, exceptions, ringtone_index):
922
923
924 entry=bpcalendar.CalendarEntry()
925 entry.start=event.start
926 entry.end=event.end
927 entry.description=event.description
928
929 if entry.start[3:]==(0, 0) and entry.end[3:]==(23, 59):
930 entry.allday=True
931
932 if event.alarmtype:
933 entry.alarm=event.alarmhours*60+event.alarmminutes
934
935 rt_idx=event.ringtone
936
937 if rt_idx<50:
938
939 rt_idx+=1
940 entry.ringtone=ringtone_index.get(rt_idx, {'name': None} )['name']
941
942 if self._cal_has_voice_id:
943 self._get_voice_id(event, entry)
944
945 entry.repeat=self._build_cal_repeat(event, exceptions)
946 return entry
947
948 - def get_cal(self, sch_file, exceptions, ringtone_index):
949 res={}
950 for event in sch_file.events:
951 if event.pos==-1:
952 continue
953 cal_event=self._build_cal_entry(event, exceptions, ringtone_index)
954 res[cal_event.id]=cal_event
955 return res
956
957 _alarm_info={
958 -1: (protocolclass.CAL_REMINDER_NONE, 100, 100),
959 0: (protocolclass.CAL_REMINDER_ONTIME, 0, 0),
960 5: (protocolclass.CAL_REMINDER_5MIN, 5, 0),
961 10: (protocolclass.CAL_REMINDER_10MIN, 10, 0),
962 60: (protocolclass.CAL_REMINDER_1HOUR, 0, 1),
963 1440: (protocolclass.CAL_REMINDER_1DAY, 0, 24),
964 2880: (protocolclass.CAL_REMINDER_2DAYS, 0, 48) }
965 _default_alarm=(protocolclass.CAL_REMINDER_NONE, 100, 100)
966 _phone_dow={
967 1: protocolclass.CAL_DOW_SUN,
968 2: protocolclass.CAL_DOW_MON,
969 4: protocolclass.CAL_DOW_TUE,
970 8: protocolclass.CAL_DOW_WED,
971 16: protocolclass.CAL_DOW_THU,
972 32: protocolclass.CAL_DOW_FRI,
973 64: protocolclass.CAL_DOW_SAT
974 }
975
1013
1027
1037
1038 - def _set_cal_event(self, event, entry, exceptions, ringtone_index,
1039 voice_files):
1069
1070 - def set_cal(self, sch_file, cal_dict, ringtone_index, voice_files):
1071 sch_file.numactiveitems=len(cal_dict)
1072 exceptions={}
1073 _pos=2
1074 _packet_size=None
1075
1076 for k, e in cal_dict.items():
1077
1078
1079 event=self.protocolclass.scheduleevent()
1080 event.pos=_pos
1081 self._set_cal_event(event, e, exceptions, ringtone_index,
1082 voice_files)
1083 sch_file.events.append(event)
1084 if not _packet_size:
1085 _packet_size=event.packetsize()
1086 _pos+=_packet_size
1087 return exceptions
1088
1090
1091 s=''
1092 try:
1093 buf=self.getfilecontents('nvm/nvm/nvm_0000')
1094 ofs=0xce
1095 if buf[ofs]=='\x01':
1096 ofs+=1
1097 while buf[ofs]!='\x01':
1098 s+=buf[ofs]
1099 ofs+=1
1100 except:
1101 if __debug__:
1102 raise
1103 return s
1122
1124 """Convert the phone number into something the phone understands
1125
1126 All digits, P, T, * and # are kept, everything else is removed"""
1127 return re.sub("[^0-9PT#*]", "", str)
1128
1129 parentprofile=com_phone.Profile
1131 protocolclass=Phone.protocolclass
1132 serialsname=Phone.serialsname
1133 BP_Calendar_Version=3
1134 phone_manufacturer='LG Electronics Inc'
1135 phone_model='VI125'
1136
1137 WALLPAPER_WIDTH=120
1138 WALLPAPER_HEIGHT=98
1139 MAX_WALLPAPER_BASENAME_LENGTH=19
1140 WALLPAPER_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789 ."
1141 WALLPAPER_CONVERT_FORMAT="bmp"
1142
1143 MAX_RINGTONE_BASENAME_LENGTH=19
1144 RINGTONE_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789 ."
1145
1146
1147 usbids_straight=( ( 0x1004, 0x6000, 2), )
1148 usbids_usbtoserial=(
1149 ( 0x067b, 0x2303, None),
1150 ( 0x0403, 0x6001, None),
1151 ( 0x0731, 0x2003, None),
1152 )
1153 usbids=usbids_straight+usbids_usbtoserial
1154
1155
1156 deviceclasses=("serial",)
1157
1158
1159 imageorigins={}
1160 imageorigins.update(common.getkv(parentprofile.stockimageorigins, "images"))
1163
1164
1165 imagetargets={}
1166 imagetargets.update(common.getkv(parentprofile.stockimagetargets, "wallpaper",
1167 {'width': 120, 'height': 98, 'format': "BMP"}))
1168 imagetargets.update(common.getkv(parentprofile.stockimagetargets, "pictureid",
1169 {'width': 120, 'height': 98, 'format': "BMP"}))
1170 imagetargets.update(common.getkv(parentprofile.stockimagetargets, "fullscreen",
1171 {'width': 120, 'height': 133, 'format': "BMP"}))
1172
1175
1178
1179
1185
1186
1188 "Assigns groups based on category data"
1189
1190 pad=[]
1191 keys=data['groups'].keys()
1192 keys.sort()
1193 for k in keys:
1194 if k:
1195 name=data['groups'][k]['name']
1196 pad.append(name)
1197
1198 groups=helper.getmostpopularcategories(10, data['phonebook'], ["No Group"], 22, pad)
1199
1200
1201 groups.sort()
1202
1203
1204 newgroups={}
1205
1206
1207 newgroups[0]={'ring': 0, 'name': 'No Group'}
1208
1209
1210 for name in groups:
1211
1212 if name=="No Group": continue
1213 key,value=self._getgroup(name, data['groups'])
1214 if key is not None and key!=0:
1215 newgroups[key]=value
1216
1217 for name in groups:
1218 key,value=self._getgroup(name, newgroups)
1219 if key is None:
1220 for key in range(1,100000):
1221 if key not in newgroups:
1222 newgroups[key]={'ring': 0, 'name': name}
1223 break
1224
1225
1226 if data['groups']!=newgroups:
1227 data['groups']=newgroups
1228 data['rebootphone']=True
1229
1231 """Converts the data to what will be used by the phone
1232
1233 @param data: contains the dict returned by getfundamentals
1234 as well as where the results go"""
1235 results={}
1236
1237 self.normalisegroups(helper, data)
1238
1239 for pbentry in data['phonebook']:
1240 if len(results)==self.protocolclass.NUMPHONEBOOKENTRIES:
1241 break
1242 e={}
1243 entry=data['phonebook'][pbentry]
1244 try:
1245
1246 serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', 0)
1247 serial2=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial2', serial1)
1248
1249 e['serial1']=serial1
1250 e['serial2']=serial2
1251 for ss in entry["serials"]:
1252 if ss["sourcetype"]=="bitpim":
1253 e['bitpimserial']=ss
1254 assert e['bitpimserial']
1255
1256
1257 e['name']=helper.getfullname(entry.get('names', []),1,1,22)[0]
1258
1259
1260 cat=helper.makeone(helper.getcategory(entry.get('categories', []),0,1,22), None)
1261 if cat is None:
1262 e['group']=0
1263 else:
1264 key,value=self._getgroup(cat, data['groups'])
1265 if key is not None:
1266 e['group']=key
1267 else:
1268
1269 e['group']=0
1270
1271
1272 emails=helper.getemails(entry.get('emails', []) ,0,self.protocolclass.NUMEMAILS,48)
1273 e['emails']=helper.filllist(emails, self.protocolclass.NUMEMAILS, "")
1274
1275
1276 e['url']=helper.makeone(helper.geturls(entry.get('urls', []), 0,1,48), "")
1277
1278
1279 e['memo']=helper.makeone(helper.getmemos(entry.get('memos', []), 0, 1, self.protocolclass.MEMOLENGTH-1), "")
1280
1281
1282
1283 minnumbers=1
1284 if len(emails): minnumbers=0
1285 numbers=helper.getnumbers(entry.get('numbers', []),minnumbers,self.protocolclass.NUMPHONENUMBERS)
1286 e['numberspeeddials']=[]
1287 e['numbertypes']=[]
1288 e['numbers']=[]
1289 for numindex in range(len(numbers)):
1290 num=numbers[numindex]
1291
1292 b4=len(e['numbertypes'])
1293 type=num['type']
1294 for i,t in enumerate(self.protocolclass.numbertypetab):
1295 if type==t:
1296
1297 if i in e['numbertypes'] and t[-1]!='2':
1298 type+='2'
1299 continue
1300 e['numbertypes'].append(i)
1301 break
1302 if t=='none':
1303 e['numbertypes'].append(i)
1304 break
1305 if len(e['numbertypes'])==b4:
1306
1307 continue
1308
1309 number=phonize(num['number'])
1310 if len(number)==0:
1311
1312 continue
1313 if len(number)>48:
1314
1315 number=number[:48]
1316 e['numbers'].append(number)
1317
1318 sd=num.get("speeddial", -1)
1319 if self.protocolclass.NUMSPEEDDIALS:
1320 if sd>=self.protocolclass.FIRSTSPEEDDIAL and sd<=self.protocolclass.LASTSPEEDDIAL:
1321 e['numberspeeddials'].append(sd)
1322 else:
1323 e['numberspeeddials'].append(255)
1324
1325 e['numberspeeddials']=helper.filllist(e['numberspeeddials'], 5, 255)
1326 e['numbertypes']=helper.filllist(e['numbertypes'], 5, 0)
1327 e['numbers']=helper.filllist(e['numbers'], 5, "")
1328
1329
1330 e['ringtone']=helper.getringtone(entry.get('ringtones', []), 'call', None)
1331
1332
1333 e['secret']=helper.getflag(entry.get('flags',[]), 'secret', False)
1334
1335 results[pbentry]=e
1336
1337 except helper.ConversionFailed:
1338 continue
1339
1340 data['phonebook']=results
1341 return data
1342
1343 _supportedsyncs=(
1344 ('phonebook', 'read', None),
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357 )
1358
1359 - def QueryAudio(self, origin, currentextension, afi):
1360
1361 if afi.format in ("MIDI", "QCP", "PMD"):
1362 return currentextension, afi
1363
1364 if afi.format=="MP3":
1365 if afi.channels==1 and 8<=afi.bitrate<=64 and 16000<=afi.samplerate<=22050:
1366 return currentextension, afi
1367
1368 return ("mp3", fileinfo.AudioFileInfo(afi, **{'format': 'MP3', 'channels': 1, 'bitrate': 32, 'samplerate': 22050}))
1369