~ubuntu-branches/ubuntu/karmic/calibre/karmic

« back to all changes in this revision

Viewing changes to src/calibre/devices/prs505/driver.py

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-04-05 18:42:16 UTC
  • mfrom: (1.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20090405184216-cyb0x4edrwjcaw33
Tags: 0.5.9+dfsg-1
* New upstream release. (Closes: #525339)
* manpages-installation.patch: Encode generated manpages as UTF-8, to avoid
  UnicodeDecodeErrors when writing them out to files.
* debian/control: Demote calibre dependency of calibre-bin to Recommends:,
  which is sufficient and avoids a circular dependency. (Closes: #522059)
* debian/control: Drop build dependency help2man, current version does not
  need it any more.
* debian/control: Drop versioned build dependency on python-mechanize,
  current sid version is enough.
* debian/rules: Copy "setup.py install" command from cdbs'
  python-distutils.mk, since the current version broke this. This is a
  hackish workaround until #525436 gets fixed.
* debian/rules: Drop using $(wildcard ), use `ls`; the former does not work
  any more.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
            path = path[:-1]
25
25
        self.path = path
26
26
        self.name = os.path.basename(path)
27
 
        
 
27
 
28
28
 
29
29
class PRS505(Device):
30
30
    VENDOR_ID    = 0x054c   #: SONY Vendor Id
33
33
    PRODUCT_NAME = 'PRS-505'
34
34
    VENDOR_NAME  = 'SONY'
35
35
    FORMATS      = ['epub', 'lrf', 'lrx', 'rtf', 'pdf', 'txt']
36
 
    
 
36
 
37
37
    MEDIA_XML    = 'database/cache/media.xml'
38
38
    CACHE_XML    = 'Sony Reader/database/cache.xml'
39
 
    
 
39
 
40
40
    MAIN_MEMORY_VOLUME_LABEL  = 'Sony Reader Main Memory'
41
41
    STORAGE_CARD_VOLUME_LABEL = 'Sony Reader Storage Card'
42
 
    
 
42
 
43
43
    OSX_NAME                  = 'Sony PRS-505'
44
 
    
 
44
 
45
45
    CARD_PATH_PREFIX          = __appname__
46
 
    
 
46
 
47
47
    FDI_TEMPLATE = \
48
48
'''
49
49
  <device>
75
75
      </match>
76
76
  </device>
77
77
'''.replace('%(app)s', __appname__)
78
 
    
79
 
    
 
78
 
 
79
 
80
80
    def __init__(self, log_packets=False):
81
81
        self._main_prefix = self._card_prefix = None
82
 
        
 
82
 
83
83
    @classmethod
84
84
    def get_fdi(cls):
85
85
        return cls.FDI_TEMPLATE%dict(
90
90
                                     main_memory=cls.MAIN_MEMORY_VOLUME_LABEL,
91
91
                                     storage_card=cls.STORAGE_CARD_VOLUME_LABEL,
92
92
                                     )
93
 
    
 
93
 
94
94
    @classmethod
95
95
    def is_device(cls, device_id):
96
96
        device_id = device_id.upper()
104
104
               'PID_'+pid in device_id:
105
105
            return True
106
106
        return False
107
 
    
 
107
 
108
108
    @classmethod
109
109
    def get_osx_mountpoints(cls, raw=None):
110
110
        if raw is None:
112
112
            if not os.access(ioreg, os.X_OK):
113
113
                ioreg = 'ioreg'
114
114
            raw = subprocess.Popen((ioreg+' -w 0 -S -c IOMedia').split(),
115
 
                                   stdout=subprocess.PIPE).stdout.read()
 
115
                                   stdout=subprocess.PIPE).communicate()[0]
116
116
        lines = raw.splitlines()
117
117
        names = {}
118
118
        for i, line in enumerate(lines):
130
130
                break
131
131
        return names
132
132
 
133
 
    
 
133
 
134
134
    def open_osx(self):
135
 
        mount = subprocess.Popen('mount', shell=True, 
 
135
        mount = subprocess.Popen('mount', shell=True,
136
136
                                 stdout=subprocess.PIPE).stdout.read()
137
137
        names = self.get_osx_mountpoints()
138
138
        dev_pat = r'/dev/%s(\w*)\s+on\s+([^\(]+)\s+'
144
144
        if card_pat is not None:
145
145
            card_pat = dev_pat%card_pat
146
146
            self._card_prefix = re.search(card_pat, mount).group(2) + os.sep
147
 
            
148
 
    
 
147
 
 
148
 
149
149
    def open_windows(self):
150
150
        time.sleep(6)
151
151
        drives = []
152
 
        wmi = __import__('wmi', globals(), locals(), [], -1) 
153
 
        c = wmi.WMI()
 
152
        wmi = __import__('wmi', globals(), locals(), [], -1)
 
153
        c = wmi.WMI(find_classes=False)
154
154
        for drive in c.Win32_DiskDrive():
155
155
            if self.__class__.is_device(str(drive.PNPDeviceID)):
156
156
                if drive.Partitions == 0:
162
162
                    drives.append((drive.Index, prefix))
163
163
                except IndexError:
164
164
                    continue
165
 
                
166
 
                
 
165
 
 
166
 
167
167
        if not drives:
168
168
            raise DeviceError(_('Unable to detect the %s disk drive. Try rebooting.')%self.__class__.__name__)
169
 
        
 
169
 
170
170
        drives.sort(cmp=lambda a, b: cmp(a[0], b[0]))
171
171
        self._main_prefix = drives[0][1]
172
172
        if len(drives) > 1:
173
173
            self._card_prefix = drives[1][1]
174
 
            
175
 
    
 
174
 
 
175
 
176
176
    def open_linux(self):
177
177
        import dbus
178
 
        bus = dbus.SystemBus() 
 
178
        bus = dbus.SystemBus()
179
179
        hm  = dbus.Interface(bus.get_object("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager"), "org.freedesktop.Hal.Manager")
180
 
        
 
180
 
181
181
        def conditional_mount(dev, main_mem=True):
182
182
            mmo = bus.get_object("org.freedesktop.Hal", dev)
183
183
            label = mmo.GetPropertyString('volume.label', dbus_interface='org.freedesktop.Hal.Device')
186
186
            fstype = mmo.GetPropertyString('volume.fstype', dbus_interface='org.freedesktop.Hal.Device')
187
187
            if is_mounted:
188
188
                return str(mount_point)
189
 
            mmo.Mount(label, fstype, ['umask=077', 'uid='+str(os.getuid()), 'sync'], 
 
189
            mmo.Mount(label, fstype, ['umask=077', 'uid='+str(os.getuid()), 'sync'],
190
190
                          dbus_interface='org.freedesktop.Hal.Device.Volume')
191
191
            return os.path.normpath('/media/'+label)+'/'
192
 
    
193
 
        
 
192
 
 
193
 
194
194
        mm = hm.FindDeviceStringMatch(__appname__+'.mainvolume', self.__class__.__name__)
195
195
        if not mm:
196
196
            raise DeviceError(_('Unable to detect the %s disk drive. Try rebooting.')%(self.__class__.__name__,))
201
201
                break
202
202
            except dbus.exceptions.DBusException:
203
203
                continue
204
 
            
205
 
            
 
204
 
 
205
 
206
206
        if not self._main_prefix:
207
207
            raise DeviceError('Could not open device for reading. Try a reboot.')
208
 
            
 
208
 
209
209
        self._card_prefix = None
210
210
        cards = hm.FindDeviceStringMatch(__appname__+'.cardvolume', self.__class__.__name__)
211
211
        keys = []
212
212
        for card in cards:
213
213
            keys.append(int('UC_SD' in bus.get_object("org.freedesktop.Hal", card).GetPropertyString('info.parent', dbus_interface='org.freedesktop.Hal.Device')))
214
 
            
 
214
 
215
215
        cards = zip(cards, keys)
216
216
        cards.sort(cmp=lambda x, y: cmp(x[1], y[1]))
217
217
        cards = [i[0] for i in cards]
218
 
        
 
218
 
219
219
        for dev in cards:
220
220
            try:
221
221
                self._card_prefix = conditional_mount(dev, False)+os.sep
224
224
                import traceback
225
225
                print traceback
226
226
                continue
227
 
            
228
 
    
 
227
 
 
228
 
229
229
    def open(self):
230
230
        time.sleep(5)
231
231
        self._main_prefix = self._card_prefix = None
262
262
                self._card_prefix = None
263
263
                import traceback
264
264
                traceback.print_exc()
265
 
            
 
265
 
266
266
    def set_progress_reporter(self, pr):
267
267
        self.report_progress = pr
268
 
        
 
268
 
269
269
    def get_device_information(self, end_session=True):
270
270
        return (self.__class__.__name__, '', '', '')
271
 
    
 
271
 
272
272
    def card_prefix(self, end_session=True):
273
273
        return self._card_prefix
274
 
    
 
274
 
275
275
    @classmethod
276
276
    def _windows_space(cls, prefix):
277
277
        if prefix is None:
288
288
            else: raise
289
289
        mult = sectors_per_cluster * bytes_per_sector
290
290
        return total_clusters * mult, free_clusters * mult
291
 
    
 
291
 
292
292
    def total_space(self, end_session=True):
293
293
        msz = csz = 0
294
294
        if not iswindows:
301
301
        else:
302
302
            msz = self._windows_space(self._main_prefix)[0]
303
303
            csz = self._windows_space(self._card_prefix)[0]
304
 
                
 
304
 
305
305
        return (msz, 0, csz)
306
 
    
 
306
 
307
307
    def free_space(self, end_session=True):
308
308
        msz = csz = 0
309
309
        if not iswindows:
316
316
        else:
317
317
            msz = self._windows_space(self._main_prefix)[1]
318
318
            csz = self._windows_space(self._card_prefix)[1]
319
 
                
 
319
 
320
320
        return (msz, 0, csz)
321
 
                
 
321
 
322
322
    def books(self, oncard=False, end_session=True):
323
323
        if oncard and self._card_prefix is None:
324
324
            return []
331
331
            if os.path.exists(path):
332
332
                os.unlink(path)
333
333
        return bl
334
 
    
 
334
 
335
335
    def munge_path(self, path):
336
336
        if path.startswith('/') and not (path.startswith(self._main_prefix) or \
337
337
            (self._card_prefix and path.startswith(self._card_prefix))):
339
339
        elif path.startswith('card:'):
340
340
            path = path.replace('card:', self._card_prefix[:-1])
341
341
        return path
342
 
            
 
342
 
343
343
    def mkdir(self, path, end_session=True):
344
344
        """ Make directory """
345
345
        path = self.munge_path(path)
346
346
        os.mkdir(path)
347
 
        
 
347
 
348
348
    def list(self, path, recurse=False, end_session=True, munge=True):
349
349
        if munge:
350
350
            path = self.munge_path(path)
356
356
            if recurse and _file.is_dir:
357
357
                dirs[len(dirs):] = self.list(_file.path, recurse=True, munge=False)
358
358
        return dirs
359
 
    
 
359
 
360
360
    def get_file(self, path, outfile, end_session=True):
361
361
        path = self.munge_path(path)
362
362
        src = open(path, 'rb')
363
363
        shutil.copyfileobj(src, outfile, 10*1024*1024)
364
 
                 
 
364
 
365
365
    def put_file(self, infile, path, replace_file=False, end_session=True):
366
366
        path = self.munge_path(path)
367
367
        if os.path.isdir(path):
372
372
        shutil.copyfileobj(infile, dest, 10*1024*1024)
373
373
        dest.flush()
374
374
        dest.close()
375
 
        
 
375
 
376
376
    def rm(self, path, end_session=True):
377
377
        path = self.munge_path(path)
378
378
        os.unlink(path)
379
 
        
 
379
 
380
380
    def touch(self, path, end_session=True):
381
381
        path = self.munge_path(path)
382
382
        if not os.path.exists(path):
383
383
            open(path, 'w').close()
384
384
        if not os.path.isdir(path):
385
385
            os.utime(path, None)
386
 
            
387
 
    def upload_books(self, files, names, on_card=False, end_session=True, 
 
386
 
 
387
    def upload_books(self, files, names, on_card=False, end_session=True,
388
388
                     metadata=None):
389
389
        if on_card and not self._card_prefix:
390
390
            raise ValueError(_('The reader has no storage card connected.'))
391
391
        path = os.path.join(self._card_prefix, self.CARD_PATH_PREFIX) if on_card \
392
392
               else os.path.join(self._main_prefix, 'database', 'media', 'books')
393
 
               
 
393
 
394
394
        def get_size(obj):
395
395
            if hasattr(obj, 'seek'):
396
396
                obj.seek(0, 2)
398
398
                obj.seek(0)
399
399
                return size
400
400
            return os.path.getsize(obj)
401
 
        
 
401
 
402
402
        sizes = map(get_size, files)
403
403
        size = sum(sizes)
404
404
        space = self.free_space()
405
405
        mspace = space[0]
406
406
        cspace = space[2]
407
 
        if on_card and size > cspace - 1024*1024: 
 
407
        if on_card and size > cspace - 1024*1024:
408
408
            raise FreeSpaceError("There is insufficient free space "+\
409
409
                                          "on the storage card")
410
 
        if not on_card and size > mspace - 2*1024*1024: 
 
410
        if not on_card and size > mspace - 2*1024*1024:
411
411
            raise FreeSpaceError("There is insufficient free space " +\
412
412
                                         "in main memory")
413
 
            
 
413
 
414
414
        paths, ctimes = [], []
415
 
        
 
415
 
416
416
        names = iter(names)
417
417
        for infile in files:
418
418
            close = False
419
419
            if not hasattr(infile, 'read'):
420
420
                infile, close = open(infile, 'rb'), True
421
 
            infile.seek(0)            
 
421
            infile.seek(0)
422
422
            name = names.next()
423
423
            paths.append(os.path.join(path, name))
424
424
            if not os.path.exists(os.path.dirname(paths[-1])):
428
428
                infile.close()
429
429
            ctimes.append(os.path.getctime(paths[-1]))
430
430
        return zip(paths, sizes, ctimes, cycle([on_card]))
431
 
    
 
431
 
432
432
    @classmethod
433
433
    def add_books_to_metadata(cls, locations, metadata, booklists):
434
434
        metadata = iter(metadata)
441
441
            name = name.replace('//', '/')
442
442
            booklists[on_card].add_book(info, name, *location[1:-1])
443
443
        fix_ids(*booklists)
444
 
        
 
444
 
445
445
    def delete_books(self, paths, end_session=True):
446
446
        for path in paths:
447
447
            if os.path.exists(path):
448
448
                os.unlink(path)
449
 
            
 
449
 
450
450
    @classmethod
451
451
    def remove_books_from_metadata(cls, paths, booklists):
452
452
        for path in paths:
454
454
                if hasattr(bl, 'remove_book'):
455
455
                    bl.remove_book(path)
456
456
        fix_ids(*booklists)
457
 
        
 
457
 
458
458
    def sync_booklists(self, booklists, end_session=True):
459
459
        fix_ids(*booklists)
460
460
        if not os.path.exists(self._main_prefix):
468
468
            f = open(self._card_prefix + self.__class__.CACHE_XML, 'wb')
469
469
            booklists[1].write(f)
470
470
            f.close()
471
 
            
472
 
    
473
 
     
 
471
 
 
472
 
 
473
 
474
474
 
475
475
def main(args=sys.argv):
476
476
    return 0