~ubuntu-branches/ubuntu/trusty/burn/trusty

« back to all changes in this revision

Viewing changes to burnlib/burn.py

  • Committer: Bazaar Package Importer
  • Author(s): Ben Finney
  • Date: 2009-08-23 23:32:37 UTC
  • mfrom: (1.1.6 sid)
  • Revision ID: james.westby@ubuntu.com-20090823233237-06ev83e82s256o2t
Tags: 0.4.5-1
* The “Miss is a sea fish” release.
* Urgency high to address security alert TEMP-0542329.
* New upstream version:
  + Documentation updates.
  + Use ‘subprocess’ module for secure invocation of child processes.
    (Closes: Bug#542329, Bug#542750)
  + No longer uses programs from ‘cdrecord’, instead switch to ‘cdrkit’
    programs.
* debian/control:
  + Update to ‘Standards-Version: 3.8.3’. No extra changes needed.
  + Additional Build-Depends for building documentation.
* debian/patches/:
  + 03.configure-current-executables.patch: obsoleted by new version.
* debian/patches/series, debian/rules, debian/control:
  + Remove Quilt infrastructure as no patches are applied.
* debian/copyright:
  + Update copyright dates.
* debian/docs, debian/install, debian/doc-base:
  + New upstream file locations.
  + Register documentation for ‘doc-base’.
* debian/pyversions:
  + Require at least Python 2.5.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
 
 
3
# burnlib/burn.py
 
4
#
 
5
# Copyright © 2009 Ben Finney <ben+python@benfinney.id.au>.
 
6
# Copyright © 2003–2009 Gaetano Paolone <bigpaul@hacknight.org>.
 
7
#
 
8
# This program is free software; you can redistribute it and/or
 
9
# modify it under the terms of the GNU General Public License
 
10
# as published by the Free Software Foundation; either version 2
 
11
# of the License, or (at your option) any later version.
 
12
#
 
13
# This program is distributed in the hope that it will be useful,
 
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
# GNU General Public License for more details.
 
17
#
 
18
# You should have received a copy of the GNU General Public License
 
19
# along with this program; if not, write to the Free Software
 
20
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
21
# 02110-1301 USA.
 
22
 
 
23
import os
 
24
import os.path
 
25
import sys
 
26
import optparse
 
27
import re
 
28
import statvfs
 
29
import mad
 
30
import ao
 
31
import ogg.vorbis
 
32
import gettext
 
33
import pwd
 
34
import fnmatch
 
35
import shlex
 
36
import subprocess
 
37
 
 
38
import burnlib.version
 
39
import console
 
40
import configure
 
41
from configure import config
 
42
import audio
 
43
 
 
44
 
 
45
gettext.bindtextdomain('burn', '/usr/share/locale/it/LC_MESSAGES/')
 
46
gettext.textdomain('burn')
 
47
_ = gettext.gettext
 
48
 
 
49
 
 
50
class ContentMode(object):
 
51
    """ Modes for content handling. """
 
52
 
 
53
    (data, iso, copy, audio) = (object() for n in range(4))
 
54
 
 
55
    titles = {
 
56
        audio: _('Audio-CD'),
 
57
        data: _('Data-CD'),
 
58
        copy: _('Copy-CD'),
 
59
        iso: _('Iso-CD'),
 
60
        }
 
61
 
 
62
 
 
63
def du(dirname, path_du, follow_symlink=False):
 
64
    #is like du. goes through dirname
 
65
    #and subdirs and append every file size to path_du
 
66
    """Goes deeply through path in order to calculate path's disk usage."""
 
67
    for root, dirs, files in os.walk(dirname):
 
68
        for file_name in files:
 
69
            if os.path.exists(os.path.realpath(os.path.join(root, file_name))):
 
70
                path_du += os.path.getsize(os.path.join(root, file_name))
 
71
    if follow_symlink:
 
72
        for directory in dirs:
 
73
            print os.path.join(root, directory)
 
74
            #os.walk does not follow symlink directories.
 
75
            #Next line will allow it.
 
76
            if os.path.islink(os.path.join(root, directory)):
 
77
                path_du += du(
 
78
                    os.path.realpath(os.path.join(root, directory)), path_du,
 
79
                    follow_symlink)
 
80
    return path_du
 
81
 
 
82
 
 
83
def check_main_option(opt):
 
84
    """Checks first argument."""
 
85
    if opt not in [
 
86
        "-D", "--data-cd",
 
87
        "-I", "--iso-cd",
 
88
        "-C", "--copy-cd",
 
89
        "-A", "--audio-cd",
 
90
        ]:
 
91
        print _(
 
92
            'Invalid syntax. First argument should be a main mode.'
 
93
            ' See \'burn -h\' for more info.')
 
94
        sys.exit()
 
95
 
 
96
 
 
97
def check_media_empty():
 
98
    """ Return True if media device is empty. """
 
99
    command_args = [
 
100
        config.get('executables', 'cdrdao'), "disk-info",
 
101
        "--device", config.get('CD-writer', 'device'),
 
102
        "--driver", config.get('CD-writer', 'driver'),
 
103
        ]
 
104
    command_process = subprocess.Popen(
 
105
        command_args, close_fds=True,
 
106
        stdout=subprocess.PIPE, stderr=open(os.devnull))
 
107
    for line in command_process.stdout:
 
108
        if line.startswith('CD-R empty'):
 
109
            if line.split(':')[1].strip() == 'yes':
 
110
                return True
 
111
            return False
 
112
    return False
 
113
 
 
114
 
 
115
def err(why):
 
116
    """Prints an error using why as argument."""
 
117
    print _('Error. '), why
 
118
 
 
119
 
 
120
def err_nf(dir_file):
 
121
    """Not found error message."""
 
122
    print _('Error. '), dir_file, _(' not found.')
 
123
 
 
124
 
 
125
def get_list_from_file(path):
 
126
    """extract a list of paths from a file"""
 
127
    in_file = open(path)
 
128
    in_file_lines = [
 
129
        path for path in (
 
130
            line.strip() for line in in_file)
 
131
        if os.path.isfile(path)]
 
132
    return in_file_lines
 
133
 
 
134
 
 
135
def get_media_capacity():
 
136
    """ Get total capacity of media device. """
 
137
    command_args = [
 
138
        config.get('executables', 'cdrdao'), "disk-info",
 
139
        "--device", config.get('CD-writer', 'device'),
 
140
        "--driver", config.get('CD-writer', 'driver'),
 
141
        ]
 
142
    command_process = subprocess.Popen(
 
143
        command_args, close_fds=True,
 
144
        stdout=subprocess.PIPE, stderr=open(os.devnull))
 
145
    for line in command_process.stdout:
 
146
        if line.startswith('Total Capacity'):
 
147
            if line.split(':')[1].strip() == 'n/a':
 
148
                return None
 
149
            return line.split()[6].split('/')[0]
 
150
    return None
 
151
 
 
152
 
 
153
def prog_intro(mode=None):
 
154
    """ Output program introduction message for specified mode. """
 
155
 
 
156
    if config.getboolean('general', 'ask_root'):
 
157
        if not pwd.getpwuid(os.geteuid())[0] == "root":
 
158
            if not console.ask_yesno(_(
 
159
                'You are not superuser (root).'
 
160
                ' Do you still want to continue'), True):
 
161
                sys.exit()
 
162
    print _(
 
163
        'Burn v.%(version)s  '
 
164
        'Written by %(author_name)s.') % vars(burnlib.version)
 
165
    print _('Burn until recorded, now!')
 
166
    print _(
 
167
        'This software comes with absolutely no warranty!'
 
168
        ' Use at your own risk!')
 
169
    print _('Burn is free software.')
 
170
    print _('See software updates at <URL:%(_url)s>.') % vars(burnlib)
 
171
    print
 
172
 
 
173
    mode_title = ContentMode.titles.get(mode)
 
174
    if mode_title is not None:
 
175
        print mode_title + "..."
 
176
        print
 
177
 
 
178
 
 
179
def show_examples(option, opt, value, parser):
 
180
    """Show examples for quick startup"""
 
181
 
 
182
    print "# burn -D -p /etc/"
 
183
    print _(
 
184
        '   Creates a CD/DVD with /etc/ contents. (you will find files'
 
185
        ' and directories contained in /etc in CD\'s root)')
 
186
    print "# burn -D -p /home/bigpaul/video/summer_2003/spain.tar.gz"
 
187
    print _('   Creates a CD/DVD with spain.tar.gz in CD\'s root')
 
188
    print "# burn -D -r /etc/"
 
189
    print _(
 
190
        '   Creates a CD/DVD containing the whole /etc/ directory.'
 
191
        ' (-r preserves path)')
 
192
    print "# burn -D -c /mail_2003 /home/bigpaul/Mail -p /boot/vmli*"
 
193
    print _(
 
194
        '   Creates a CD/DVD containing the whole /home/bigpaul/Mail'
 
195
        ' renamed into /mail_2003. (-c changes path name).'
 
196
        ' This command also adds in CD\'s root every vmli* file'
 
197
        ' in /boot/ directory')
 
198
    print "# burn -I -n image.iso"
 
199
    print _('   Burns image.iso')
 
200
    print "# burn -C"
 
201
    print _('   Copy CDs (disk at once).')
 
202
    print "# burn -A -a *.wav"
 
203
    print _('   Creates an Audio CD. Tracks come from wav files')
 
204
    print "# burn -A -a *.mp3"
 
205
    print _('   Creates an Audio CD. Tracks come from mp3 files')
 
206
    print "# burn -A -a *.ogg"
 
207
    print _('   Creates an Audio CD. Tracks come from Ogg Vorbis files')
 
208
    print "# burn -A -a *.mp3 file.ogg track01.wav"
 
209
    print _('   Creates an Audio CD. Tracks come from .wav, .ogg, .mp3 files')
 
210
 
 
211
    sys.exit()
 
212
 
 
213
 
 
214
def varargs(option, opt, value, parser):
 
215
    """Callback function to manage multiple arguments (or shell expansion)"""
 
216
    assert value is None
 
217
    step = 0
 
218
    value = []
 
219
    rargs = parser.rargs
 
220
    while rargs:
 
221
        step = step + 1
 
222
        arg = rargs[0]
 
223
        if ((arg[:2] == "--" and len(arg) > 2) or
 
224
            (arg[:1] == "-" and len(arg) > 1 and arg[1] != "-")):
 
225
            if step == 1:
 
226
                print _(
 
227
                    '%(option)s is an option that takes one or more arguments.'
 
228
                    ' So you can\'t put %(arg)s after it') % vars()
 
229
                sys.exit()
 
230
            else:
 
231
                break
 
232
        else:
 
233
            value.append(arg)
 
234
            del rargs[0]
 
235
    setattr(parser.values, option.dest, value)
 
236
 
 
237
 
 
238
class ISO:
 
239
    "ISO class"
 
240
 
 
241
    def __init__(self):
 
242
        """ Set up a new instance. """
 
243
        self.path_o = []
 
244
        self.genisoimage_args = []
 
245
        self.windows = config.getboolean('ISO', 'windows_read')
 
246
        self.tempdir = config.get('ISO', 'tempdir')
 
247
        self.image_name = config.get('ISO', 'image')
 
248
        self.mount_dir = config.get('ISO', 'mount_dir')
 
249
        self.dest = os.path.normpath(self.tempdir + self.image_name)
 
250
 
 
251
    def create(self):
 
252
        """ Execute data track recording command. """
 
253
        print _('Creating temporary image: '), self.dest
 
254
        pbar = console.ProgressBar(width=30)
 
255
        command_process = subprocess.Popen(
 
256
            self.genisoimage_args, close_fds=True,
 
257
            stdin=subprocess.PIPE,
 
258
            stdout=open(os.devnull), stderr=subprocess.PIPE)
 
259
        progress = 0
 
260
        for line in command_process.stderr:
 
261
            if "done, estimate finish" in line:
 
262
                progress = int(float(line.split()[0][:-1]))
 
263
                pbar.amount = progress
 
264
                pbar.update_display()
 
265
        pbar.amount = 100
 
266
        pbar.update_display()
 
267
 
 
268
    def destroy(self):
 
269
        """remove the file"""
 
270
        os.remove(self.dest)
 
271
 
 
272
    def ask_mount(self, image):
 
273
        """asks if user wants to mount image"""
 
274
        if console.ask_yesno(_(
 
275
            'Do you want to see image\'s contents before proceeding'
 
276
            ), True):
 
277
            self.mount(image)
 
278
 
 
279
    def freespace(self):
 
280
        """return free disk space"""
 
281
        space = os.statvfs(self.tempdir)
 
282
        return (long(space[statvfs.F_BAVAIL]) * \
 
283
            long(space[statvfs.F_BSIZE]))/1048576
 
284
 
 
285
    def mount(self, image):
 
286
        """mount image in self.mount_dir"""
 
287
        mount_dir = self.mount_dir
 
288
        if os.path.exists(mount_dir) and os.path.isdir(mount_dir):
 
289
            command_args = ["mount", "-o", "loop", image, mount_dir]
 
290
            if subprocess.call(command_args):
 
291
                print _(
 
292
                    'Unable to mount %(image)s. Please check if you have'
 
293
                    ' permissions to mount it on %(mount_dir)s') % vars()
 
294
                sys.exit()
 
295
            self.ask_after_mount(self.mount_dir)
 
296
        else:
 
297
            err(self.mount_dir + _(' is not valid as a mount point'))
 
298
            sys.exit()
 
299
        command_args = ["umount", self.mount_dir]
 
300
        subprocess.call(command_args)
 
301
 
 
302
    def ask_after_mount(self, dirname):
 
303
        """Choose what to do with the mounted image..."""
 
304
        prompt = _(
 
305
            '\n\nPlease choose:\n\n'
 
306
            '1. Print every file with path\n'
 
307
            '2. Print directory tree structure\n'
 
308
            '3. Ok, finished... Let\'s burn\n'
 
309
            '> ')
 
310
        mount_choice = raw_input(prompt)
 
311
        if mount_choice in ('1'): #option num. 1 ---> every file
 
312
            print
 
313
            for root, dirs, files in os.walk(dirname):
 
314
                for file_path in files:
 
315
                    print os.path.join(root, file_path)
 
316
            self.ask_after_mount(dirname) #return True
 
317
        if mount_choice in ('2'): #option num. 2 ---> tree structure
 
318
            print
 
319
            for root, dirs, files in os.walk(dirname):
 
320
                for directory in dirs:
 
321
                    print os.path.join(root, directory)
 
322
            self.ask_after_mount(dirname)
 
323
        if mount_choice in ('3'): #option num. 3 ---> done
 
324
            return True
 
325
 
 
326
    def ask_multisession(self):
 
327
        """Asks if user wants to add stuff to a multisession CD or if he wants
 
328
        to create a new multisession CD from scratch."""
 
329
        prompt = _(
 
330
            '\n\nPlease choose:\n\n'
 
331
            '1. Create new multisession CD from a blank media\n'
 
332
            '2. Append data to an existant multisession CD\n'
 
333
            '> ')
 
334
        multisession_cd = raw_input(prompt)
 
335
        if multisession_cd in ('1'): #option num. 1 new multisession
 
336
            return 1
 
337
        if multisession_cd in ('2'): #option num. 2 already multisession
 
338
            return 2
 
339
 
 
340
    def ask_remove(self):
 
341
        """asks to remove image"""
 
342
        print
 
343
        print self.dest, _(' is the image file created...')
 
344
        if console.ask_yesno(_('Do you want me to remove it'), False):
 
345
            print _('Removing '), self.dest, "..."
 
346
            os.remove(self.dest)
 
347
            return True
 
348
        else:
 
349
            return False
 
350
 
 
351
    def first_ask_remove(self):
 
352
        """asks to remove image at the very beginning"""
 
353
        print
 
354
        print _(
 
355
            'Warning. there is already a temporary image file'
 
356
            ' named %(dest)s.') % vars(self)
 
357
        if console.ask_yesno(_('Do you want me to remove it'), False):
 
358
            print _('Removing '), self.dest, "..."
 
359
            os.remove(self.dest)
 
360
            return True
 
361
        else:
 
362
            return False
 
363
 
 
364
 
 
365
class CDROM:
 
366
    "CDROM class"
 
367
 
 
368
    def __init__(self, options):
 
369
        """ Set up a new instance. """
 
370
        self.wodim_args = []
 
371
        self.wodim = config.get('executables', 'wodim')
 
372
        self.cdrdao = config.get('executables', 'cdrdao')
 
373
        self.speed = config.getint('CD-writer', 'speed')
 
374
        self.device = config.get('CD-writer', 'device')
 
375
        self.source_device = config.get('CD-reader', 'device')
 
376
        self.driver = config.get('CD-writer', 'driver')
 
377
        self.source_driver = config.get('CD-reader', 'driver')
 
378
        self.burnfree = config.getboolean('CD-writer', 'burnfree')
 
379
 
 
380
        self.content_mode = options.mode
 
381
        self.multisession = options.multisession
 
382
        self.simulate = options.simulate
 
383
        self.eject = options.eject
 
384
 
 
385
        self.iso = ISO()
 
386
 
 
387
    def compute_media_size(self):
 
388
        """ Get the storage capacity of the media. """
 
389
        if config.getboolean('Media', 'media-check'):
 
390
            empty = check_media_empty()
 
391
            if not empty:
 
392
                if not self.multisession:
 
393
                    print _('Error. Please insert a blank CD/DVD.')
 
394
                    command_args = [
 
395
                        self.wodim, "-eject",
 
396
                        "dev=%(device)s" % vars(self)]
 
397
                    subprocess.call(command_args, stderr=open(os.devnull))
 
398
                    sys.exit()
 
399
 
 
400
            self.size = get_media_capacity()
 
401
            if not self.size:
 
402
                print _(
 
403
                    "Error. unknown media capacity. "
 
404
                    "Using configuration default.")
 
405
                self.size = config.getint('Media', 'size')
 
406
        else:
 
407
            self.size = config.getint('Media', 'size')
 
408
 
 
409
    def size_compare(self, tobeburned, space_needed):
 
410
        """Checks free space for temporary files and CD oversize"""
 
411
        free_disk_space = int(self.iso.freespace())
 
412
        self.compute_media_size()
 
413
        print
 
414
        print _('To be burned: '), "\t\t\t", tobeburned / 1048576, "Mb"
 
415
        print _('Disk space needed: '), "\t\t", space_needed/1048576, "Mb"
 
416
        print _('Media capacity: '), "\t\t", self.size, "Mb"
 
417
        if self.content_mode is not ContentMode.iso:
 
418
            print _('Free disk space: '), "\t\t", free_disk_space, "Mb"
 
419
        if space_needed == 0:
 
420
            space_needed = tobeburned
 
421
        if self.content_mode is not ContentMode.iso:
 
422
            if (space_needed/1048576) > free_disk_space:
 
423
                if self.content_mode is ContentMode.data:
 
424
                    print _('You do not have enough free disk space'), \
 
425
                        " (", free_disk_space, " Mb )", \
 
426
                        _('to create temporary image file '), \
 
427
                        "( ", tobeburned / 1048576, " Mb )"
 
428
                elif self.content_mode is ContentMode.audio:
 
429
                    print _('You do not have enough free disk space'), \
 
430
                        " (", free_disk_space, " Mb )", \
 
431
                        _('to create temporary audio files '), \
 
432
                        "( ", tobeburned / 1048576, " Mb )"
 
433
                sys.exit()
 
434
        if (tobeburned / 1048576) > int(self.size):
 
435
            if not console.ask_yesno(_(
 
436
                'It seems you are going to burn more than media\'s capacity.\n'
 
437
                'Do you still want to continue'), False):
 
438
                sys.exit()
 
439
        return True
 
440
 
 
441
    def make_command_args(self):
 
442
        """ Generate command-line arguments for track recording. """
 
443
        self.wodim_args = [self.wodim, "-v", "-pad"]
 
444
        if self.simulate:
 
445
            self.wodim_args.append("-dummy")
 
446
        if self.eject:
 
447
            self.wodim_args.append("-eject")
 
448
        if self.speed:
 
449
            self.wodim_args.append("speed=%(speed)s" % vars(self))
 
450
        else:
 
451
            print _('no burning speed defined, using 2x')
 
452
            self.wodim_args.append("speed=2")
 
453
        if self.device:
 
454
            self.wodim_args.append("dev=%(device)s" % vars(self))
 
455
        else:
 
456
            print _('no device specified.')
 
457
            sys.exit()
 
458
        if self.burnfree:
 
459
            self.wodim_args.append("driveropts=burnfree")
 
460
        if self.multisession:
 
461
            self.wodim_args.append("-multi")
 
462
        if self.content_mode in [ContentMode.data, ContentMode.iso]:
 
463
            self.wodim_args.extend(["-data", self.iso.dest])
 
464
 
 
465
    def create(self):
 
466
        """ Execute track recording command. """
 
467
        print
 
468
        if config.getboolean('general', 'pause'):
 
469
            print _('Press a key to begin recording...')
 
470
            console.getch()
 
471
        print _('Please wait...')
 
472
        subprocess.call(self.wodim_args)
 
473
 
 
474
    def double_dao_create(self, command_args):
 
475
        """ Execute disk-at-once copy with two drives (reader and writer). """
 
476
        print
 
477
        print _('Place the source CD in the CD drive')
 
478
        print _('and place a blank media in the recording unit.')
 
479
        print _('Press a key to begin on-the-fly copy')
 
480
        console.getch()
 
481
        subprocess.call(command_args)
 
482
 
 
483
    def single_dao_create(self, command_args):
 
484
        """ Execute disk-at-once copy with one drive. """
 
485
        print
 
486
        print _('Place source CD in the recording unit.')
 
487
        print _('Press a key to begin reading...')
 
488
        console.getch()
 
489
        subprocess.call(command_args)
 
490
 
 
491
    def another_copy(self):
 
492
        """burn image untill user says no"""
 
493
        while console.ask_yesno(_(
 
494
            'Do you want to use this image to make another copy now?'
 
495
            ), False):
 
496
            self.make_command_args()
 
497
            self.create()
 
498
 
 
499
 
 
500
def main():
 
501
    """ Program mainline procedure. """
 
502
 
 
503
    usage = """%prog -MODE [general_option] [mode_option] ...
 
504
 
 
505
For quick start you can get common examples with:
 
506
 
 
507
burn -e
 
508
"""
 
509
    parser = optparse.OptionParser(usage=usage)
 
510
 
 
511
    parser.add_option(
 
512
        "-e", "--examples", action="callback", callback=show_examples,
 
513
        dest="examples",
 
514
        help=_('show examples for quick startup'))
 
515
 
 
516
    #Modes
 
517
    mode_options = optparse.OptionGroup(
 
518
        parser, _('Main burn MODES'),
 
519
        _('They _have_ to be the first argument after program name'))
 
520
    mode_options.add_option(
 
521
        "-D", "--data-cd",
 
522
        action="store_const", dest="mode", const=ContentMode.data,
 
523
        help=_('creates a Data CD/DVD.'))
 
524
    mode_options.add_option(
 
525
        "-I", "--iso-cd",
 
526
        action="store_const", dest="mode", const=ContentMode.iso,
 
527
        help=_('creates a CD/DVD from ISO.'))
 
528
    mode_options.add_option(
 
529
        "-C", "--copy-cd",
 
530
        action="store_const", dest="mode", const=ContentMode.copy,
 
531
        help=_('copy CD/DVD.'))
 
532
    mode_options.add_option(
 
533
        "-A", "--audio-cd",
 
534
        action="store_const", dest="mode", const=ContentMode.audio,
 
535
        help=_('creates an Audio CD from .wav, .mp3 and .ogg files.'))
 
536
 
 
537
    #General options
 
538
    general_option = optparse.OptionGroup(
 
539
        parser, "General options",
 
540
        _(
 
541
            'These options could be used for every burn mode'
 
542
            ' unless stated otherwise'))
 
543
 
 
544
    general_option.add_option(
 
545
        "-s", "--simulate", action="store_true", dest="simulate",
 
546
        help=_('This option will perform a burn simulation.'))
 
547
    general_option.add_option(
 
548
        "-j", "--eject", action="store_true", dest="eject",
 
549
        help=_(
 
550
            'This option will eject disk when burn process is over.'))
 
551
    general_option.add_option(
 
552
        "--dao", action="store_true", dest="dao",
 
553
        help=_(
 
554
            'Enable disk at once. Enabling this option, you will not have'
 
555
            ' 2 seconds gap between tracks.'))
 
556
 
 
557
    #DATA-CD Options
 
558
    data_cd = optparse.OptionGroup(parser, _('Data CD Mode (-D) options'),
 
559
        _('Data CD: adds files and directories.'))
 
560
    data_cd.add_option(
 
561
        "-p", "--path",
 
562
        action="callback", callback=varargs, dest="path",
 
563
        help=_(
 
564
            'add file/s or path\'s content to CD-ROM/DVD\'s root.'
 
565
            ' e.g.: -p /cvs/myproj/ <return>. In this example we will find'
 
566
            ' CD-ROM/DVD\'s root filled with /cvs/myproj/ contents, but'
 
567
            ' no /cvs/myproj/ will be created.'))
 
568
    data_cd.add_option(
 
569
        "-r", "--preserve-path",
 
570
        action="callback", callback=varargs, dest="preserve_path",
 
571
        help=_(
 
572
            'add file/s or path\'s content to CD-ROM/DVD preserving'
 
573
            ' original path. e.g.: -r /cvs/myproj/ <return>. In this'
 
574
            ' example we will find /cvs/myproj/ in CD-ROM/DVD\'s root.'))
 
575
    data_cd.add_option(
 
576
        "-x", "--exclude-path",
 
577
        #action="append", type="string", dest="exclude_path",
 
578
        action="callback", callback=varargs, dest="exclude_path",
 
579
        help=_(
 
580
            'every file or directory matching this string'
 
581
            ' will not be included.'))
 
582
    data_cd.add_option(
 
583
        "-c", "--change-path", action="append",
 
584
        nargs=2, type="string", dest="change_path",
 
585
        help=_(
 
586
            'usage: -c <new_path> <old_path>. With this option,'
 
587
            ' old_path will be named new_path in CD-ROM/DVD.'
 
588
            ' e.g.: -c /my_home/2004_Jan/ /home/bigpaul/ <return>.'
 
589
            ' Thus /home/bigpaul/ will be named  /my_home/2004_Jan/'
 
590
            ' in CD-ROM/DVD.'))
 
591
    data_cd.add_option(
 
592
        "-l", "--follow-symlink", action="store_true", dest="follow_symlink",
 
593
        help=_('this option allows burn to follow symbolic link directories'))
 
594
    data_cd.add_option(
 
595
        "-m", "--multisession", action="store_true", dest="multisession",
 
596
        help=_('this option allows multisession CDs'))
 
597
 
 
598
    #ISO-CD Options
 
599
    iso_cd = optparse.OptionGroup(parser, "ISO CD Mode (-I) options",
 
600
        _('Creates a CD-ROM/DVD from an existing image.'))
 
601
 
 
602
    iso_cd.add_option(
 
603
        "-n", "--name", action="store", type="string", dest="iso_name",
 
604
        help=_('image name'))
 
605
 
 
606
    #COPY-CD Options
 
607
    copy_cd = optparse.OptionGroup(
 
608
        parser, _('Copy CD Mode (-C) options'),
 
609
        _(
 
610
            'If you have both a reader and a recording unit'
 
611
            ' you can perform a copy on-the-fly. You can also copy a CD'
 
612
            ' even if you only have the recording unit.'))
 
613
 
 
614
    #AUDIO-CD Options
 
615
    audio_cd = optparse.OptionGroup(
 
616
        parser, _('Audio CD Mode (-A) options'),
 
617
        _(
 
618
            'Audio CD is used to create an audio CD-ROM'
 
619
            ' from .wav, .ogg and .mp3 files. You can can use -a option'
 
620
            ' to perform an Audio CD from different source audio files.'))
 
621
    audio_cd.add_option(
 
622
        "-a", "--audio-file",
 
623
        action="callback", callback=varargs, dest="general_audio_file_list",
 
624
        help=_(
 
625
            '.wav, .mp3, .ogg file/s. Files must have extensions'
 
626
            ' (no matter if they are upper or lowercase).'))
 
627
    audio_cd.add_option(
 
628
        "--audio-list",
 
629
        action="store", type="string", dest="file_list",
 
630
        help=_('m3u playlist or file with one audio file per line.'))
 
631
    audio_cd.add_option(
 
632
        "--clear-audiotemp",
 
633
        action="store_true", dest="clear_audio_temp",
 
634
        help=_('remove temporary audio files.'))
 
635
    audio_cd.add_option(
 
636
        "--no-gaps", action="store_true", dest="nogaps",
 
637
        help=_(
 
638
            'Enable disk at once. Enabling this option, you will not have'
 
639
            ' 2 seconds gap between tracks.'))
 
640
 
 
641
    parser.add_option_group(mode_options)
 
642
    parser.add_option_group(general_option)
 
643
    parser.add_option_group(data_cd)
 
644
    parser.add_option_group(iso_cd)
 
645
    parser.add_option_group(copy_cd)
 
646
    parser.add_option_group(audio_cd)
 
647
    (options, args) = parser.parse_args()
 
648
 
 
649
    if len(sys.argv) > 1:
 
650
        check_main_option(sys.argv[1])
 
651
    else:
 
652
        prog_intro()
 
653
        parser.print_help()
 
654
        sys.exit()
 
655
 
 
656
    configure.read_from_files()
 
657
 
 
658
    prog_intro(options.mode)
 
659
    cdrom = CDROM(options)
 
660
 
 
661
    if options.mode is ContentMode.data:
 
662
        print _('Checking files, directories and disk usage. Please wait...')
 
663
        print
 
664
        path = ''
 
665
        path_preserved = ''
 
666
        path_changed = ''
 
667
        paths_excluded = []
 
668
        size = 0
 
669
        first_time_multisession = 0
 
670
 
 
671
        if options.path:
 
672
            for directory in options.path:
 
673
                if os.path.exists(directory):
 
674
                    abspath = os.path.abspath(directory)
 
675
                    path = path + '\'' + abspath + '\'' + ' '
 
676
                    if os.path.isfile(abspath):
 
677
                        size = size + os.path.getsize(abspath)
 
678
                    elif os.path.isdir(abspath):
 
679
                        size = size + du(abspath, 0, options.follow_symlink)
 
680
                    else:
 
681
                        err(abspath + _(': no such file or directory.'))
 
682
                else:
 
683
                    err_nf(directory)
 
684
        if options.preserve_path:
 
685
            for directory in options.preserve_path:
 
686
                if os.path.exists(directory):
 
687
                    abspath = os.path.abspath(directory)
 
688
                    if os.path.isdir(abspath):
 
689
                        size = size + du(abspath, 0, options.follow_symlink)
 
690
                    elif os.path.isfile(abspath):
 
691
                        size = size + os.path.getsize(abspath)
 
692
                    else:
 
693
 
 
694
                        err(abspath + _(': no such file or directory.'))
 
695
                        sys.exit()
 
696
                    path_preserved = path_preserved \
 
697
                        + '\'' + abspath + '\'' + '=' \
 
698
                        + '\'' + abspath + '\'' + ' '
 
699
                else:
 
700
                    err_nf(directory)
 
701
        if options.change_path:
 
702
            for (new_path, old_path) in options.change_path:
 
703
                if os.path.exists(old_path):
 
704
                    abspath = os.path.abspath(old_path)
 
705
                    if os.path.isfile(abspath):
 
706
                        size += os.path.getsize(abspath)
 
707
                    elif os.path.isdir(abspath):
 
708
                        size += du(abspath, 0, options.follow_symlink)
 
709
                    else:
 
710
                        err(abspath + _(': no such file or directory.'))
 
711
                        sys.exit()
 
712
                    path_changed = path_changed \
 
713
                        + '\'' + new_path + '\'' + '=' \
 
714
                        + '\'' + abspath + '\'' + ' '
 
715
                else:
 
716
                    err_nf(old_path)
 
717
                    print _(
 
718
                        'nothing will be done for %(old_path)s -> %(new_path)s'
 
719
                        ) % vars()
 
720
        if options.exclude_path:
 
721
            testsize = size
 
722
            for directory in options.path:
 
723
                if os.path.isdir(directory):
 
724
                    for exclude_path in options.exclude_path:
 
725
                        for root, dirs, files in os.walk(directory):
 
726
                            for file_name in files:
 
727
                                if fnmatch.fnmatch(file_name, exclude_path):
 
728
                                    if os.path.exists(
 
729
                                        os.path.join(root, file_name)):
 
730
                                        if os.path.isfile(
 
731
                                            os.path.join(root, file_name)):
 
732
                                            size = size - os.path.getsize(
 
733
                                                os.path.join(root, file_name))
 
734
                                            paths_excluded.append(
 
735
                                                os.path.join(root, file_name))
 
736
                            for subdir in dirs:
 
737
                                if fnmatch.fnmatch(subdir, exclude_path):
 
738
                                    if os.path.exists(
 
739
                                        os.path.join(root, subdir)):
 
740
                                        size = size - du(
 
741
                                            os.path.join(root, subdir), 0,
 
742
                                            options.follow_symlink)
 
743
                                        paths_excluded.append(
 
744
                                            os.path.join(root, subdir))
 
745
            print
 
746
            print _('Size without exclusions: '), "\t", testsize/1048576, "Mb"
 
747
 
 
748
        global_path = path + path_preserved + path_changed
 
749
        if global_path == '':
 
750
            err(_('Nothing to be burned...'))
 
751
            sys.exit()
 
752
        cdrom.size_compare(size, size)
 
753
 
 
754
        cdrom.iso.genisoimage_args.extend(
 
755
            [config.get('executables', 'genisoimage'), "-R"])
 
756
        if os.path.exists(cdrom.iso.tempdir):
 
757
            cdrom.iso.genisoimage_args.extend(["-o", cdrom.iso.dest])
 
758
        else:
 
759
            err(_('Error: ') + cdrom.iso.tempdir + _(' does not exist'))
 
760
            sys.exit()
 
761
 
 
762
        if cdrom.iso.windows:
 
763
            cdrom.iso.genisoimage_args.extend(["-J", "-joliet-long"])
 
764
 
 
765
        for path_excluded in paths_excluded:
 
766
            cdrom.iso.genisoimage_args.extend(["-x", path_excluded])
 
767
 
 
768
        if options.multisession:
 
769
            multisession_choose = cdrom.iso.ask_multisession()
 
770
            if multisession_choose == 2:
 
771
                #ciao
 
772
                print _(
 
773
                    'Place target CD in CD/DVD writer unit and press a key...')
 
774
                console.getch()
 
775
                print _('Please wait...')
 
776
                command_args = [
 
777
                    config.get('executables', 'wodim'), "-msinfo",
 
778
                    "dev=%(device)s" % vars(cdrom)]
 
779
                command_process = subprocess.Popen(
 
780
                    command_args,
 
781
                    stdout=subprocess.PIPE, stderr=open(os.devnull))
 
782
                msinfo = command_process.communicate()[0]
 
783
                cdrom.iso.genisoimage_args.extend(
 
784
                    ["-C", msinfo, "-M", cdrom.device])
 
785
            elif not multisession_choose == 1:
 
786
                sys.exit()
 
787
            else:
 
788
                first_time_multisession = 1
 
789
        cdrom.iso.genisoimage_args.extend(["-graft-points", global_path])
 
790
        cdrom.make_command_args()
 
791
        if os.path.exists(cdrom.iso.dest):
 
792
            if not cdrom.iso.first_ask_remove():
 
793
                cdrom.another_copy()
 
794
                sys.exit()
 
795
        cdrom.iso.create()
 
796
        if first_time_multisession == 1:
 
797
            cdrom.iso.ask_mount(cdrom.iso.dest)
 
798
        cdrom.create()
 
799
        if os.path.exists(cdrom.iso.dest):
 
800
            if not cdrom.iso.ask_remove():
 
801
                cdrom.another_copy()
 
802
        sys.exit()
 
803
 
 
804
    if options.mode is ContentMode.iso:
 
805
        if os.path.exists(options.iso_name):
 
806
            if cdrom.size_compare(os.path.getsize(options.iso_name), 0):
 
807
                print
 
808
                cdrom.iso.dest = options.iso_name
 
809
                cdrom.iso.ask_mount(options.iso_name)
 
810
                cdrom.make_command_args()
 
811
                cdrom.create()
 
812
                if os.path.exists(cdrom.iso.dest):
 
813
                    if not cdrom.iso.ask_remove():
 
814
                        cdrom.another_copy()
 
815
            else:
 
816
                sys.exit()
 
817
        else:
 
818
            err_nf(options.iso_name)
 
819
            sys.exit()
 
820
        sys.exit()
 
821
 
 
822
    if options.mode is ContentMode.copy:
 
823
        cdrom.compute_media_size()
 
824
        single_drive_mode = 0
 
825
        if cdrom.device == cdrom.source_device or cdrom.source_device == '':
 
826
            single_drive_mode = 1
 
827
            #print single_drive_mode
 
828
        cdrdao_args = [config.get('executables', 'cdrdao')]
 
829
 
 
830
        if single_drive_mode == 1:
 
831
            cdrdao_args.append("copy")
 
832
            if options.simulate:
 
833
                cdrdao_args.append("--simulate")
 
834
            if options.eject:
 
835
                cdrdao_args.append("--eject")
 
836
            cdrdao_args.extend(["--datafile", cdrom.iso.dest])
 
837
            cdrdao_args.extend(["--device", cdrom.device])
 
838
            if not cdrom.driver == '':
 
839
                cdrdao_args.extend(["--driver", cdrom.driver])
 
840
            cdrdao_args.extend(["--speed", str(cdrom.speed)])
 
841
            cdrdao_args.append("--fast-toc")
 
842
            cdrom.single_dao_create(cdrdao_args)
 
843
        else:
 
844
            cdrdao_args.append("copy")
 
845
            if options.simulate:
 
846
                cdrdao_args.append("--simulate")
 
847
            if options.eject:
 
848
                cdrdao_args.append("--eject")
 
849
            cdrdao_args.extend(["--device", cdrom.device])
 
850
            if not cdrom.driver == '':
 
851
                cdrdao_args.extend(["--driver", cdrom.driver])
 
852
            cdrdao_args.extend(["--source-device", cdrom.source_device])
 
853
            if not cdrom.source_driver == '':
 
854
                cdrdao_args.extend(["--source-driver", cdrom.source_driver])
 
855
            cdrdao_args.extend(["--speed", str(cdrom.speed)])
 
856
            cdrdao_args.append("--on-the-fly")
 
857
            cdrdao_args.append("--fast-toc")
 
858
            cdrom.double_dao_create(cdrdao_args)
 
859
        sys.exit()
 
860
 
 
861
    if options.mode is ContentMode.audio:
 
862
        print _('Audio file processing. Please wait...')
 
863
        print
 
864
        audio_list = []
 
865
        to_be_removed = []
 
866
        old_temp_wavs = []
 
867
        file_list = []
 
868
        track_type = ''
 
869
        size = 0
 
870
        track_number = 0
 
871
        track_number2 = 0
 
872
        mp3_ogg_size = 0
 
873
        counter = 1000
 
874
        total_audio_time = 0
 
875
 
 
876
        #61196 wav header????
 
877
        #176400 kb 1 wav second comes from:
 
878
        #44100 * 16 * 2bit / 8 = byte
 
879
 
 
880
        list_dir = os.listdir(cdrom.iso.tempdir)
 
881
 
 
882
        if options.clear_audio_temp:
 
883
            for file_path in list_dir:
 
884
                if re.compile("^burn_1").search(file_path[:5], 0):
 
885
                    old_temp_wavs.append(
 
886
                        os.path.normpath(cdrom.iso.tempdir + file_path))
 
887
            if old_temp_wavs:
 
888
                print
 
889
                for old_wavs in old_temp_wavs:
 
890
                    print _('removing '), old_wavs, "..."
 
891
                    os.remove(old_wavs)
 
892
        if options.general_audio_file_list:
 
893
            file_list = options.general_audio_file_list
 
894
 
 
895
        if options.file_list:
 
896
            file_list.extend(get_list_from_file(options.file_list))
 
897
 
 
898
        for file_path in file_list:
 
899
            base, ext = os.path.splitext(file_path)
 
900
            ext = ext.lower()
 
901
            if ext == '.ogg' or ext == '.mp3':
 
902
                mp3_ogg_size += (
 
903
                    audio.file_duration(file_path) * 176400)
 
904
            if ext == '.wav':
 
905
                size += os.path.getsize(file_path)
 
906
            if ext != '.ogg' and ext != '.mp3' and ext != '.wav':
 
907
                print file_path, _(': not a regular audio file. Skipped')
 
908
 
 
909
        cdrom.size_compare((size+mp3_ogg_size), mp3_ogg_size)
 
910
        print
 
911
 
 
912
        list_dir = os.listdir(cdrom.iso.tempdir)
 
913
        old_temp_wavs = []
 
914
        for file_path in list_dir:
 
915
            if re.compile("^burn_1").search(file_path[:5], 0):
 
916
                old_temp_wavs.append(
 
917
                    os.path.normpath(cdrom.iso.tempdir + file_path))
 
918
        if old_temp_wavs:
 
919
            print
 
920
            for wav_path in old_temp_wavs:
 
921
                print wav_path
 
922
            if console.ask_yesno(_(
 
923
                'You have old burn audio files in temporary directory.'
 
924
                ' Remove these files and continue'
 
925
                ), False):
 
926
                for oldwavs in old_temp_wavs:
 
927
                    print _('removing '), oldwavs, "..."
 
928
                    os.remove(oldwavs)
 
929
            else:
 
930
                sys.exit()
 
931
        print
 
932
        print "---------------------------------------------"
 
933
        print "Burn - " + _('Track summary')
 
934
        print "---------------------------------------------"
 
935
        for file_path in file_list:
 
936
            track_number = track_number + 1
 
937
            base, ext = os.path.splitext(file_path)
 
938
            ext = ext.lower()
 
939
 
 
940
            if ext == '.mp3' or ext == '.ogg':
 
941
                if os.path.exists(file_path):
 
942
                    abspath = os.path.abspath(file_path)
 
943
                    if os.path.isfile(abspath):
 
944
                        info = audio.FileInfo(abspath)
 
945
                        if info.title:
 
946
                            print track_number, ")\t", \
 
947
                                info.duration, "-", info.title
 
948
                        else:
 
949
                            print track_number, ")\t", \
 
950
                                info.duration, "-", os.path.abspath(file_path)
 
951
                        total_audio_time += info.total_time
 
952
            else:
 
953
                print track_number, ")\t", audio.compute_duration(
 
954
                    os.path.getsize(os.path.abspath(file_path)) / 176400), \
 
955
                    "-", os.path.abspath(file_path)
 
956
                total_audio_time += os.path.getsize(
 
957
                    os.path.abspath(file_path)) / 176400
 
958
        # print "Total audio time: ", int(total_audio_time)
 
959
        print
 
960
        print _('Total Audio-CD: '), audio.compute_duration(
 
961
            int(total_audio_time))
 
962
        print
 
963
        if config.getboolean('general', 'external_decoding'):
 
964
            print _('Performing audio decoding with external decoder.')
 
965
            ogg_decoder = config.get('executables', 'ogg_decoder')
 
966
            mp3_decoder = config.get('executables', 'mp3_decoder')
 
967
            ogg_decoder_option = config.get(
 
968
                'executables', 'ogg_decoder_option')
 
969
            mp3_decoder_option = config.get(
 
970
                'executables', 'mp3_decoder_option')
 
971
        else:
 
972
            print _('Performing audio decoding with burn\'s native functions.')
 
973
        for file_path in file_list:
 
974
            track_number2 = track_number2 + 1
 
975
            base, ext = os.path.splitext(file_path)
 
976
            ext = ext.lower()
 
977
 
 
978
            if ext == '.mp3' or ext == '.ogg':
 
979
                counter = counter + 1
 
980
                if ext == '.mp3':
 
981
                    track_type = 'MP3'
 
982
                else:
 
983
                    track_type = 'OGG'
 
984
                if os.path.exists(file_path):
 
985
                    abspath = os.path.abspath(file_path)
 
986
                    if os.path.isfile(abspath):
 
987
                        #Shows full path ogg files
 
988
                        print _(
 
989
                            "[%(track_number2)d/%(track_number)d]"
 
990
                            " %(track_type)s\tProcessing %(abspath)s") % vars()
 
991
                        info = audio.FileInfo(abspath)
 
992
                        #Shows ID3 TAGS
 
993
                        #print "\t\tTitle: \t\t",info.title
 
994
                        #print "\t\tAlbum: \t\t",info.album
 
995
                        #print "\t\tArtist: \t",info.artist
 
996
                        #Convert mp3/ogg file in tempdir/file.[mp3|ogg].wav
 
997
                    if ext == '.mp3':
 
998
                        if config.getboolean('general', 'external_decoding'):
 
999
                            wav_name = "burn_%(counter)d.wav" % vars()
 
1000
                            wav_path = os.path.normpath(os.path.join(
 
1001
                                cdrom.iso.tempdir, wav_name))
 
1002
                            command_args = [mp3_decoder]
 
1003
                            command_args.extend(
 
1004
                                shlex.split(mp3_decoder_option))
 
1005
                            command_args.extend([wav_path, abspath])
 
1006
                            subprocess.call(command_args)
 
1007
                        else:
 
1008
                            dev = ao.AudioDevice(
 
1009
                                'wav', filename=(
 
1010
                                    os.path.normpath(
 
1011
                                        cdrom.iso.tempdir
 
1012
                                        + 'burn_' + repr(counter))
 
1013
                                    + '.wav'),
 
1014
                                overwrite=True)
 
1015
                            pbar = console.ProgressBar(width=30)
 
1016
                            audio_buffer = mad.MadFile(abspath)
 
1017
                            old_progress = 0
 
1018
                            while True:
 
1019
                                buf = audio_buffer.read()
 
1020
                                if buf is None:
 
1021
                                    break
 
1022
                                progress = \
 
1023
                                    audio_buffer.current_time() * 100 / \
 
1024
                                        audio_buffer.total_time()
 
1025
                                if progress > old_progress:
 
1026
                                    pbar.amount = progress
 
1027
                                    pbar.update_display()
 
1028
                                old_progress = progress
 
1029
                                dev.play(buf, len(buf))
 
1030
                        audio_list.append(os.path.normpath(
 
1031
                            cdrom.iso.tempdir
 
1032
                            + 'burn_' + repr(counter)) + '.wav')
 
1033
                        to_be_removed.append(os.path.normpath(
 
1034
                            cdrom.iso.tempdir
 
1035
                            + 'burn_' + repr(counter)) + '.wav')
 
1036
                    elif ext == '.ogg':
 
1037
                        size = 4096
 
1038
                        if config.getboolean('general', 'external_decoding'):
 
1039
                            wav_name = "burn_%(counter)d.wav" % vars()
 
1040
                            wav_path = os.path.normpath(os.path.join(
 
1041
                                cdrom.iso.tempdir, wav_name))
 
1042
                            command_args = [ogg_decoder]
 
1043
                            command_args.extend(
 
1044
                                shlex.split(ogg_decoder_option))
 
1045
                            command_args.extend([wav_path, abspath])
 
1046
                            subprocess.call(command_args)
 
1047
                        else:
 
1048
                            dev = ao.AudioDevice(
 
1049
                                'wav', filename=os.path.normpath(
 
1050
                                    cdrom.iso.tempdir
 
1051
                                    + 'burn_' + repr(counter))
 
1052
                                + '.wav',
 
1053
                                overwrite=True)
 
1054
                            pbar = console.ProgressBar(width=30)
 
1055
                            audiofile = ogg.vorbis.VorbisFile(abspath)
 
1056
                            old_progress = 0
 
1057
                            while True:
 
1058
                                (buf, bytes, bit) = audiofile.read(size)
 
1059
                                if bytes == 0:
 
1060
                                    break
 
1061
                                progress = \
 
1062
                                    audiofile.time_tell() * 100 / \
 
1063
                                        audiofile.time_total(-1)
 
1064
                                if progress > old_progress:
 
1065
                                    pbar.amount = progress
 
1066
                                    pbar.update_display()
 
1067
                                old_progress = progress
 
1068
                                dev.play(buf, bytes)
 
1069
 
 
1070
                        audio_list.append(os.path.normpath(
 
1071
                            cdrom.iso.tempdir
 
1072
                            + 'burn_' + repr(counter)) +'.wav')
 
1073
                        to_be_removed.append(os.path.normpath(
 
1074
                            cdrom.iso.tempdir
 
1075
                            + 'burn_' + repr(counter)) +'.wav')
 
1076
                    else:
 
1077
                        err(abspath + _(': not a valid audio file.'))
 
1078
 
 
1079
            if ext == '.wav':
 
1080
                track_type = 'WAV'
 
1081
                if os.path.exists(file_path):
 
1082
                    abspath = os.path.abspath(file_path)
 
1083
                    print _(
 
1084
                        "[%(track_number2)d/%(track_number)d]"
 
1085
                        " %(track_type)s\tProcessing %(abspath)s") % vars()
 
1086
                    audio_list.append(abspath)
 
1087
 
 
1088
        cdrom.make_command_args()
 
1089
        if options.nogaps:
 
1090
            cdrom.wodim_args.append("-dao")
 
1091
        cdrom.wodim_args.append("-audio")
 
1092
        cdrom.wodim_args.extend(audio_list)
 
1093
 
 
1094
        #burning CD
 
1095
        cdrom.create()
 
1096
        if config.getboolean('general', 'pause'):
 
1097
            while console.ask_yesno(_(
 
1098
                'Do you want to use processed audio files to create'
 
1099
                ' another Audio CD now'), False):
 
1100
                cdrom.create()
 
1101
        else:
 
1102
            while console.ask_yesno(_(
 
1103
                'Write another copy (insert a blank disc now)'),
 
1104
                False):
 
1105
                console.getch()
 
1106
                cdrom.create()
 
1107
 
 
1108
        #removing temp audio files
 
1109
        for file_path in to_be_removed:
 
1110
            if os.path.exists(file_path):
 
1111
                print _('removing '), file_path, "..."
 
1112
                os.remove(file_path)
 
1113
 
 
1114
        sys.exit()
 
1115
 
 
1116
 
 
1117
if __name__ == '__main__':
 
1118
    try:
 
1119
        main()
 
1120
    except KeyboardInterrupt:
 
1121
        print
 
1122
        print _('burn: exiting now...')
 
1123
 
 
1124
 
 
1125
# Local variables:
 
1126
# mode: python
 
1127
# coding: utf-8
 
1128
# End:
 
1129
# vim: filetype=python fileencoding=utf-8 :