summaryrefslogtreecommitdiff
path: root/jack
blob: d59c9499a7a0c2e64493f6a44ac5b72c287dcd4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
#!/usr/bin/env python
### jack - extract audio from a CD and encode it using 3rd party software
### Copyright (C) 1999-2004  Arne Zellentin <zarne@users.sf.net>

### This program is free software; you can redistribute it and/or modify
### it under the terms of the GNU General Public License as published by
### the Free Software Foundation; either version 2 of the License, or
### (at your option) any later version.

### This program is distributed in the hope that it will be useful,
### but WITHOUT ANY WARRANTY; without even the implied warranty of
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
### GNU General Public License for more details.

### You should have received a copy of the GNU General Public License
### along with this program; if not, write to the Free Software
### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

### If you want to comment on this program, contact me: zarne@users.sf.net ###
### Visit the homepage: http://www.home.unix-ag.org/arne/jack/

### see CHANGELOG for recent changes in this program
### see TODO if you want to see what needs to be implemented

import os
import sys
import time
import wave
import types
import posix
import string
import select
import signal
import pprint
import traceback

from jack_globals import *

import jack_version
import jack_misc
import jack_mp3
import jack_argv
import jack_rc
import jack_helpers
import jack_targets
import jack_freedb
import jack_display
import jack_term
import jack_children
import jack_tag
import jack_workers
import jack_utils
import jack_ripstuff
import jack_encstuff
import jack_checkopts
import jack_status
import jack_functions
import jack_main_loop
import jack_progress
import jack_prepare


##############################################################################
###################### M A I N ###############################################
##############################################################################

# say hello...
print "This is", jack_version.prog_name, jack_version.prog_version, jack_version.prog_copyright, jack_version.prog_devemail

### interpret options
global_cf = jack_rc.load(cf, cf['global_rc']['val'])
jack_checkopts.checkopts(cf, global_cf)
cf.rupdate(global_cf, "global_rc")
user_cf = jack_rc.load(cf, cf['user_rc']['val'])
jack_checkopts.checkopts(cf, user_cf)
cf.rupdate(user_cf, "user_rc")
help, argv_cf = jack_argv.parse_argv(cf, sys.argv)
jack_checkopts.checkopts(cf, argv_cf)
cf.rupdate(argv_cf, "argv")
if help:
    jack_argv.show_usage(cf, long=help-1)
    sys.exit(0)
debug("global_cf: " + `global_cf`)
debug("user_cf: " + `user_cf`)
debug("argv_cf: " + `argv_cf`)

jack_checkopts.consistency_check(cf)

if cf['save_args']['val'] == 1:
    count = jack_rc.save(cf['user_rc']['val'], cf)
    info("%d options saved in %s" % (count, cf['user_rc']['val']))
    sys.exit()

ext = jack_targets.targets[jack_helpers.helpers[cf['_encoder']]['target']]['file_extension']

### (1) search for a dir containing a toc-file or do the multi-mode
toc_just_read = jack_prepare.find_workdir()
os.environ["JACK_CUR_DIR"] = os.getcwd()
os.environ["JACK_BASE_DIR"] = cf['_base_dir']
# now we are set to go as we know we are in the right dir

### (2) check toc (operation mode)
if cf['_check_toc']:
    jack_prepare.check_toc()
    sys.exit(0)

### (3a) read and interpret toc_file
is_submittable, track1_offset = jack_prepare.read_toc_file()

### (3b) make sure we have a freedb file
if not os.path.exists(cf['_freedb_form_file']):
    jack_freedb.freedb_template(jack_ripstuff.all_tracks)

### (4a) filter out data tracks
jack_prepare.filter_tracks(toc_just_read)

### (4b) Parse tracks from argv, generate todo
todo = jack_prepare.gen_todo()
if len(todo) == 0:
    error("nothing to do. bye.")

### init status
jack_status.init(todo)

#XXX## (5) read progress info into status

jack_ripstuff.all_tracks_orig = []
for i in jack_ripstuff.all_tracks:
    jack_ripstuff.all_tracks_orig.append(i[:])

status = jack_prepare.init_status()

### (6) update progress file at user's request (operation mode)
if cf['_upd_progress']:
    jack_prepare.update_progress(todo)
    sys.exit(0)

### (7) now read in the progress file
status = jack_prepare.read_progress(status, todo)

### (8) submit freedb data on user's request
if cf['_freedb_submit'] or cf['_freedb_mailsubmit']:
    jack_prepare.freedb_submit()
    sys.exit(0)

### (9) do query on start
freedb_rename = 0
if cf['_query_if_needed']:
    if not os.path.exists(cf['_freedb_form_file'] + ".bak"):
        cf['_query_on_start'] = 1
if cf['_query_on_start']:
    freedb_rename = jack_prepare.query_on_start()

### (10) update freedb dbfile
if cf['_update_freedb']:
    if not jack_tag.track_names:
        err, jack_tag.track_names, jack_tag.locale_names, freedb_rename, revision = jack_freedb.interpret_db_file(jack_ripstuff.all_tracks, cf['_freedb_form_file'], verb = 1, dirs = 0)
    jack_freedb.freedb_template(jack_ripstuff.all_tracks, jack_tag.track_names, revision + 1)
    jack_utils.ex_edit(cf['_freedb_form_file'])
    info("now submit your changes if you like, using the option --submit (via http POST). Don't forget to activate your changes locally with -R")
    sys.exit(0)

### (11) undo renaming (operation mode)
if cf['_undo_rename']:
    jack_prepare.undo_rename(status, todo)
    sys.exit(0)

#### Reorder if told so
if cf['_reorder']:
    todo.sort(jack_utils.cmp_toc)
    todo.reverse()

#### check how much bytes we can burn
if cf['space_from_argv']['history'][-1][0] == "argv":
    space = jack_ripstuff.raw_space = cf['_space_from_argv']
else:
    space = jack_ripstuff.raw_space = jack_functions.df()

#### check what is already there
space, remove_q, wavs_todo, mp3s_todo, dae_queue, enc_queue = jack_prepare.what_todo(space, todo)

if cf['_todo_exit']:           # print what needs to be done, then exit
    jack_prepare.print_todo(todo, wavs_todo, mp3s_todo)
    sys.exit(0)

# now mp3s_todo contains the tracks where the wavs only need to be coded and
# wavs_todo lists those tracks which need to be dae'd end enc'd. The dae_queue
# has been filled from wavs_todo (todo is superflous now). The main_loop
# will handle the tracks in mp3s_todo.

### make sure we have enough space to rip the whole thing
jack_prepare.check_space(space, wavs_todo, mp3s_todo)

cf['_max_load'] = cf['_max_load'] + cf['_encoders'] #XXX

if not cf['_dont_work'] and dae_queue:     # check if inserted cd matches toc.
    jack_prepare.check_cd() # why? paranoia or needed? XXX
    if cf['_rip_from_device']:
        all_tracks_on_cd = jack_functions.gettoc(cf['_toc_prog'])
        if not cf['_force'] and not jack_utils.cmp_toc_cd(jack_ripstuff.all_tracks_orig, all_tracks_on_cd, what=(NUM, LEN)):
            error("you did not insert the right cd")

### if we have work to do, we may have to remove some files first
if remove_q:
    jack_prepare.remove_files(remove_q)

### bail out now if told so
if cf['_dont_work']:
    info("quitting now as requested.")
    sys.exit(0)

### install signal handlers
signal.signal(signal.SIGTERM, jack_display.sig_handler)
signal.signal(signal.SIGINT, jack_display.sig_handler)
signal.signal(signal.SIGQUIT, jack_display.sig_handler)
signal.signal(signal.SIGHUP, jack_display.sig_handler)


       #\                         /#
#########> real work starts here <#############################################
       #/                         \#

global_error = None
if (wavs_todo or mp3s_todo):
    jack_ripstuff.gen_printable_names(jack_tag.track_names, todo)
    jack_term.init(cf['_terminal'], cf['_xtermset_enable'])
    jack_display.init()
    try:
        jack_term.enable()
        global_error = jack_main_loop.main_loop(mp3s_todo, wavs_todo, space, dae_queue, enc_queue, track1_offset)
    except SystemExit:
        jack_term.disable()
        print jack_display.options_string
        print "--- Last status: ---------------------------------------------------------------"
        jack_status.print_status(form = 'short')
        sys.exit(0)
    except:
        jack_term.disable()
        warning("abnormal exit")
        traceback.print_exc()         
        sys.exit(1)
# Set the files we have processed but this may still be overwritten by
# jack_tag.tag() called below.
os.environ["JACK_JUST_ENCODED"] = "\n".join([x[NAME] + ext for x in mp3s_todo])
os.environ["JACK_JUST_RIPPED"] = "\n".join([x[NAME] + ".wav" for x in wavs_todo])

jack_term.disable()
if cf['_query_when_ready']:
    info("querying...")
    if jack_freedb.freedb_query(jack_freedb.freedb_id(jack_ripstuff.all_tracks), jack_ripstuff.all_tracks, cf['_freedb_form_file']):
        jack_display.exit()

if cf['_query_when_ready'] or cf['_read_freedb_file'] or cf['_query_on_start']:
    err, jack_tag.track_names, jack_tag.locale_names, freedb_rename, revision = jack_freedb.interpret_db_file(jack_ripstuff.all_tracks, cf['_freedb_form_file'], verb = 1, dirs = 1)
    if err:
        error("could not read freedb file")

if jack_term.term_type == "curses":
    if jack_display.options_string:
        print jack_display.options_string
    print "The final status was:"
    jack_status.print_status(form = 'short')

if global_error:
    if cf['_exec_when_done']:
        os.system(cf['_exec_err'])
    error("aborting because of previous error(s) [%i]." % global_error)

jack_tag.tag(freedb_rename)

if jack_functions.progress_changed:
    jack_functions.progress("all", "done", time.strftime("%b %2d %H:%M:%S", time.localtime(time.time())))

if cf['_remove_files']:
    print "cleaning up in", os.getcwd()
    for i in [cf['_progress_file'], cf['_toc_file'], cf['_def_toc'], cf['_freedb_form_file'], cf['_freedb_form_file'] + ".bak"]:
        if os.path.exists(i):
            os.remove(i)

if cf['_exec_when_done']:
    os.system(cf['_exec_no_err'])

jack_display.exit()      # call the cleanup function & exit


###############################################################################
##################################         ####################################
##################################  T H E  ####################################
##################################  E N D  ####################################
##################################         ####################################
###############################################################################