Package phones ::
Module com_samsungscha670
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """Communicate with a Samsung SCH-A670"""
16
17
18 import re
19 import sha
20 import time
21
22
23 import common
24 import commport
25 import com_brew
26 import com_samsung
27 import com_phone
28 import conversions
29 import fileinfo
30 import nameparser
31 import p_samsungscha670
32 import prototypes
33
34
35 -class Phone(com_samsung.Phone):
36 "Talk to the Samsung SCH-A670 Cell Phone"
37
38 desc="SCH-A670"
39 serialsname='scha670'
40 protocolclass=p_samsungscha670
41 parent_phone=com_samsung.Phone
42
43 __groups_range=xrange(5)
44 __phone_entries_range=xrange(1,501)
45 __pb_atpbokw_field_count=26
46
47 __pb_max_speeddials=500
48 __pb_entry=0
49 __pb_mem_loc=1
50 __pb_group=2
51 __pb_ringtone=3
52 __pb_name=4
53 __pb_speed_dial=5
54 __pb_home_num=7
55 __pb_office_num=9
56 __pb_mobile_num=11
57 __pb_pager_num=13
58 __pb_fax_num=15
59 __pb_alias=17
60 __pb_blanks=(19, 20)
61 __pb_email=21
62 __pb_image_assign=22
63 __pb_image_id=23
64 __pb_contact_image=24
65 __pb_date_time_stamp=25
66 __pb_numbers= ({'home': __pb_home_num},
67 {'office': __pb_office_num},
68 {'cell': __pb_mobile_num},
69 {'pager': __pb_pager_num},
70 {'fax': __pb_fax_num})
71 __pb_max_name_len=22
72 __pb_max_number_len=32
73 __pb_max_emails=1
74 __pb_max_email_chars=48
75 __pb_max_alias_chars=48
76 __wp_photo_dir="digital_cam"
77 __wp_header_bytes=96
78 __wp_ts_offset=47
79 __wp_index_file = "nvm/nvm/brew_image"
80 __rt_index_file = "nvm/nvm/brew_melody"
81 __rt_dir = "brew/ringer"
82 __wp_dir = "brew/shared"
83
84
85
86
87 builtinringtones=( 'Inactive',
88 'Bell 1', 'Bell 2', 'Bell 3', 'Bell 4', 'Bell 5',
89 'Melody 1', 'Melody 2', 'Melody 3', 'Melody 4', 'Melody 5',
90 'Melody 6', 'Melody 7', 'Melody 8', 'Melody 9', 'Melody 10',
91 'User 00', 'User 01', 'User 02', 'User 03', 'User 04', 'User 05',
92 'User 06', 'User 07', 'User 08', 'User 09', 'User 10', 'User 11',
93 'User 12', 'User 13', 'User 14', 'User 15', 'User 16', 'User 17',
94 'User 18', 'User 19')
95 allringtones={}
96
97
98 __ringtone_info=('ringtone', 'ringtone-index', 'ringtone', 'brew/ringer', 19, 20)
99 __wallpaper_info=('wallpapers', 'wallpaper-index', 'images', 'mms_image', 19, 10)
100
101 __camerapix_info=('wallpapers', 'wallpaper-index', 'camera', 'digital_cam', 19, 40)
102 __video0_info=('wallpapers', 'wallpaper-index', 'video', 'camcoder0', None, None)
103 __video1_info=('wallpapers', 'wallpaper-index', 'video', 'camcoder1', None, None)
104
105 - def __init__(self, logtarget, commport):
110
112
113 """Gets information fundamental to interoperating with the phone and UI.
114
115 Currently this is:
116
117 - 'uniqueserial' a unique serial number representing the phone
118 - 'groups' the phonebook groups
119 - 'wallpaper-index' map index numbers to names
120 - 'ringtone-index' map index numbers to ringtone names
121
122 This method is called before we read the phonebook data or before we
123 write phonebook data.
124 """
125
126 self.setmode(self.MODEPHONEBOOK)
127
128
129
130 self.log("Retrieving fundamental phone information")
131 self.log("Reading phone serial number")
132 results['uniqueserial']=sha.new(self.get_esn()).hexdigest()
133
134
135
136 self.log("Reading group information")
137 g=self.get_groups(self.__groups_range)
138 groups={}
139 for i, g_i in enumerate(g):
140 if len(g_i):
141 groups[i]={ 'name': g_i }
142 results['groups']=groups
143
144
145 self.setmode(self.MODEBREW)
146 rt_index=RingtoneIndex(self)
147 results['ringtone-index']=rt_index.get()
148
149
150 img_index=ImageIndex(self)
151 results['wallpaper-index']=img_index.get()
152
153 self.setmode(self.MODEMODEM)
154 self.log("Fundamentals retrieved")
155
156 return results
157
159 r={}
160 for k, n in enumerate(self.builtinringtones):
161 r[k]={ 'name': n, 'origin': 'builtin' }
162 return r
163
165 r={}
166 s=self.comm.sendatcommand("#PUGSN?")
167 for rt in s[1:]:
168 this_r = rt.split(",")
169 r[int(this_r[0])] = { 'name': this_r[2], 'origin': 'builtin' }
170 self.allringtones[int(this_r[0])] = this_r[2]
171 return r
172
174 bi_cnt = len(r)
175 rtlist = self.getfilecontents(self.__rt_index_file)
176 offset=0
177 while offset < (40 * 77):
178 rtid = ord(rtlist[offset+1])
179 rtlen = ord(rtlist[offset+74])
180 rtname = rtlist[offset+23:offset+23+rtlen][len(self.__rt_dir)+1:]
181 if rtlen > 0:
182 r[rtid + bi_cnt] = { 'name': rtname, 'origin': 'ringtone' }
183 self.allringtones[rtid + bi_cnt] = rtname
184 offset+=77
185 return r
186
188 wpi = {}
189 imglist = self.getfilecontents(self.__wp_index_file)
190 offset=0
191 while offset < (30 * 76):
192 imgid = ord(imglist[offset+1])
193 imglen = ord(imglist[offset+73])
194 imgname = imglist[offset+22:offset+22+imglen][len(self.__wp_dir)+1:]
195 if imglen > 0:
196 wpi[imgid] = { 'name': imgname, 'origin': 'wallpaper' }
197 offset+=76
198 return wpi
199
223
225 """Reads the phonebook data. The L{getfundamentals} information will
226 already be in result."""
227 pb_book=self._get_phonebook(result)
228 result['phonebook']=pb_book
229 return pb_book
230
232
233 res={}
234
235 res['serials']=[ {'sourcetype': self.serialsname,
236 'sourceuniqueid': fundamentals['uniqueserial'],
237 'serial1': entry[self.__pb_entry],
238 'serial2': entry[self.__pb_mem_loc] }]
239
240 res['names']=[ {'full': unicode(entry[self.__pb_name].replace('"', ''),
241 errors='ignore') } ]
242 if len(entry[self.__pb_alias]):
243 res['urls']=[ {'url': entry[self.__pb_alias] } ]
244
245
246 g=fundamentals['groups']
247 i=int(entry[self.__pb_group])
248 res['categories']=[ {'category': g[i]['name'] } ]
249
250
251 s=entry[self.__pb_email].replace('"', '')
252 if len(s):
253 res['emails']=[ { 'email': s } ]
254
255
256
257
258
259
260 if entry[self.__pb_image_assign]=='3':
261
262 res['wallpapers']=[ { 'wallpaper': entry[self.__pb_contact_image].split( "/")[1]+".jpg",
263 'use': 'call' } ]
264 elif entry[self.__pb_image_assign]=='4':
265
266 wp_index=fundamentals.get('wallpaper-index', {})
267 try:
268 res['wallpapers']=[{ 'wallpaper': wp_index[int(entry[self.__pb_image_id])]['name'],
269 'use': 'call'} ]
270 except:
271 pass
272
273
274 try:
275 rt_index=fundamentals.get('ringtone-index', {})
276 res['ringtones']=[ { 'ringtone': rt_index[int(entry[self.__pb_ringtone])]['name'],
277 'use': 'call' } ]
278 except:
279 res['ringtones']=[ { 'ringtone': self.builtinringtones[0],
280 'use': 'call' } ]
281
282
283
284 speed_dial=int(entry[self.__pb_speed_dial])
285 res['numbers']=[]
286 for k, n in enumerate(self.__pb_numbers):
287 for key in n:
288 if len(entry[n[key]]):
289 if speed_dial==k:
290 res['numbers'].append({ 'number': entry[n[key]],
291 'type': key,
292 'speeddial': int(entry[self.__pb_mem_loc])})
293 else:
294 res['numbers'].append({ 'number': entry[n[key]],
295 'type': key })
296
297 return res
298
300 "Saves out the phonebook"
301
302 pb_book=data['phonebook']
303 pb_groups=data['groups']
304 ringtone_index=data.get('ringtone-index', {})
305 self.log('Validating phonebook entries.')
306 del_entries=[]
307 for k in pb_book:
308 if not self.__validate_entry(pb_book[k], pb_groups, ringtone_index):
309 self.log('Invalid entry, entry will be not be sent.')
310 del_entries.append(k)
311 for k in del_entries:
312 self.log('Deleting entry '+\
313 nameparser.getfullname(pb_book[k]['names'][0]))
314 del pb_book[k]
315 self._has_duplicate_speeddial(pb_book)
316 self.log('All entries validated')
317
318 pb_locs=[False]*(len(self.__phone_entries_range)+1)
319 pb_mem=[False]*len(pb_locs)
320
321
322 self.log("Getting current phonebook from the phone")
323 current_pb=self._get_phonebook(data)
324
325
326 self.log("Processing speeddial data")
327 for k in pb_book:
328 self._update_speeddial(pb_book[k])
329
330
331 self.setmode(self.MODEPHONEBOOK)
332 self.log("Processing deleted entries")
333
334 for k1 in current_pb:
335 s1=current_pb[k1]['serials'][0]['serial1']
336 found=False
337 for k2 in pb_book:
338 if self._same_serial1(s1, pb_book[k2]):
339 found=True
340 break
341 if found:
342 pb_locs[int(current_pb[k1]['serials'][0]['serial1'])]=True
343 pb_mem[int(current_pb[k1]['serials'][0]['serial2'])]=True
344 else:
345 self.log("Deleted item: "+\
346 nameparser.getfullname(current_pb[k1]['names'][0]))
347
348 self.progress(0, 10, "Deleting "+\
349 nameparser.getfullname(\
350 current_pb[k1]['names'][0]))
351 self._del_phone_entry(current_pb[k1])
352 mem_idx, loc_idx = self.__pb_max_speeddials, 1
353
354
355 self.log("Processing new & updated entries")
356 serials_update=[]
357 progresscur, progressmax=1,len(pb_book)
358 for k in pb_book:
359 if progresscur>len(self.__phone_entries_range):
360 self.log('Max phone entries exceeded: '+str(progresscur))
361 break
362 e=pb_book[k]
363 if not self._has_serial1(e):
364 while pb_locs[loc_idx]:
365 loc_idx += 1
366 pb_locs[loc_idx]=True
367 sd=self._get_speeddial(e)
368 if sd:
369 mem_index=sd
370 pb_mem[sd]=True
371 else:
372 while pb_mem[mem_idx]:
373 mem_idx -= 1
374 pb_mem[mem_idx]=True
375 mem_index=mem_idx
376 self._set_speeddial(e, mem_idx)
377 s1={ 'sourcetype': self.serialsname,
378 'sourceuniqueid': data['uniqueserial'],
379 'serial1': `loc_idx`,
380 'serial2': `mem_index` }
381 e['serials'].append(s1)
382 self.log("New entries: Name: "+\
383 nameparser.getfullname(e['names'][0])+", s1: "+`loc_idx`+", s2: "+`mem_index`)
384 serials_update.append((self._bitpim_serials(e), s1))
385 self.progress(progresscur, progressmax, "Updating "+\
386 nameparser.getfullname(e['names'][0]))
387 if not self._write_phone_entry(e, data):
388 self.log("Failed to save entry: "+\
389 nameparser.getfullname(e['names'][0]))
390 progresscur += 1
391
392 data["serialupdates"]=serials_update
393 self.log("Done")
394 self.setmode(self.MODEMODEM)
395 return data
396
397
398 - def __validate_entry(self, pb_entry, pb_groups, ringtone_index):
399 try:
400
401 name=nameparser.getfullname(pb_entry['names'][0]).replace('"', '')
402 if len(name)>self.__pb_max_name_len:
403 name=name[:self.__pb_max_name_len]
404 pb_entry['names'][0].setdefault('full', name)
405
406 url=pb_entry.get('urls', [{}])[0].get('url', None)
407 if url is not None:
408 url=re.sub('[,"]', '', url)
409 if len(url)>self.__pb_max_alias_chars:
410 url=url[:self.__pb_max_alias_chars]
411 pb_entry['urls']=[ { 'url': url } ]
412
413 has_number_or_email=False
414 if pb_entry.has_key('numbers'):
415 for n in pb_entry['numbers']:
416 num=self.phonize(n['number'])
417 if len(num)>self.__pb_max_number_len:
418 num=num[:self.__pb_max_number_len]
419 if num != n['number']:
420 self.log('Updating number from '+n['number']+' to '+num)
421 n['number']=num
422 try:
423 self._get_number_type(n['type'])
424 except:
425 self.log(n['number']+': setting type to home.')
426 n['type']='home'
427 has_number_or_email=True
428
429 if pb_entry.has_key('emails'):
430 if len(pb_entry['emails'])>self.__pb_max_emails:
431 self.log(name+': Each entry can only have %s emails. The rest will be ignored.'%str(self.__pb_max_emails))
432 email=pb_entry['emails'][0]['email'].replace('"', '')
433 if len(email)>self.__pb_max_email_chars:
434 email=email[:self.__pb_max_email_chars]
435 if email!=pb_entry['emails'][0]['email']:
436 pb_entry['emails'][0]['email']=email
437 has_number_or_email=True
438 if not has_number_or_email:
439 self.log(name+': Entry has no numbers or emails')
440
441 return False
442
443 found=False
444 if pb_entry.has_key('categories') and len(pb_entry['categories']):
445 pb_cat=pb_entry['categories'][0]['category']
446 for k in pb_groups:
447 if pb_groups[k]['name']==pb_cat:
448 found=True
449 break
450 if not found:
451 self.log(name+': category set to '+pb_groups[0]['name'])
452 pb_entry['categories']=[{'category': pb_groups[0]['name']}]
453
454 found=False
455 if pb_entry.has_key('ringtones') and len(pb_entry['ringtones']):
456 pb_rt=pb_entry['ringtones'][0]['ringtone']
457 for k, rt in ringtone_index.items():
458 if pb_rt==rt['name']:
459 found=True
460 break
461 if not found:
462 rt=ringtone_index[0]['name']
463 self.log(name+': ringtone set to '+rt)
464 pb_entry['ringtones']=[{'ringtone': rt,
465 'use': 'call' }]
466
467
468
469 return True
470 except:
471 raise
472
474 b=[False]*(self.__pb_max_speeddials+1)
475 for k in pb_book:
476 try:
477 for k1, kk in enumerate(pb_book[k]['numbers']):
478 sd=kk['speeddial']
479 if sd and b[sd]:
480
481 del pb_book[k]['numbers'][k1]['speeddial']
482 self.log('speeddial %d exists, deleted'%sd)
483 else:
484 b[sd]=True
485 except:
486 pass
487 return False
488
502
504 n=pb_entry.get('numbers', [])
505 for k in n:
506 try:
507 if k['speeddial']:
508 return k['speeddial']
509 except:
510 pass
511 return 0
512
514 if not pb_entry.has_key('numbers'):
515
516 return
517 for k in pb_entry['numbers']:
518 if k.has_key('speeddial'):
519 k['speeddial']=sd
520 return
521 pb_entry['numbers'][0]['speeddial']=sd
522
523 - def _del_phone_entry(self, pb_entry):
524 try:
525 return self.save_phone_entry(self._my_serials(pb_entry)['serial1'])
526 except:
527 return False
528
530 for k in pb_entry['serials']:
531 if k['sourcetype']==self.serialsname and k.has_key('serial1'):
532 return k['serial1']==s1
533 return False
534
536 for k in pb_entry['serials']:
537 if k['sourcetype']==self.serialsname and k.has_key('serial1'):
538 return True
539 return False
540
542 for k in pb_entry['serials']:
543 if k['sourcetype']=="bitpim":
544 return k
545 return {}
546
548 for k in range(len(pb_entry['serials'])):
549 if pb_entry['serials'][k]['sourcetype']==self.serialsname:
550 del pb_entry['serials'][k]
551 return
552
554 for k in pb_entry['serials']:
555 if k['sourcetype']==self.serialsname:
556 return k
557 return {}
558
565
566 - def _write_phone_entry(self, pb_entry, data):
567
568
569 e=['0']*self.__pb_atpbokw_field_count
570
571
572 serials=self._my_serials(pb_entry)
573 e[self.__pb_entry]=serials['serial1']
574 e[self.__pb_mem_loc]=serials['serial2']
575
576
577 groups=data.get('groups', {})
578 e[self.__pb_group]='0'
579 try:
580 grp_name=pb_entry['categories'][0]['category']
581 for k, n in groups.items():
582 if n.get('name', None)==grp_name:
583 e[self.__pb_group]=`k`
584 break
585 except:
586 pass
587
588
589 ringtone_index=data.get('ringtone-index', {})
590 e[self.__pb_ringtone]='0'
591 try:
592 rt=pb_entry['ringtones'][0]['ringtone']
593 for k, n in ringtone_index.items():
594 if rt==n.get('name', None):
595 e[self.__pb_ringtone]=`k`
596 break
597 except:
598 pass
599
600
601 e[self.__pb_name]='"'+nameparser.getfullname(\
602 pb_entry['names'][0])+'"'
603 url=''
604 try:
605 url=pb_entry['urls'][0]['url']
606 except:
607 pass
608 e[self.__pb_alias]=url
609 if len(url):
610 e[self.__pb_alias+1]='0'
611 else:
612 e[self.__pb_alias+1]=''
613
614
615
616 for k in range(len(self.__pb_numbers)):
617 for kk in self.__pb_numbers[k]:
618 e[self.__pb_numbers[k][kk]]=''
619 e[self.__pb_numbers[k][kk]+1]=''
620 speed_dial='0'
621 n=pb_entry.get('numbers', [])
622 for k in range(len(n)):
623 try:
624 nk=n[k]
625 kkk, kk=self._get_number_type(nk['type'])
626 except:
627
628 nk['type']='home'
629 kkk, kk=0, self.__pb_home_num
630 e[kk],e[kk+1]=self.phonize(nk['number']),'0'
631 try:
632 if nk['speeddial']:
633 speed_dial=`kkk`
634 except:
635 pass
636 e[self.__pb_speed_dial]=speed_dial
637
638
639 email=''
640 try:
641 email=pb_entry['emails'][0]['email']
642 except:
643 pass
644 e[self.__pb_email]='"'+email+'"'
645
646
647
648 e[self.__pb_image_assign]='5'
649 e[self.__pb_image_id]='0'
650 e[self.__pb_contact_image]='""'
651 try:
652 imgName = pb_entry['wallpapers'][0]['wallpaper']
653 image_index=data.get('wallpaper-index', {})
654 for k, n in image_index.items():
655 if imgName==n.get('name', None):
656 if k>self.protocolclass.max_image_entries:
657
658 e[self.__pb_image_assign]='3'
659 e[self.__pb_contact_image]='"'+self.__wp_photo_dir+'/'+imgName.split('.')[0]+'"'
660 e[self.__pb_image_id]='0'
661 else:
662
663 e[self.__pb_image_assign]='4'
664 e[self.__pb_image_id]=`k`
665 e[self.__pb_contact_image]='""'
666 break
667 except:
668 pass
669
670 for k in self.__pb_blanks:
671 e[k]=''
672
673 e[self.__pb_date_time_stamp]=self.get_time_stamp()
674
675
676
677 ee=self.get_phone_entry(int(e[self.__pb_entry]))
678 if len(ee)==self.__pb_atpbokw_field_count:
679
680 ee[self.__pb_name]='"'+ee[self.__pb_name]+'"'
681 ee[self.__pb_email]='"'+ee[self.__pb_email]+'"'
682 ee[self.__pb_contact_image]='"'+ee[self.__pb_contact_image]+'"'
683
684 k=self.__pb_atpbokw_field_count-1
685 if e[:k]==ee[:k]:
686 return True
687 return self.save_phone_entry('0,'+','.join(e))
688
696
704
714
722
723 getmemo=parent_phone._getmemo
724 savememo=parent_phone._savememo
725
726 gettodo=parent_phone._gettodo
727 savetodo=parent_phone._savetodo
728
729 getsms=parent_phone._getsms
730 savesms=parent_phone._savesms
731
732 getphoneinfo=parent_phone._getphoneinfo
733
734 getmedia=None
735
736 -class Profile(com_samsung.Profile):
737
738 serialsname='scha670'
739
740 WALLPAPER_WIDTH=128
741 WALLPAPER_HEIGHT=128
742 MAX_WALLPAPER_BASENAME_LENGTH=19
743 WALLPAPER_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789_ ."
744
745 WALLPAPER_CONVERT_FORMAT="jpg"
746 MAX_RINGTONE_BASENAME_LENGTH=19
747 RINGTONE_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789_ ."
748 RINGTONE_LIMITS= {
749 'MAXSIZE': 30000
750 }
751
752 phone_manufacturer='SAMSUNG ELECTRONICS'
753 phone_model='SCH-A670/164'
754
757
758 _supportedsyncs=(
759 ('phonebook', 'read', None),
760 ('phonebook', 'write', 'OVERWRITE'),
761 ('calendar', 'read', None),
762 ('calendar', 'write', 'OVERWRITE'),
763 ('ringtone', 'read', None),
764 ('ringtone', 'write', 'OVERWRITE'),
765 ('wallpaper', 'read', None),
766 ('wallpaper', 'write', 'OVERWRITE'),
767 ('memo', 'read', None),
768 ('memo', 'write', 'OVERWRITE'),
769 ('todo', 'read', None),
770 ('todo', 'write', 'OVERWRITE'),
771 ('sms', 'read', None),
772 )
773
774 if __debug__:
775 _supportedsyncs+=(('sms', 'write', 'OVERWRITE'),)
776
779
780 __audio_ext={ 'MIDI': 'mid', 'PMD': 'pmd', 'QCP': 'pmd' }
781 - def QueryAudio(self, origin, currentextension, afi):
790
791 imageorigins={}
792 imageorigins.update(common.getkv(com_samsung.Profile.stockimageorigins, "images"))
793
794 imagetargets={}
795 imagetargets.update(common.getkv(com_samsung.Profile.stockimagetargets, "wallpaper",
796 {'width': 128, 'height': 128, 'format': "PNG"}))
797 imagetargets.update(common.getkv(com_samsung.Profile.stockimagetargets, "fullscreen",
798 {'width': 128, 'height': 160, 'format': "PNG"}))
799 imagetargets.update(common.getkv(com_samsung.Profile.stockimagetargets, "pictureid",
800 {'width': 96, 'height': 96, 'format': "JPEG"}))
801
805
810
813 self.__phone=phone
814 self.__file_type, self.__index_type, self.__origin, self.__path, self.__max_file_len, self.__max_file_count=info
815
822
849
882
883 - def get_video(self, result, video_file_name):
884 if not conversions.helperavailable('bmp2avi'):
885
886 self.__phone.log('Helper bmp2avi not found, cannot retrieve '+\
887 video_file_name)
888 return result
889 self.__phone.log('Getting video file '+video_file_name)
890 media=result.get(self.__file_type, {})
891 idx=result.get(self.__index_type, {})
892 tmp_avi_name=common.gettempfilename("avi")
893 try:
894 file_list=self.__phone.listfiles(self.__path)
895 except com_brew.BrewNoSuchDirectoryException:
896 file_list={}
897 except:
898 file_list={}
899 if __debug__: raise
900
901 if not len(file_list):
902
903 return result
904 file_keys=file_list.keys()
905 file_keys.sort();
906 for k in file_keys:
907 try:
908 conversions.convertjpgtoavi(self.__phone.getfilecontents(k, True)[96:],
909 tmp_avi_name)
910 except:
911 self.__phone.log('Failed to read video files')
912 if __debug__: raise
913
914 if len(idx):
915 idx_k=max(idx.keys())+1
916 else:
917 idx_k=0
918 media[video_file_name]=open(tmp_avi_name, 'rb').read()
919 idx[idx_k]={ 'name': video_file_name, 'origin': 'video' }
920 result[self.__file_type]=media
921 result[self.__index_type]=idx
922 try:
923 os.remove(tmp_avi_name)
924 except:
925 pass
926 return result
927
928 __mms_max_file_name_len=35
953
1028
1030 __builtin_ringtones=( 'Inactive',
1031 'Bell 1', 'Bell 2', 'Bell 3', 'Bell 4', 'Bell 5',
1032 'Melody 1', 'Melody 2', 'Melody 3', 'Melody 4', 'Melody 5',
1033 'Melody 6', 'Melody 7', 'Melody 8', 'Melody 9', 'Melody 10')
1034
1037
1039 r={}
1040 for k, n in enumerate(self.__builtin_ringtones):
1041 r[k]={ 'name': n, 'origin': 'builtin' }
1042 return r
1043
1061
1066
1082
1160