PyXR

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



0001 ### BITPIM
0002 ###
0003 ### Copyright (C) 2006 Joe Pham <djpham@bitpim.org>
0004 ###
0005 ### This program is free software; you can redistribute it and/or modify
0006 ### it under the terms of the BitPim license as detailed in the LICENSE file.
0007 ###
0008 ### $Id: com_samsungschu740.py 4517 2007-12-23 05:23:36Z djpham $
0009 
0010 """Communicate with the Samsung SCH-U740 Phone"""
0011 
0012 # System Modules
0013 import re
0014 import wx
0015 
0016 # BitPim Modules
0017 
0018 import call_history
0019 import common
0020 import com_brew
0021 import com_samsungscha950 as scha950
0022 import helpids
0023 import prototypes
0024 import p_samsungschu740 as p_schu740
0025 
0026 parentphone=scha950.Phone
0027 class Phone(parentphone):
0028     desc='SCH-U740'
0029     helpid=helpids.ID_PHONE_SAMSUNGSCHU740
0030     protocolclass=p_schu740
0031     serialsname='schu740'
0032 
0033     ringtone_noring_range='range_tones_preloaded_el_13'
0034     ringtone_default_range='range_tones_preloaded_el_01'
0035     builtin_ringtones={
0036         'VZW Default Tone': ringtone_default_range,
0037         'Bell 1': 'range_tones_preloaded_el_02',
0038         'Bell 2': 'range_tones_preloaded_el_03',
0039         'Bell 3': 'range_tones_preloaded_el_04',
0040         'Melody 1': 'range_tones_preloaded_el_05',
0041         'Melody 2': 'range_tones_preloaded_el_06',
0042         'Melody 3': 'range_tones_preloaded_el_07',
0043         'Melody 4': 'range_tones_preloaded_el_08',
0044         'Melody 5': 'range_tones_preloaded_el_09',
0045         'Melody 6': 'range_tones_preloaded_el_10',
0046         'Beep Once': 'range_tones_preloaded_el_11',
0047         'No Ring': ringtone_noring_range,
0048         }
0049     # can we use Sounds as ringtones?
0050     builtin_sounds={}
0051 ##    builtin_sounds={
0052 ##        'Birthday': 'range_sound_preloaded_el_birthday',
0053 ##        'Crowd Roar': 'range_sound_preloaded_el_crowed_roar',
0054 ##        'Train': 'range_sound_preloaded_el_train',
0055 ##        'Rainforest': 'range_sound_preloaded_el_rainforest',
0056 ##        'Clapping': 'range_sound_preloaded_el_clapping',
0057 ##        # same as ringtones ??
0058 ##        'Sound Beep Once': 'range_sound_preloaded_el_beep_once',
0059 ##        'Sound No Ring': 'range_sound_preloaded_el_no_rings',
0060 ##        }
0061     builtin_wallpapers={
0062         'Preloaded1': 'range_f_wallpaper_preloaded_el_01',
0063         'Preloaded2': 'range_f_wallpaper_preloaded_el_02',
0064         'Preloaded3': 'range_f_wallpaper_preloaded_el_03',
0065         'Preloaded4': 'range_f_wallpaper_preloaded_el_04',
0066         'Preloaded5': 'range_f_wallpaper_preloaded_el_05',
0067         'Preloaded6': 'range_f_wallpaper_preloaded_el_06',
0068         'Preloaded7': 'range_f_wallpaper_preloaded_el_07',
0069         'Preloaded8': 'range_f_wallpaper_preloaded_el_08',
0070         }
0071     builtin_groups={
0072         1: 'Business',
0073         2: 'Colleague',
0074         3: 'Family',
0075         4: 'Friends'
0076         }
0077 
0078     my_model='SCH-U740/DM'
0079     my_manufacturer='SAMSUNG'
0080     detected_model='u740'
0081 
0082     def __init__(self, logtarget, commport):
0083         "Calls all the constructors and sets initial modes"
0084         parentphone.__init__(self, logtarget, commport)
0085         global PBEntry
0086         self.pbentryclass=PBEntry
0087 
0088     def _get_file_wallpaper_index(self, idx, result,
0089                                   indexfilename, origin):
0090         try:
0091             _buf=prototypes.buffer(self.getfilecontents(indexfilename))
0092         except (com_brew.BrewNoSuchFileException,
0093                 com_brew.BrewBadPathnameException,
0094                 com_brew.BrewFileLockedException,
0095                 com_brew.BrewAccessDeniedException):
0096             return idx
0097         except:
0098             if __debug__:
0099                 raise
0100             return idx
0101         _index_file=self.protocolclass.RPictureIndexFile()
0102         _index_file.readfrombuffer(_buf)
0103         for _entry in _index_file.items:
0104             if _entry.pictype==self.protocolclass.PIC_TYPE_USERS:
0105                 if _entry.pathname.startswith('/ff/'):
0106                     _file_name=_entry.pathname[4:]
0107                 else:
0108                     _file_name=_entry.pathname
0109                 result[idx]={ 'name': common.basename(_entry.pathname),
0110                               'filename': _file_name,
0111                               'origin': origin,
0112                               }
0113                 idx+=1
0114         return idx
0115     def get_wallpaper_index(self):
0116         _res={}
0117         _idx=self._get_builtin_wallpaper_index(0, _res)
0118         _idx=self._get_file_wallpaper_index(_idx, _res,
0119                                             self.protocolclass.PIC_INDEX_FILE_NAME,
0120                                             'images')
0121         _idx=self._get_file_wallpaper_index(_idx, _res,
0122                                             self.protocolclass.VIDEO_INDEX_FILE_NAME,
0123                                             'video')
0124         return _res
0125 
0126     # Ringtone stuff
0127     def saveringtones(self, fundamentals, merge):
0128         """Save ringtones to the phone"""
0129         self.log('Writing ringtones to the phone')
0130         try:
0131             _del_list, _new_list=self._get_del_new_list('ringtone-index',
0132                                                         'ringtone',
0133                                                         merge,
0134                                                         fundamentals)
0135             if __debug__:
0136                 self.log('Delete list: '+','.join(_del_list))
0137                 self.log('New list: '+','.join(_new_list))
0138             self._add_files('ringtone-index', 'ringtone',
0139                             _new_list, fundamentals)
0140             self._update_media_index(self.protocolclass.WRingtoneIndexFile,
0141                                      self.protocolclass.WRingtoneIndexEntry,
0142                                      [self.protocolclass.RT_PATH],
0143                                      self.protocolclass.RT_EXCLUDED_FILES,
0144                                      self.protocolclass.RT_INDEX_FILE_NAME)
0145             self._update_media_index(self.protocolclass.WSoundsIndexFile,
0146                                      self.protocolclass.WSoundsIndexEntry,
0147                                      [self.protocolclass.SND_PATH],
0148                                      self.protocolclass.SND_EXCLUDED_FILES,
0149                                      self.protocolclass.SND_INDEX_FILE_NAME)
0150             fundamentals['rebootphone']=True
0151         except:
0152             if __debug__:
0153                 raise
0154         return fundamentals
0155 
0156     # Wallpaper stuff-----------------------------------------------------------
0157     def savewallpapers(self, fundamentals, merge):
0158         # send wallpapers to the phone
0159         """Save ringtones to the phone"""
0160         self.log('Writing wallpapers to the phone')
0161         try:
0162             _del_list, _new_list=self._get_del_new_list('wallpaper-index',
0163                                                         'wallpapers',
0164                                                         merge,
0165                                                         fundamentals,
0166                                                         ('video',))
0167             if __debug__:
0168                 self.log('Delete list: '+','.join(_del_list))
0169                 self.log('New list: '+','.join(_new_list))
0170             self._add_files('wallpaper-index', 'wallpapers',
0171                             _new_list, fundamentals)
0172             self._update_media_index(self.protocolclass.WPictureIndexFile,
0173                                      self.protocolclass.WPictureIndexEntry,
0174                                      [self.protocolclass.PIC_PATH],
0175                                      self.protocolclass.PIC_EXCLUDED_FILES,
0176                                      self.protocolclass.PIC_INDEX_FILE_NAME)
0177             fundamentals['rebootphone']=True
0178         except:
0179             if __debug__:
0180                 raise
0181         return fundamentals
0182 
0183     # Phonebook stuff-----------------------------------------------------------
0184     def _rescale_and_cache(self, wp, filename, idx,
0185                            fundamentals):
0186         # rescale the wp and add it to the cache dir
0187         try:
0188             _data=self.getfilecontents(filename, True)
0189             _tmpname=common.gettempfilename('tmp')
0190             file(_tmpname, 'wb').write(_data)
0191             _img=wx.Image(_tmpname)
0192             if not _img.Ok():
0193                 self.log('Failed to understand image: '+filename)
0194                 return
0195             _img.Rescale(128, 96)
0196             _img.SaveFile(_tmpname, wx.BITMAP_TYPE_JPEG)
0197             _newfilename='%(prefix)s/%(index)d.jpg'%\
0198                           { 'prefix': self.protocolclass.PB_WP_CACHE_PATH,
0199                             'index': idx }
0200             _data=file(_tmpname, 'rb').read()
0201             self.writefile(_newfilename, _data)
0202             return _newfilename
0203         except:
0204             if __debug__:
0205                 self.log('Failed to add cache image: '+wp)
0206                 raise
0207 
0208     def _add_wp_cache(self, wp, idx, fundamentals):
0209         # check to see if it already exists
0210         _wp_range=fundamentals.get('wallpaper-range', {})
0211         # add this wallpaper into the cache dir
0212         _wp_index=fundamentals.get('wallpaper-index', {})
0213         # look for the file name
0214         _filename=self._get_wp_filename(wp, _wp_index)
0215         if not _filename:
0216             # couldn't find the filename
0217             return
0218         # copy the image file, rescale, and put it in the cache dir
0219         _newfilename=self._rescale_and_cache(wp, _filename, idx, fundamentals)
0220         if _newfilename:
0221             # rescale successful, update the dict
0222             _wp_range[wp]='/ff/'+_newfilename
0223             _wp_range[wp]='/ff/%(filename)s|%(wpname)s'%\
0224                            { 'filename': _newfilename,
0225                              'wpname': common.stripext(wp),
0226                              }
0227             fundamentals['wallpaper-range']=_wp_range
0228 
0229 # PBEntry class-----------------------------------------------------------------
0230 parentpbentry=scha950.PBEntry
0231 class PBEntry(parentpbentry):
0232 
0233     def _build_memo(self, memo):
0234         if memo:
0235             self.pb.note=memo
0236 
0237     def _build(self, entry):
0238         parentpbentry._build(self, entry)
0239         self._build_memo(entry.get('memos', [{}])[0].get('memo', None))
0240 
0241     def _extract_wallpaper(self, entry, p_class):
0242         if not self.pb.info&p_class.PB_FLG_WP:
0243             return
0244         _idx=self.pb.wallpaper.rfind('|')+1
0245         # really ugly hack here !!!
0246         _wp=self.pb.wallpaper[_idx:]
0247         if not _wp.startswith('Preloaded'):
0248             # assume that the name has extension .jpg
0249             _wp+='.jpg'
0250         
0251         entry['wallpapers']=[{ 'wallpaper': _wp,
0252                                'use': 'call' }]
0253 
0254     def _extract_memo(self, entry, p_class):
0255         # extract the note portion from the phone into BitPim dict
0256         if self.pb.info&p_class.PB_FLG_NOTE:
0257             entry['memos']=[{ 'memo': self.pb.note }]
0258 
0259     def getvalue(self):
0260         _entry=parentpbentry.getvalue(self)
0261         self._extract_memo(_entry, self.phone.protocolclass)
0262         return _entry
0263 
0264 # Profile class-----------------------------------------------------------------
0265 parentprofile=scha950.Profile
0266 class Profile(parentprofile):
0267     serialsname=Phone.serialsname
0268     WALLPAPER_WIDTH=176
0269     WALLPAPER_HEIGHT=220
0270     # 128x96: outside LCD
0271     autodetect_delay=3
0272     usbids=( ( 0x04e8, 0x6640, 2),)
0273     deviceclasses=("serial",)
0274     BP_Calendar_Version=3
0275     # For phone detection
0276     phone_manufacturer=Phone.my_manufacturer
0277     phone_model=Phone.my_model
0278     # arbitrary ringtone file size limit
0279     RINGTONE_LIMITS= {
0280         'MAXSIZE': 100000
0281     }
0282     WALLPAPER_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789 ._:"
0283     RINGTONE_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789 ._:"
0284 
0285     # fill in the list of ringtone/sound origins on your phone
0286     ringtoneorigins=('ringers', 'sounds')
0287     # ringtone origins that are not available for the contact assignment
0288     excluded_ringtone_origins=('sounds',)
0289 
0290     imageorigins={}
0291     imageorigins.update(common.getkv(parentprofile.stockimageorigins, "images"))
0292     imageorigins.update(common.getkv(parentprofile.stockimageorigins, "video"))
0293     # wallpaper origins that are not available for the contact assignment
0294     excluded_wallpaper_origins=('video',)
0295 
0296     # our targets are the same for all origins
0297     imagetargets={}
0298     imagetargets.update(common.getkv(parentprofile.stockimagetargets, "wallpaper",
0299                                       {'width': 220, 'height': 184, 'format': "JPEG"}))
0300     imagetargets.update(common.getkv(parentprofile.stockimagetargets, "pictureid",
0301                                       {'width': 128, 'height': 96, 'format': "JPEG"}))
0302     imagetargets.update(common.getkv(parentprofile.stockimagetargets, "outsidelcd",
0303                                       {'width': 128, 'height': 96, 'format': "JPEG"}))
0304     def GetTargetsForImageOrigin(self, origin):
0305         return self.imagetargets
0306 
0307     def __init__(self):
0308         parentprofile.__init__(self)
0309 
0310     _supportedsyncs=(
0311         ('phonebook', 'read', None),  # all phonebook reading
0312         ('phonebook', 'write', 'OVERWRITE'),  # only overwriting phonebook
0313         ('calendar', 'read', None),   # all calendar reading
0314         ('calendar', 'write', 'OVERWRITE'),   # only overwriting calendar
0315         ('ringtone', 'read', None),   # all ringtone reading
0316         ('ringtone', 'write', 'MERGE'),
0317         ('wallpaper', 'read', None),  # all wallpaper reading
0318         ('wallpaper', 'write', 'MERGE'),
0319         ('memo', 'read', None),     # all memo list reading DJP
0320         ('memo', 'write', 'OVERWRITE'),  # all memo list writing DJP
0321         ('call_history', 'read', None),# all call history list reading
0322         ('sms', 'read', None),     # all SMS list reading DJP
0323         )
0324 
0325     field_color_data={
0326         'phonebook': {
0327             'name': {
0328                 'first': 1, 'middle': 1, 'last': 1, 'full': 1,
0329                 'nickname': 0, 'details': 1 },
0330             'number': {
0331                 'type': 5, 'speeddial': 5, 'number': 5,
0332                 'details': 5,
0333                 'ringtone': False, 'wallpaper': False },
0334             'email': 2,
0335             'email_details': {
0336                 'emailspeeddial': False, 'emailringtone': False,
0337                 'emailwallpaper': False },
0338             'address': {
0339                 'type': 0, 'company': 0, 'street': 0, 'street2': 0,
0340                 'city': 0, 'state': 0, 'postalcode': 0, 'country': 0,
0341                 'details': 0 },
0342             'url': 0,
0343             'memo': 1,
0344             'category': 1,
0345             'wallpaper': 1,
0346             'ringtone': 1,
0347             'storage': 0,
0348             },
0349         'calendar': {
0350             'description': True, 'location': True, 'allday': False,
0351             'start': True, 'end': True, 'priority': False,
0352             'alarm': True, 'vibrate': True,
0353             'repeat': True,
0354             'memo': False,
0355             'category': False,
0356             'wallpaper': False,
0357             'ringtone': True,
0358             },
0359         'memo': {
0360             'subject': False,
0361             'date': False,
0362             'secret': False,
0363             'category': False,
0364             'memo': True,
0365             },
0366         'todo': {
0367             'summary': False,
0368             'status': False,
0369             'due_date': False,
0370             'percent_complete': False,
0371             'completion_date': False,
0372             'private': False,
0373             'priority': False,
0374             'category': False,
0375             'memo': False,
0376             },
0377         }
0378 

Generated by PyXR 0.9.4