Package phones ::
Module com_samsungspha620
|
|
1
2
3
4
5
6
7
8
9
10
11 """Communicate with a Samsung SPH-A620"""
12
13 import sha
14 import re
15 import struct
16
17 import common
18 import commport
19 import p_samsungspha620
20 import p_brew
21 import com_brew
22 import com_phone
23 import com_samsung_packet
24 import prototypes
25 import fileinfo
26 import helpids
27
28 numbertypetab=('home','office','cell','pager','fax','none')
29
30 -class Phone(com_samsung_packet.Phone):
31 "Talk to a Samsung SPH-A620 phone"
32
33 desc="SPH-A620"
34 helpid=helpids.ID_PHONE_SAMSUNGOTHERS
35 protocolclass=p_samsungspha620
36 serialsname='spha620'
37
38
39
40 imagelocations=(
41
42
43 (400, "digital_cam/wallet", "camera", 100, 148),
44 (300, "digital_cam/jpeg", "camera", 100, 148),
45 )
46
47 ringtonelocations=(
48
49 )
50
51 __audio_mimetype={ 'mid': 'audio/midi', 'qcp': 'audio/vnd.qcelp', 'pmd': 'application/x-pmd'}
52 __image_mimetype={ 'jpg': 'image/jpg', 'jpeg': 'image/jpeg', 'gif': 'image/gif', 'bmp': 'image/bmp', 'png': 'image/png'}
53
54 - def __init__(self, logtarget, commport):
58
60 """Gets information fundamental to interopating with the phone and UI."""
61 self.amsanalyze(results)
62
63
64 self.log("Retrieving fundamental phone information")
65 self.log("Phone serial number")
66 self.setmode(self.MODEMODEM)
67 results['uniqueserial']=sha.new(self.get_esn()).hexdigest()
68
69 self.log("Reading group information")
70 results['groups']=self.read_groups()
71
72
73
74 self.log("Fundamentals retrieved")
75 return results
76
78 buf=prototypes.buffer(self.getfilecontents(self.protocolclass.AMSREGISTRY))
79 ams=self.protocolclass.amsregistry()
80 ams.readfrombuffer(buf, logtitle="Read AMS registry")
81 rt={}
82 nrt=0
83 wp={}
84 nwp=0
85 for i in range(ams.nfiles):
86 filetype=ams.info[i].filetype
87 if filetype:
88 dir_ptr=ams.info[i].dir_ptr
89 name_ptr=ams.info[i].name_ptr
90 mimetype_ptr=ams.info[i].mimetype_ptr
91 version_ptr=ams.info[i].version_ptr
92 vendor_ptr=ams.info[i].vendor_ptr
93 dir=self.getstring(ams.strings,dir_ptr)
94 name=self.getstring(ams.strings,name_ptr)
95 mimetype=self.getstring(ams.strings,mimetype_ptr)
96 version=self.getstring(ams.strings,version_ptr)
97 vendor=self.getstring(ams.strings,vendor_ptr)
98
99
100 print i, filetype, version, dir, vendor, name, mimetype
101
102
103 print ams.info[i].num2, ams.info[i].num7, ams.info[i].num8, ams.info[i].num9, ams.info[i].num12, ams.info[i].num13, ams.info[i].num14, ams.info[i].num15, ams.info[i].num16, ams.info[i].num17
104 print " "
105
106
107 if filetype==12:
108 if mimetype=="audio/vnd.qcelp":
109 filetype='.qcp'
110 elif mimetype=="audio/midi":
111 filetype='.mid'
112 elif mimetype=="application/x-pmd":
113 filetype='.pmd'
114 elif mimetype=="audio/mp3":
115 filetype='.mp3'
116 else:
117 filetype=''
118 rt[100+nrt]={'name':name+filetype,'location':'ams/'+dir,'origin':'ringers'}
119 nrt+=1
120 elif filetype==13:
121 if mimetype=="image/jpeg":
122 filetype='.jpg'
123 elif mimetype=="image/png":
124 filetype='.png'
125 elif mimetype=="image/gif":
126 filetype='.gif'
127 elif mimetype=="image/bmp":
128 filetype='.bmp'
129 else:
130 filetype=''
131 wp[100+nwp]={'name':name+filetype,'location':'ams/'+dir,'origin':'images'}
132 nwp+=1
133
134 results['ringtone-index']=rt
135 results['wallpaper-index']=wp
136
138 "Extend incomplete lines"
139
140
141 nfields=26
142 ncommas=self.countcommas(line)
143 if ncommas<0:
144 line+='"'
145 ncommas = -ncommas
146 if nfields-ncommas>1:
147 line=line+","*(nfields-ncommas-1)
148 return line
149
151 inquote=False
152 ncommas=0
153 for c in line:
154 if c == '"':
155 inquote = not inquote
156 elif not inquote and c == ',':
157 ncommas+=1
158
159 if inquote:
160 ncommas = -ncommas
161
162 return ncommas
163
167
171
172
219
242
256
258 "Get a null terminated string from contents"
259 i=start
260 while contents[i:i+1]!='\0':
261 i+=1
262 return contents[start:i]
263
264 - def makegcd(self, filename,size,mimetable):
265 "Build a GCD file for filename"
266 ext=common.getext(filename.lower())
267 try:
268 mimetype=mimetable[ext]
269 except:
270 return ""
271
272 noextname=common.stripext(filename)
273 gcdcontent="Content-Type: "+mimetype+"\nContent-Name: "+noextname+"\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file:"+filename+"\nContent-Size: "+`size`+"\n\n\n"
274 return gcdcontent
275
277 dircache=self.DirCache(self)
278 media_prefix=self.protocolclass.RINGERPREFIX
279 endtransactionpath=self.protocolclass.ENDTRANSACTION
280 media=result.get('ringtone', {})
281 media_index=result.get('ringtone-index', {})
282 media_names=[x['name'] for x in media.values()]
283 index_names=[x['name'] for x in media_index.values()]
284 if merge:
285 del_names=[]
286 else:
287 del_names=[common.stripext(x) for x in index_names if x not in media_names]
288 gcdpattern=re.compile("[\n\r]Content-Name: +(.*?)[\n\r]")
289 new_names=[x for x in media_names if x not in index_names]
290
291 progressmax=len(del_names)+len(new_names)
292 progresscur=0
293 self.log("Writing ringers")
294 self.progress(progresscur, progressmax, "Writing ringers")
295
296 for icnt in range(1,101):
297 if not (new_names or del_names):
298 break
299 fname=media_prefix+`icnt`
300 fnamegcd=media_prefix+`icnt`+".gcd"
301 fstat=dircache.stat(fnamegcd)
302 if del_names and fstat:
303
304 gcdcontents=dircache.readfile(fnamegcd)
305 thisfile=gcdpattern.search(gcdcontents).groups()[0]
306 if thisfile in del_names:
307 self.log("Deleting ringer "+thisfile)
308 self.progress(progresscur, progressmax, "Deleting ringer "+thisfile)
309 progresscur+=1
310 dircache.rmfile(fname)
311 dircache.rmfile(fnamegcd)
312 del_names.remove(thisfile)
313 fstat=False
314 if new_names and not fstat:
315 newname=new_names.pop()
316 contents=""
317 for k in media.keys():
318 if media[k]['name']==newname:
319 contents=media[k]['data']
320 break
321
322 contentsize=len(contents)
323 if contentsize:
324 gcdcontents=self.makegcd(newname,contentsize,self.__audio_mimetype)
325 self.log("Writing ringer "+newname)
326 self.progress(progresscur, progressmax, "Deleting ringer "+newname)
327 progresscur+=1
328 dircache.writefile(fname,contents)
329 dircache.writefile(fnamegcd,gcdcontents)
330
331 fstat=dircache.stat(endtransactionpath)
332 self.log("Finished writing ringers")
333 self.progress(progressmax, progressmax, "Finished writing ringers")
334 if fstat:
335 dircache.rmfile(endtransactionpath)
336 result['rebootphone']=True
337
338 return
339
341 dircache=self.DirCache(self)
342 media_prefix=self.protocolclass.WALLPAPERPREFIX
343 endtransactionpath=self.protocolclass.ENDTRANSACTION
344 media=result.get('wallpapers', {})
345 for i in media.keys():
346 try:
347 if media[i]['origin']=='camera':
348 del media[i]
349 except:
350 pass
351 media_index=result.get('wallpaper-index', {})
352 media_names=[x['name'] for x in media.values()]
353 index_names=[x['name'] for x in media_index.values()]
354 if merge:
355 del_names=[]
356 else:
357 del_names=[common.stripext(x) for x in index_names if x not in media_names]
358 gcdpattern=re.compile("[\n\r]Content-Name: +(.*?)[\n\r]")
359 new_names=[x for x in media_names if x not in index_names]
360
361 progressmax=len(del_names)+len(new_names)
362 progresscur=0
363 self.log("Writing images")
364 self.progress(progresscur, progressmax, "Writing images")
365
366 for icnt in range(1,101):
367 if not (new_names or del_names):
368 break
369 fname=media_prefix+`icnt`
370 fnamegcd=media_prefix+`icnt`+".gcd"
371 fstat=dircache.stat(fnamegcd)
372 if del_names and fstat:
373
374 gcdcontents=dircache.readfile(fnamegcd)
375 thisfile=gcdpattern.search(gcdcontents).groups()[0]
376 if thisfile in del_names:
377 self.log("Deleting image "+thisfile)
378 self.progress(progresscur, progressmax, "Deleting image "+thisfile)
379 progresscur+=1
380 dircache.rmfile(fname)
381 dircache.rmfile(fnamegcd)
382 del_names.remove(thisfile)
383 fstat=False
384 if new_names and not fstat:
385 newname=new_names.pop()
386 contents=""
387 for k in media.keys():
388 if media[k]['name']==newname:
389 contents=media[k]['data']
390 break
391
392 contentsize=len(contents)
393 if contentsize:
394 gcdcontents=self.makegcd(newname,contentsize,self.__image_mimetype)
395 self.log("Writing image "+newname)
396 self.progress(progresscur, progressmax, "Deleting image "+newname)
397 progresscur+=1
398 dircache.writefile(fname,contents)
399 dircache.writefile(fnamegcd,gcdcontents)
400
401 fstat=dircache.stat(endtransactionpath)
402 self.log("Finished writing images")
403 self.progress(progressmax, progressmax, "Finished writing images")
404 if fstat:
405 dircache.rmfile(endtransactionpath)
406 result['rebootphone']=True
407
408 return
409
410
411 -class Profile(com_samsung_packet.Profile):
412 protocolclass=Phone.protocolclass
413 serialsname=Phone.serialsname
414
415 MAX_RINGTONE_BASENAME_LENGTH=19
416 RINGTONE_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789_ ."
417 RINGTONE_LIMITS= {
418 'MAXSIZE': 250000
419 }
420 phone_manufacturer='SAMSUNG'
421 phone_model='SPH-A620/152'
422
426
427 _supportedsyncs=(
428 ('phonebook', 'read', None),
429 ('phonebook', 'write', 'OVERWRITE'),
430 ('wallpaper', 'read', None),
431 ('wallpaper', 'write', None),
432 ('ringtone', 'read', None),
433 ('ringtone', 'write', None),
434 ('calendar', 'read', None),
435 ('calendar', 'write', 'OVERWRITE'),
436 ('todo', 'read', None),
437 ('todo', 'write', 'OVERWRITE'),
438 ('memo', 'read', None),
439 ('memo', 'write', 'OVERWRITE'),
440 )
441
442 __audio_ext={ 'MIDI': 'mid', 'PMD': 'pmd', 'QCP': 'qcp' }
443 - def QueryAudio(self, origin, currentextension, afi):
453