Package phones :: Module com_samsungscha870
[hide private]
[frames] | no frames]

Source Code for Module phones.com_samsungscha870

  1  ### BITPIM 
  2  ### 
  3  ### Copyright (C) 2006 Joe Pham <djpham@bitpim.org> 
  4  ### Copyright (C) 2006 Stephen Wood <saw@bitpim.org> 
  5  ### 
  6  ### This program is free software; you can redistribute it and/or modify 
  7  ### it under the terms of the BitPim license as detailed in the LICENSE file. 
  8  ### 
  9  ### $Id: com_samsungscha870.py 4569 2008-01-15 01:03:05Z djpham $ 
 10   
 11  """Communicate with the Samsung SCH-A870 Phone""" 
 12   
 13  # System Models 
 14   
 15  # BitPim modules 
 16  import bpcalendar 
 17  import common 
 18  import helpids 
 19  import com_samsungscha950 as com_a950 
 20  import p_samsungscha950 as p_a950 
 21  import p_samsungscha870 as p_a870 
 22  import prototypes 
 23   
 24  parentphone=com_a950.Phone 
25 -class Phone(parentphone):
26 desc='SCH-A870' 27 helpid=helpids.ID_PHONE_SAMSUNGSCHA870 28 protocolclass=p_a870 29 serialsname='scha870' 30 31 # Detection stuff 32 my_model='SCH-A870/187' 33 my_manufacturer='SAMSUNG' 34 detected_model='A870' 35 36 ringtone_noring_range='range_tones_preloaded_el_15' 37 ringtone_default_range='range_tones_preloaded_el_01' 38 builtin_ringtones={ 39 'VZW Default Tone': 0x52, 40 'Melody 1': 0x56, 41 'Melody 2': 0x57, 42 'Melody 3': 0x58, 43 'Melody 4': 0x59, 44 'Melody 5': 0x5A, 45 'Melody 6': 0x5B, 46 'Bell 1': 0x53, 47 'Bell 2': 0x54, 48 'Bell 3': 0x55, 49 'Beep Once': 0x93, 50 'No Ring': 0xC2, 51 'Default': None, 52 } 53 builtin_sounds={ 54 'Clapping': 0x5C, 55 'Crowd': 0x5D, 56 'Happy Birthday': 0x5E, 57 'Rain Forest': 0x5F, 58 'Train': 0x60, 59 # same as ringtones ?? 60 } 61 builtin_wallpapers={ 62 'No Picture': None, 63 } 64
65 - def __init__(self, logtarget, commport):
66 "Calls all the constructors and sets initial modes" 67 parentphone.__init__(self, logtarget, commport) 68 global PBEntry, CalendarEntry 69 self.pbentryclass=PBEntry 70 self.calendarclass=CalendarEntry
71
72 - def getfilecontents(self, filename, use_cache=False):
73 if filename and filename[0]!='/': 74 return parentphone.getfilecontents(self, '/'+filename, use_cache) 75 return parentphone.getfilecontents(self, filename, use_cache)
76
77 - def get_groups(self):
78 _res={} 79 _buf=prototypes.buffer(self.getfilecontents(self.protocolclass.GROUP_INDEX_FILE_NAME)) 80 _index_file=self.protocolclass.GroupIndexFile() 81 _index_file.readfrombuffer(_buf) 82 for _entry in _index_file.items: 83 if _entry.name: 84 _res[_entry.index-1]={ 'name': _entry.name } 85 return _res
86
87 - def _get_dir_index(self, idx, result, pathname, origin, excludenames=()):
88 # build the index list by listing contents of the specified dir 89 for _path in self.listfiles(pathname): 90 _file=common.basename(_path) 91 if _file in excludenames: 92 continue 93 result[idx]={ 'name': _file, 94 'filename': _path, 95 'origin': origin, 96 } 97 idx+=1 98 return idx
99
100 - def get_ringtone_index(self):
101 _res={} 102 _idx=self._get_builtin_ringtone_index(0, _res) 103 _idx=self._get_dir_index(_idx, _res, 104 self.protocolclass.RT_PATH, 'ringers', 105 self.protocolclass.RT_EXCLUDED_FILES) 106 _idx=self._get_dir_index(_idx, _res, 107 self.protocolclass.SND_PATH, 'sounds', 108 self.protocolclass.SND_EXCLUDED_FILES) 109 return _res
110
111 - def _get_file_wallpaper_index(self, idx, result):
112 try: 113 _buf=prototypes.buffer(self.getfilecontents(self.protocolclass.PIC_INDEX_FILE_NAME)) 114 except (com_brew.BrewNoSuchFileException, 115 com_brew.BrewBadPathnameException, 116 com_brew.BrewFileLockedException, 117 com_brew.BrewAccessDeniedException): 118 return idx 119 except: 120 if __debug__: 121 raise 122 return idx 123 _index_file=self.protocolclass.PictureIndexFile() 124 _index_file.readfrombuffer(_buf) 125 for _entry in _index_file.items: 126 result[idx]={ 'name': _entry.name, 127 'filename': _entry.pathname, 128 'origin': 'images', 129 } 130 idx+=1 131 return idx
132
133 - def get_wallpaper_index(self):
134 _res={} 135 _idx=self._get_builtin_wallpaper_index(0, _res) 136 _idx=self._get_file_wallpaper_index(_idx, _res) 137 return _res
138
139 - def _get_del_new_list(self, index_key, media_key, merge, fundamentals, 140 origins):
141 """Return a list of media being deleted and being added""" 142 _index=fundamentals.get(index_key, {}) 143 _media=fundamentals.get(media_key, {}) 144 _index_file_list=[_entry['name'] for _entry in _index.values() \ 145 if _entry.has_key('filename') and \ 146 _entry.get('origin', None) in origins ] 147 _bp_file_list=[_entry['name'] for _entry in _media.values() \ 148 if _entry.get('origin', None) in origins ] 149 if merge: 150 # just add the new files, don't delete anything 151 _del_list=[] 152 _new_list=_bp_file_list 153 else: 154 # Delete specified files and add everything 155 _del_list=[x for x in _index_file_list if x not in _bp_file_list] 156 _new_list=_bp_file_list 157 return _del_list, _new_list
158
159 - def saveringtones(self, fundamentals, merge):
160 """Save ringtones to the phone""" 161 self.log('Writing ringtones to the phone') 162 try: 163 _del_list, _new_list=self._get_del_new_list('ringtone-index', 164 'ringtone', 165 merge, 166 fundamentals, 167 frozenset(('ringers', 'sounds'))) 168 if __debug__: 169 self.log('Delete list: '+','.join(_del_list)) 170 self.log('New list: '+','.join(_new_list)) 171 self._replace_files('ringtone-index', 'ringtone', 172 _new_list, fundamentals) 173 self._add_files('ringtone-index', 'ringtone', 174 _new_list, fundamentals) 175 fundamentals['rebootphone']=True 176 except: 177 if __debug__: 178 raise 179 return fundamentals
180
181 - def _add_files(self, index_key, media_key, 182 new_list, fundamentals):
183 """Add new file using BEW""" 184 _index=fundamentals.get(index_key, {}) 185 _media=fundamentals.get(media_key, {}) 186 _files_added=[] 187 for _file in new_list: 188 _data=self._item_from_index(_file, 'data', _media) 189 if not _data: 190 self.log('Failed to write file %s due to no data'%_file) 191 continue 192 if self._item_from_index(_file, None, _index) is None: 193 # new file 194 _origin=self._item_from_index(_file, 'origin', _media) 195 if _origin=='ringers': 196 _path=self.protocolclass.RT_PATH 197 elif _origin=='sounds': 198 _path=self.protocolclass.SND_PATH 199 elif _origin=='images': 200 _path=self.protocolclass.PIC_PATH 201 else: 202 selg.log('File %s has unknown origin, skip!'%_file) 203 continue 204 _file_name=_path+'/'+_file 205 try: 206 self.writefile(_file_name, _data) 207 _files_added.append({ 'filename': _file, 208 'filesize': len(_data) }) 209 except: 210 self.log('Failed to write file '+_file_name) 211 if __debug__: 212 raise 213 return _files_added
214
215 - def _update_wp_index_file(self, filelist):
216 # update the wp/picture index file with list of new files 217 if not filelist: 218 # no new files to update, bail 219 return 220 _index_file=self.protocolclass.PictureIndexFile() 221 try: 222 # read existing index items ... 223 _data=self.getfilecontents(self.protocolclass.PIC_INDEX_FILE_NAME) 224 if _data: 225 _index_file.readfrombuffer(prototypes.buffer(_data)) 226 except (com_brew.BrewNoSuchFileException, 227 com_brew.BrewBadPathnameException, 228 com_brew.BrewFileLockedException, 229 com_brew.BrewAccessDeniedException): 230 pass 231 # and append the new files 232 for _fileitem in filelist: 233 _index_file.items.append(self.protocolclass.PictureIndexEntry(**_fileitem)) 234 # and write out the new index file 235 _buffer=prototypes.buffer() 236 _index_file.writetobuffer(_buffer) 237 self.writefile(self.protocolclass.PIC_INDEX_FILE_NAME, 238 _buffer.getvalue())
239
240 - def savewallpapers(self, fundamentals, merge):
241 # send wallpapers to the phone 242 """Save ringtones to the phone""" 243 self.log('Writing wallpapers to the phone') 244 try: 245 _del_list, _new_list=self._get_del_new_list('wallpaper-index', 246 'wallpapers', 247 merge, 248 fundamentals, 249 frozenset(['images'])) 250 if __debug__: 251 self.log('Delete list: '+','.join(_del_list)) 252 self.log('New list: '+','.join(_new_list)) 253 self._replace_files('wallpaper-index', 'wallpapers', 254 _new_list, fundamentals) 255 _files_added=self._add_files('wallpaper-index', 'wallpapers', 256 _new_list, fundamentals) 257 self._update_wp_index_file(_files_added) 258 fundamentals['rebootphone']=True 259 except: 260 if __debug__: 261 raise 262 return fundamentals
263
264 - def _read_ringtone_range(self, fundamentals):
265 pass
266 - def _add_wp_cache(self, wp, idx, fundamentals):
267 # check to see if it already exists 268 pass
269 270 # PBEntry class----------------------------------------------------------------- 271 parentpbentry=com_a950.PBEntry
272 -class PBEntry(parentpbentry):
273 274 # Building a phonebook rec from a bp phone dict-----------------------------
275 - def _build_number(self, number, ringtone, primary):
276 # build a number rec 277 _num_type=self._pb_type_dict.get(number['type'], None) 278 if not _num_type: 279 # we don's support this type 280 return 281 # check for cell2 282 if _num_type=='cell' and self.pb.cell.number: 283 _num_type='cell2' 284 # build a number entry 285 _entry=self.phone.protocolclass.ss_number_entry() 286 _entry.number=number['number'] 287 _sd=number.get('speeddial', None) 288 if _sd is not None: 289 _entry.speeddial=_sd 290 if primary: 291 _entry.primary=1 292 # add it to the contact 293 setattr(self.pb, _num_type, _entry)
294
295 - def _build_wallpaper(self, wallpaper):
296 # set the wallpaper if specified 297 if not wallpaper: 298 return 299 for _rt in self.fundamentals.get('wallpaper-index', {}).values(): 300 if _rt.get('name', None)==wallpaper and \ 301 _rt.get('filename', None): 302 self.pb.wallpaper='%(name)s|%(pathname)s'% { 303 'name': _rt['name'], 304 'pathname': _rt['filename'] } 305 break
306
307 - def _build_ringtone(self, ringtone):
308 # set the ringtone if specified 309 if not ringtone: 310 self.pb.ringtone='Default' 311 return 312 for _wp in self.fundamentals.get('ringtone-index', {}).values(): 313 if _wp.get('name', None)==ringtone: 314 if _wp.get('filename', None): 315 self.pb.ringtone=_wp['filename'] if _wp['filename'][0]=='/' \ 316 else '/'+_wp['filename'] 317 elif _wp.get('origin', None)=='builtin': 318 self.pb.ringtone=_wp['name'] 319 break
320
321 - def _build(self, entry):
322 # Build a phone dict base on the phone data 323 super(PBEntry, self)._build(entry) 324 self._build_ringtone(entry.get('ringtones', [{}])[0].get('ringtone', None))
325 326 # Extracting data from the phone--------------------------------------------
327 - def _extract_wallpaper(self, entry, p_class):
328 if self.pb.info&p_class.PB_FLG_WP and \ 329 self.pb.wallpaper: 330 entry['wallpapers']=[{ 'wallpaper': self.pb.wallpaper.partition('|')[0], 331 'use': 'call' }]
332 - def _extract_ringtone(self, entry, p_class):
333 if self.pb.info&p_class.PB_FLG_CRINGTONE and \ 334 self.pb.ringtone: 335 entry['ringtones']=[{ 'ringtone': common.basename(self.pb.ringtone), 336 'use': 'call' }]
337 - def getvalue(self):
338 _entry=super(PBEntry, self).getvalue() 339 self._extract_ringtone(_entry, self.phone.protocolclass) 340 return _entry
341 342 # CalendarEntry class----------------------------------------------------------- 343 calendarentryparent=com_a950.CalendarEntry
344 -class CalendarEntry(calendarentryparent):
345 """Transient class to handle calendar data being sent to, retrieved from 346 the phone. 347 """ 348 # Extracting routine--------------------------------------------------------
349 - def _extract_ringtone(self):
350 # extract the builtin ringtone value, if possible 351 for _rt_name, _rt_code in self.phone.builtin_ringtones.items(): 352 if _rt_code==self.cal.ringtoneindex: 353 return _rt_name 354 for _rt_name, _rt_code in self.phone.builtin_sounds.items(): 355 if _rt_code==self.cal.ringtoneindex: 356 return _rt_name
357
358 - def getvalue(self):
359 # return a BitPim calendar entry equivalence 360 _entry=bpcalendar.CalendarEntry() 361 _entry.desc_loc=self.cal.title 362 _entry.start=self.cal.start 363 _entry.end=self._extract_end() 364 _entry.alarm=self._extract_alarm() 365 _entry.ringtone=self._extract_ringtone() 366 _entry.vibrate=self.cal.alert==self.ALERT_VIBRATE 367 return _entry
368 369 # building routines---------------------------------------------------------
370 - def _build_ringtone(self, entry):
371 _rt_name=entry.ringtone 372 if self.phone.builtin_ringtones.get(_rt_name, None): 373 return self.phone.builtin_ringtones[_rt_name] 374 elif self.phone.builtin_sounds.get(_rt_name, None): 375 return self.phone.builtin_sounds[_rt_name] 376 else: 377 return 0
378
379 - def _build(self, entry):
380 # populate this object with data from BitPim 381 self.cal.titlelen=len(entry.desc_loc) 382 self.cal.title=entry.desc_loc 383 self.cal.start=entry.start 384 self.cal.exptime=entry.end[3:5] 385 self.cal.alarm=self._build_alarm(entry) 386 self.cal.alert=self._build_alert(entry) 387 self.cal.duration=self._build_duration(entry) 388 self.cal.ringtoneindex=self._build_ringtone(entry)
389 390 #------------------------------------------------------------------------------- 391 parentprofile=com_a950.Profile
392 -class Profile(parentprofile):
393 serialsname=Phone.serialsname 394 # main LCD resolution, (external LCD is 96x96) 395 WALLPAPER_WIDTH=128 396 WALLPAPER_HEIGHT=160 397 # For phone detection 398 phone_manufacturer=Phone.my_manufacturer 399 phone_model=Phone.my_model 400 autodetect_delay=5 401 # "Warning" media size limit 402 RINGTONE_LIMITS= { 403 'MAXSIZE': 290000 404 } 405 406 # fill in the list of ringtone/sound origins on your phone 407 ringtoneorigins=('ringers', 'sounds') 408 # ringtone origins that are not available for the contact assignment 409 excluded_ringtone_origins=() 410 411 # all dumped in "images" 412 imageorigins={} 413 imageorigins.update(common.getkv(parentprofile.stockimageorigins, "images"))
414 - def GetImageOrigins(self):
415 return self.imageorigins
416 417 # our targets are the same for all origins 418 imagetargets={} 419 imagetargets.update(common.getkv(parentprofile.stockimagetargets, "wallpaper", 420 {'width': 128, 'height': 128, 'format': "JPEG"})) 421 imagetargets.update(common.getkv(parentprofile.stockimagetargets, "pictureid", 422 {'width': 96, 'height': 84, 'format': "JPEG"})) 423 imagetargets.update(common.getkv(parentprofile.stockimagetargets, "fullscreen", 424 {'width': 128, 'height': 160, 'format': "JPEG"})) 425 imagetargets.update(common.getkv(parentprofile.stockimagetargets, "outsidelcd", 426 {'width': 96, 'height': 84, 'format': "JPEG"}))
427 - def __init__(self):
428 parentprofile.__init__(self)
429 430 _supportedsyncs=( 431 ('phonebook', 'read', None), # all phonebook reading 432 ('phonebook', 'write', 'OVERWRITE'), # only overwriting phonebook 433 ('calendar', 'read', None), # all calendar reading 434 ('calendar', 'write', 'OVERWRITE'), # only overwriting calendar 435 ('ringtone', 'read', None), # all ringtone reading 436 ('ringtone', 'write', 'MERGE'), 437 ('wallpaper', 'read', None), # all wallpaper reading 438 ('wallpaper', 'write', 'MERGE'), 439 ('memo', 'read', None), # all memo list reading DJP 440 ('memo', 'write', 'OVERWRITE'), # all memo list writing DJP 441 ('call_history', 'read', None),# all call history list reading 442 ('sms', 'read', None), # all SMS list reading DJP 443 )
444