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

« back to all changes in this revision

Viewing changes to src/calibre/ebooks/metadata/mobi.py

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-07-30 12:49:41 UTC
  • mfrom: (1.3.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090730124941-qjdsmri25zt8zocn
Tags: 0.6.3+dfsg-0ubuntu1
* New upstream release. Please see http://calibre.kovidgoyal.net/new_in_6/
  for the list of new features and changes.
* remove_postinstall.patch: Update for new version.
* build_debug.patch: Does not apply any more, disable for now. Might not be
  necessary any more.
* debian/copyright: Fix reference to versionless GPL.
* debian/rules: Drop obsolete dh_desktop call.
* debian/rules: Add workaround for weird Python 2.6 setuptools behaviour of
  putting compiled .so files into src/calibre/plugins/calibre/plugins
  instead of src/calibre/plugins.
* debian/rules: Drop hal fdi moving, new upstream version does not use hal
  any more. Drop hal dependency, too.
* debian/rules: Install udev rules into /lib/udev/rules.d.
* Add debian/calibre.preinst: Remove unmodified
  /etc/udev/rules.d/95-calibre.rules on upgrade.
* debian/control: Bump Python dependencies to 2.6, since upstream needs
  it now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
    'Marshall T. Vandegrift <llasram@gmail.com>'
10
10
__docformat__ = 'restructuredtext en'
11
11
 
12
 
import sys
13
 
import os
14
12
from struct import pack, unpack
15
13
from cStringIO import StringIO
16
 
from calibre.ebooks.metadata import get_parser
 
14
from datetime import datetime
 
15
 
17
16
from calibre.ebooks.mobi import MobiError
18
 
from calibre.ebooks.mobi.reader import get_metadata
19
17
from calibre.ebooks.mobi.writer import rescale_image, MAX_THUMB_DIMEN
20
18
from calibre.ebooks.mobi.langcodes import iana2mobi
21
19
 
22
20
class StreamSlicer(object):
 
21
 
23
22
    def __init__(self, stream, start=0, stop=None):
24
23
        self._stream = stream
25
24
        self.start = start
88
87
        flags, = unpack('>I', record0[128:132])
89
88
        have_exth = self.have_exth = (flags & 0x40) != 0
90
89
        self.cover_record = self.thumbnail_record = None
 
90
        self.timestamp = None
91
91
        if not have_exth:
92
92
            return
93
93
        exth_off = unpack('>I', record0[20:24])[0] + 16 + record0.start
94
94
        exth = self.exth = StreamSlicer(stream, exth_off, record0.stop)
95
95
        nitems, = unpack('>I', exth[8:12])
96
96
        pos = 12
 
97
        # Store any EXTH fields not specifiable in GUI
97
98
        for i in xrange(nitems):
98
99
            id, size = unpack('>II', exth[pos:pos + 8])
99
100
            content = exth[pos + 8: pos + size]
100
101
            pos += size
101
 
            if id == 201:
 
102
 
 
103
            if id == 106:
 
104
                self.timestamp = content
 
105
            elif id == 201:
102
106
                rindex, = self.cover_rindex, = unpack('>I', content)
103
107
                self.cover_record = self.record(rindex + image_base)
104
108
            elif id == 202:
117
121
 
118
122
    def update(self, mi):
119
123
        recs = []
120
 
        from calibre.ebooks.mobi.from_any import config
121
 
        if mi.author_sort and config().parse().prefer_author_sort:
 
124
        try:
 
125
             from calibre.ebooks.conversion.config import load_defaults
 
126
             prefs = load_defaults('mobi_output')
 
127
             pas = prefs.get('prefer_author_sort', False)
 
128
        except:
 
129
            pas = False
 
130
        if mi.author_sort and pas:
122
131
            authors = mi.author_sort
123
132
            recs.append((100, authors.encode(self.codec, 'replace')))
124
133
        elif mi.authors:
133
142
        if mi.tags:
134
143
            subjects = '; '.join(mi.tags)
135
144
            recs.append((105, subjects.encode(self.codec, 'replace')))
 
145
 
 
146
        if mi.pubdate:
 
147
            recs.append((106, str(mi.pubdate).encode(self.codec, 'replace')))
 
148
        elif mi.timestamp:
 
149
            recs.append((106, str(mi.timestamp).encode(self.codec, 'replace')))
 
150
        elif self.timestamp:
 
151
            recs.append((106, self.timestamp))
 
152
        else:
 
153
            recs.append((106, str(datetime.now()).encode(self.codec, 'replace')))
 
154
 
136
155
        if self.cover_record is not None:
137
156
            recs.append((201, pack('>I', self.cover_rindex)))
138
157
            recs.append((203, pack('>I', 0)))
182
201
    mu = MetadataUpdater(stream)
183
202
    mu.update(mi)
184
203
    return
185
 
 
186
 
 
187
 
def option_parser():
188
 
    parser = get_parser('mobi')
189
 
    parser.remove_option('--category')
190
 
    parser.add_option('--tags', default=None,
191
 
                      help=_('Set the subject tags'))
192
 
    parser.add_option('--language', default=None,
193
 
                      help=_('Set the language'))
194
 
    parser.add_option('--publisher', default=None,
195
 
                      help=_('Set the publisher'))
196
 
    parser.add_option('--isbn', default=None,
197
 
                      help=_('Set the ISBN'))
198
 
    return parser
199
 
 
200
 
def main(args=sys.argv):
201
 
    parser = option_parser()
202
 
    opts, args = parser.parse_args(args)
203
 
    if len(args) != 2:
204
 
        parser.print_help()
205
 
        print >>sys.stderr, 'Usage: %s file.mobi' % args[0]
206
 
        return 1
207
 
    fname = args[1]
208
 
    changed = False
209
 
    with open(fname, 'r+b') as stream:
210
 
        mi = get_metadata(stream)
211
 
        if opts.title:
212
 
            mi.title = opts.title
213
 
            changed = True
214
 
        if opts.authors:
215
 
            mi.authors = opts.authors.split(',')
216
 
            changed = True
217
 
        if opts.comment:
218
 
            mi.comments = opts.comment
219
 
            changed = True
220
 
        if opts.tags is not None:
221
 
            mi.tags = opts.tags.split(',')
222
 
            changed = True
223
 
        if opts.language is not None:
224
 
            mi.language = opts.language
225
 
            changed = True
226
 
        if opts.publisher is not None:
227
 
            mi.publisher = opts.publisher
228
 
            changed = True
229
 
        if opts.isbn is not None:
230
 
            mi.isbn = opts.isbn
231
 
            changed = True
232
 
        if changed:
233
 
            set_metadata(stream, mi)
234
 
        print unicode(get_metadata(stream))
235
 
    if not changed and mi.cover_data[1]:
236
 
        cover = os.path.abspath(
237
 
            '.'.join((os.path.splitext(os.path.basename(fname))[0],
238
 
                      mi.cover_data[0].lower())))
239
 
        open(cover, 'wb').write(mi.cover_data[1])
240
 
        print _('Cover saved to'), cover
241
 
    return 0
242
 
 
243
 
if __name__ == '__main__':
244
 
    sys.exit(main())