Exemple #1
0
def undo_rename(status, todo):
    ext = jack_targets.targets[jack_helpers.helpers[cf['_encoder']]['target']]['file_extension']
    "undo renaming (operation mode)"
    maxnames = max(map(lambda x: len(x['names']), status.values()))
    if len(jack_progress.status_all['names']) >= maxnames:
        dir_too = 1
    else:
        dir_too = 0
    maxnames = max(maxnames, len(jack_progress.status_all['names']))
    if maxnames > 1:

        # undo dir renaming
        cwd = os.getcwd()
        if jack_freedb.dir_created and jack_utils.check_path(jack_freedb.dir_created, cwd) and dir_too:
            new_name, old_name = jack_progress.status_all['names'][-2:]
            jack_utils.rename_path(old_name, new_name)    # this changes cwd!
            info("cwd now " + os.getcwd())
            jack_functions.progress("all", "undo", "dir")

        else:
            maxnames = max(map(lambda x: len(x['names']), status.values()))

        # undo file renaming
        for i in todo:
            if maxnames < 2:
                break
            act_names = status[i[NUM]]['names']
            if len(act_names) == maxnames:
                for j in (ext, '.wav'):
                    new_name, old_name = act_names[-2:]
                    new_name, old_name = new_name + j, old_name + j
                    if not os.path.exists(old_name):
                        if j == ext:
                            print 'NOT renaming "' + old_name + '": it doesn\'t exist.'
                    else:
                        if os.path.exists(new_name):
                            print 'NOT renaming "' + old_name + '" to "' + new_name + '" because dest. exists.'
                        else:
                            jack_functions.progress(i[NUM], "undo", "-")
                            os.rename(old_name, new_name)
    else:
        info("nothing to do.")
Exemple #2
0
def filter_tracks(toc_just_read, status):
    "filter out data tracks"
    global datatracks

    if toc_just_read and jack_helpers.helpers[cf['_ripper']].has_key("toc_cmd") and cf['_ripper'] != cf['_toc_prog']:
        ripper_tracks = jack_functions.gettoc(cf['_ripper'])
        if ripper_tracks != jack_ripstuff.all_tracks:
            for i in range(len(jack_ripstuff.all_tracks)):
                rtn = jack_utils.has_track(ripper_tracks, jack_ripstuff.all_tracks[i][NUM])
                if rtn >= 0:
                    for j in range(6):
                        # "NUM LEN START COPY PRE CH" (not: "RIP RATE NAME")
                        if ripper_tracks[rtn][j] != jack_ripstuff.all_tracks[i][j]:
                            jack_functions.progress(i + 1, "patch", "%s %d -> %d" % (fields[j], jack_ripstuff.all_tracks[i][j], ripper_tracks[rtn][j]))
                            jack_ripstuff.all_tracks[i][j] = ripper_tracks[rtn][j]
                            debug("Track %02d %s" % (i + 1, fields[j]) + `jack_ripstuff.all_tracks[i][j]` + " != " + `ripper_tracks[rtn][j]` + " (trusting %s; to the right)" % cf['_ripper'])
                else:
                    jack_functions.progress(i + 1, "off", "non-audio")
                    datatracks.append(i + 1)
                    info("Track %02d not found by %s. Treated as non-audio." % (i + 1, cf['_ripper']))
    if not toc_just_read:
        datatracks += [x for x in status.keys() if status[x]["off"] and status[x]["off"] == ["non-audio"]]
Exemple #3
0
def update_progress(status, todo):
    ext = jack_targets.targets[jack_helpers.helpers[cf['_encoder']]['target']]['file_extension']
    "update progress file at user's request (operation mode)"

    if cf['_upd_progress']:
        # users may still have a valid jack.freedb file lying around
        if not jack_freedb.names_available:
            err, jack_tag.track_names, jack_tag.locale_names, freedb_rename, revision = jack_freedb.interpret_db_file(jack_ripstuff.all_tracks, todo, cf['_freedb_form_file'], verb = 0, dirs = 1)

        for i in todo:
            num = i[NUM]
            if not status[num]['dae']:
                filename = jack_functions.check_file(num, i, ".wav")
                if filename:
                    status[num]['dae'] = "  *   [          simulated           ]"
                    jack_functions.progress(num, "dae", status[num]['dae'])
            if not status[num]['enc']:
                filename = jack_functions.check_file(num, i, ext)
                if filename:
                    if ext.upper() == ".MP3":
                        x = jack_mp3.mp3format(filename + ext)
                        temp_rate = x['bitrate']
                    elif ext.upper() == ".OGG" and ogg:
                        x = ogg.vorbis.VorbisFile(filename + ext)
                        temp_rate = int(x.raw_total(0) * 8 / x.time_total(0) / 1000 + 0.5)
                    elif ext.upper() == ".FLAC" and flac:
                        f = flac.FLAC(filename + ext)
                        size = os.path.getsize(filename + ext)
                        if f.info and size:
                            temp_rate = int(size * 8 * f.info.sample_rate / f.info.total_samples / 1000)
                        else:
                            temp_rate = 0
                    else:
                        error("don't know how to handle %s files." % ext)
                    status[num]['enc'] = `temp_rate` + cf['_progr_sep'] + "[simulated]"
                    jack_functions.progress(num, "enc", status[num]['enc'])
Exemple #4
0
def find_workdir():
    "search for a dir containing a toc-file or do the multi-mode"
    tries = 0
    toc_just_read = 0
    debug("multi_mode:" + `cf['_multi_mode']`)
    while (not os.path.exists(cf['_toc_file'])) or cf['_multi_mode']:
        tries = tries + 1
        if tries > 2:
            break
        if cf['_guess_mp3s']:
            jack_ripstuff.all_tracks = jack_functions.guesstoc(cf['_guess_mp3s'])
        else:
            if cf['_multi_mode']:
                debug("multimode all_tracks reset")
                jack_ripstuff.all_tracks = []
            else:
                if cf['_image_toc_file']:
                    # put the absolute path in the variable since we'll change cwd soon
                    cf['_image_toc_file'] = os.path.abspath(cf['_image_toc_file'])
                    jack_ripstuff.all_tracks, dummy, dummy = jack_functions.cdrdao_gettoc(cf['_image_toc_file'])
                else:
                    if cf['_image_file']:
                        warning("No TOC file for image '%s' specified, reading TOC from CD device." % cf['_image_file'])
                        cf['_image_file'] = os.path.abspath(cf['_image_file'])
                    jack_ripstuff.all_tracks = jack_functions.gettoc(cf['_toc_prog'])
                    toc_just_read = 1

            if cf['_scan_dirs']:
                dirs = [os.getcwd()]
                # Also scan base_dir since it's not guaranteed that users
                # run jack in base_dir
                if cf['_base_dir']:
                    cf['_base_dir'] = expand(cf['_base_dir'])
                    if os.path.exists(cf['_base_dir']) and cf['_base_dir'] not in dirs:
                        dirs.append(cf['_base_dir'])
            else:
                dirs = cf['_searchdirs']

            while cf['_scan_dirs'] > 0:
                cf['_scan_dirs'] = cf['_scan_dirs'] - 1
                new_dirs = []
                for i in dirs:
                    if not i in new_dirs:
                        new_dirs.append(i)
                    try:
                        subdir = os.listdir(i)
                    except OSError, msg:
                        print "skipped %s, %s" % (i, msg)
                        continue
                    for j in subdir:
                        dir = os.path.join(i,j)
                        if os.path.isdir(dir) and not dir in new_dirs:
                            new_dirs.append(dir)
                dirs = new_dirs
            possible_dirs = []  # dirs matching inserted CD
            jack_dirs = []      # dirs containing toc_file
            for i in dirs:
                if os.path.exists(os.path.join(i, cf['_toc_file'])):
                    jack_dirs.append(i)
                    file_toc, dummy, dummy = jack_functions.cdrdao_gettoc(os.path.join(i, cf['_toc_file']))
                    if jack_freedb.freedb_id(jack_ripstuff.all_tracks) == jack_freedb.freedb_id(file_toc):
                        possible_dirs.append(i)

            if cf['_multi_mode']:
                unique_dirs = []
                for i in range(len(jack_dirs)):
                    found = 0
                    for j in range(i + 1,len(jack_dirs)):
                        if os.path.samefile(jack_dirs[i], jack_dirs[j]):
                            found = 1
                    if not found:
                        unique_dirs.append(jack_dirs[i])
                for i in unique_dirs:
                    jack_ripstuff.all_tracks, dummy, track1_offset = jack_functions.cdrdao_gettoc(os.path.join(i, cf['_toc_file']))
                    err, jack_tag.track_names, jack_tag.locale_names, cd_id, revision = freedb_names(jack_freedb.freedb_id(jack_ripstuff.all_tracks), jack_ripstuff.all_tracks, jack_ripstuff.all_tracks, os.path.join(i, cf['_freedb_form_file']), verb = 0, warn = 0)
                    if err or cf['_force']:# this means freedb data is not there yet
                        info("matching dir found: %d" % i)
                        pid = os.fork()
                        if pid == CHILD:
                            os.chdir(i)
                            ch_args = sys.argv
                            for killarg in ('--force', '--multi-mode'):
                                if killarg in ch_args:
                                    ch_args.remove(killarg)
                            info("running" + `ch_args`)
                            os.execvp(ch_args[0], ch_args)
                        else:
                            respid, res = os.waitpid(pid, 0)
                sys.exit()

            unique_dirs = []
            for i in range(len(possible_dirs)):
                found = 0
                for j in range(i + 1,len(possible_dirs)):
                    if os.path.samefile(possible_dirs[i], possible_dirs[j]):
                        found = 1
                if not found:
                    unique_dirs.append(possible_dirs[i])
                    info("matching dir found: " + possible_dirs[i])
            if len(unique_dirs) > 1:
                error("found more than one workdir, change to the correct one.")
            elif len(unique_dirs) == 1:
                os.chdir(unique_dirs[0])
            else:
                if cf['_create_dirs']:
                    cf['_base_dir'] = expand(cf['_base_dir'])
                    if not os.path.exists(cf['_base_dir']):
                        os.makedirs(cf['_base_dir'])
                    os.chdir(cf['_base_dir'])
                    dir_name = jack_version.prog_name + "-" + jack_freedb.freedb_id(jack_ripstuff.all_tracks, warn=0)
                    if not os.path.exists(dir_name) and not os.path.isdir(dir_name):
                        os.mkdir(dir_name)
                    os.chdir(dir_name)
                    jack_freedb.dir_created = dir_name
                    jack_functions.progress("all", "mkdir", jack_freedb.dir_created)

        if not cf['_multi_mode']:
            if not os.path.exists(cf['_toc_file']):
                jack_functions.cdrdao_puttoc(cf['_toc_file'], jack_ripstuff.all_tracks, jack_freedb.freedb_id(jack_ripstuff.all_tracks))
                jack_freedb.freedb_template(jack_ripstuff.all_tracks) # generate freedb form if tocfile is created
            if not os.path.exists(cf['_freedb_form_file']):
                jack_freedb.freedb_template(jack_ripstuff.all_tracks)
        else:
            break
Exemple #5
0
def interpret_db_file(all_tracks, todo, freedb_form_file, verb, dirs = 0, warn = None):
    "read freedb file and rename dir(s)"
    global names_available, dir_created
    freedb_rename = 0
    if warn == None:
        err, track_names, locale_names, cd_id, revision = freedb_names(freedb_id(all_tracks), all_tracks, todo, freedb_form_file, verb = verb)
    else:
        err, track_names, locale_names, cd_id, revision = freedb_names(freedb_id(all_tracks), all_tracks, todo, freedb_form_file, verb = verb, warn = warn)
    if (not err) and dirs:
        freedb_rename = 1

# The user wants us to use the current dir, unconditionally.

        if cf['_claim_dir']:
            dir_created = jack_utils.split_dirname(os.getcwd())[-1]
            jack_functions.progress("all", "mkdir", dir_created)
            cf['_claim_dir'] = 0

        if cf['_rename_dir'] and dir_created:
            new_dirs, new_dir = jack_utils.mkdirname(track_names, cf['_dir_template'])
            old_dir = os.getcwd()
            old_dirs = jack_utils.split_dirname(old_dir)
            dirs_created = jack_utils.split_dirname(dir_created)

# only do the following if we are where we think we are and the dir has to be
# renamed.

            if jack_utils.check_path(dirs_created, old_dirs) and not jack_utils.check_path(dirs_created, new_dirs):
                jack_utils.rename_path(dirs_created, new_dirs)
                print "Info: cwd now", os.getcwd()
                jack_functions.progress("all", 'ren', unicode(dir_created + "-->" + new_dir, cf['_charset'], "replace"))

    if not err:
        cd = track_names[0]
        year = genretxt = None
        if len(cd) > 2:
            year = `cd[2]`
        if len(cd) > 3:
            genretxt = id3genres[cd[3]]
        filenames.append('') # FIXME: possibly put the dir here, but in no
        # case remove this since people access filenames with i[NUM] which starts at 1
        num = 1
        for i in track_names[1:]:
            replacelist = {"n": cf['_rename_num'] % num, "l": cd[1], "t": i[1],
                           "y": year, "g": genretxt}
            if cf['_various']:
                replacelist["a"] = i[0]
                newname = jack_misc.multi_replace(cf['_rename_fmt_va'], replacelist, "rename_fmt_va", warn = (num == 1))
            else:
                replacelist["a"] = cd[0]
                newname = jack_misc.multi_replace(cf['_rename_fmt'], replacelist, "rename_fmt", warn = (num == 1))
            exec("newname = newname" + cf['_char_filter'])
            for char_i in range(len(cf['_unusable_chars'])):
                try:
                    a = unicode(cf['_unusable_chars'][char_i], locale.getpreferredencoding(), "replace")
                    b = unicode(cf['_replacement_chars'][char_i], locale.getpreferredencoding(), "replace")
                except UnicodeDecodeError:
                    warning("Cannot substitute unusable character %d."
% (char_i+1))
                else:
                    newname = string.replace(newname, a, b)
            filenames.append(newname)
            num += 1
        names_available = 1
    else:
        freedb_rename = 0
    return err, track_names, locale_names, freedb_rename, revision
Exemple #6
0
def freedb_query(cd_id, tracks, file):
    if cf['_freedb_dir']:
        if local_freedb(cd_id, cf['_freedb_dir'], file)==0: # use local database (if any)
            return 0

    qs = "cmd=cddb query " + cd_id + " " + `len(tracks)` + " " # query string
    for i in tracks:
        qs = qs + `i[START] + MSF_OFFSET` + " "
    qs = qs + `(MSF_OFFSET + tracks[-1][START] + tracks[-1][LEN]) / CDDA_BLOCKS_PER_SECOND`
    hello = "hello=" + cf['_username'] + " " + cf['_hostname'] + " " + freedb_servers[cf['_freedb_server']]['id']
    qs = urllib.quote_plus(qs + "&" + hello + "&proto=6", "=&")
    url = "http://" + freedb_servers[cf['_freedb_server']]['host'] + "/~cddb/cddb.cgi?" + qs
    if cf['_cont_failed_query']:
        try:
            f = urllib2.urlopen(url)
        except IOError:
            traceback.print_exc()
            err = 1
            return err
    else:
        f = urllib2.urlopen(url)
    buf = f.readline()
    if buf and buf[0:1] == "2":
        if buf[0:3] in ("210", "211"): # Found inexact or multiple exact matches, list follows
            if buf[0:3] == "211":
                global freedb_inexact_match
                freedb_inexact_match = 1
            print "Found the following matches. Choose one:"
            num = 1
            matches = []
            while 1:
                buf = f.readline()
                try:
                    buf = unicode(buf, "utf-8")
                except UnicodeDecodeError:
                    buf = unicode(buf, "latin-1")
                if not buf:
                    break
                buf = string.rstrip(buf)
                if buf != ".":
                    print "%2i" % num + ".) " + buf.encode(locale.getpreferredencoding(), "replace")
                    matches.append(buf)
                    num = num + 1
            x = -1
            while x < 0 or x > num - 1:
                input = raw_input(" 0.) none of the above: ")
                if not input:
                    continue
                try:
                    x = int(input)
                except ValueError:
                    x = -1    # start the loop again
                if not x:
                    print "ok, aborting."
                    sys.exit()
 
            buf = matches[x-1]
            buf = string.split(buf, " ", 2)
            freedb_cat = buf[0]
            cd_id = buf[1]
            err = 0
 
        elif buf[0:3] == "200":
            buf = string.split(buf)
            freedb_cat = buf[1]
        elif buf[0:3] == "202":
            if cf['_cont_failed_query']:
                warning(buf + f.read() + " How about trying another --server?")
                err = 1
                return err
            else:
                error(buf + f.read() + " How about trying another --server?")
        else:
            if cf['_cont_failed_query']:
                warning(buf + f.read() + " --don't know what to do, aborting query.")
                err = 1
                return err
            else:
                error(buf + f.read() + " --don't know what to do, aborting query.")
 
        cmd = "cmd=cddb read " + freedb_cat + " " + cd_id
        url = "http://" + freedb_servers[cf['_freedb_server']]['host'] + "/~cddb/cddb.cgi?" + urllib.quote_plus(cmd + "&" + hello + "&proto=6", "=&")
        f = urllib2.urlopen(url)
        buf = f.readline()
        if buf and buf[0:3] == "210": # entry follows
            if os.path.exists(file):
                os.rename(file, file + ".bak")
            of = open(file, "w")
            buf = f.readline()
            while buf:
                buf = string.rstrip(buf)
                if buf != ".":
                    of.write(buf + "\n")
                buf = f.readline()
            of.close()
            jack_functions.progress("all", "freedb_cat", freedb_cat)
            jack_progress.status_all['freedb_cat'] = freedb_cat
            err = 0
        else:
            print string.rstrip(buf)
            print f.read()
            warning("could not query freedb entry")
            err = 1
        f.close()
    else:
        print string.rstrip(buf)
        print f.read()
        warning("could not check freedb category")
        err = 2
    f.close()
    return err
Exemple #7
0
def main_loop(mp3s_todo, wavs_todo, space, dae_queue, enc_queue,
              track1_offset):
    global_error = 0  # remember if something went wrong
    actual_load = -2  # this is always smaller than max_load
    waiting_load = 0  # are we waiting for the load to drop?
    waiting_space = 0  # are we waiting for disk space to be freed?
    space_waiting = 0  # how much space _running_ subprocesses will consume
    space_adjust = 0  # by how much space has been modified
    blocked = 0  # we _try_ do detect deadlocks
    cycles = 0  # it's sort of a timer
    last_update = 0  # screen updates are done once per second
    pause = 0  # no new encoders are started if pause==1
    flags = "[   ]"  # runtime controllable flags
    enc_running = 0  # what is going on?
    dae_running = 0  # what is going on?

    rotate = "/-\\|"
    rotate_ball = " .o0O0o."
    rot_cycle = len(rotate)
    rot_ball_cycle = len(rotate_ball)
    rot_count = 0
    global_done = 0
    first_encoder = 1
    ext = jack_targets.targets[jack_helpers.helpers[cf['_encoder']]
                               ['target']]['file_extension']
    global_blocks = jack_functions.tracksize(
        wavs_todo)[BLOCKS] + jack_functions.tracksize(mp3s_todo)[BLOCKS]

    #####################
    ### MAIN LOOP ###
    #####################

    global_start = time.time()
    while mp3s_todo or enc_queue or dae_queue or enc_running or dae_running:
        orig_space = space
        # feed in the WAVs which have been there from the start
        if mp3s_todo and jack_functions.tracksize(mp3s_todo[0])[ENC] < space:
            waiting_space = 0
            enc_queue.append(mp3s_todo[0])
            space = space - jack_functions.tracksize(mp3s_todo[0])[ENC]
            jack_status.enc_stat_upd(mp3s_todo[0][NUM], "waiting for encoder.")
            mp3s_todo = mp3s_todo[1:]

            # start new DAE subprocess

        elif (len(enc_queue) + enc_running) < (
                cf['_read_ahead'] + cf['_encoders']
        ) and dae_queue and dae_running < cf['_rippers'] and (
            (jack_functions.tracksize(dae_queue[0])[BOTH] < space) or
            (cf['_only_dae']
             and jack_functions.tracksize(dae_queue[0])[WAV] < space) or
            (cf['_otf']
             and jack_functions.tracksize(dae_queue[0])[ENC] < space)):
            waiting_space = 0
            this_is_ok = 1
            if pause:
                this_is_ok = 0
                jack_status.dae_stat_upd(dae_queue[0][NUM],
                                         "Paused. Press 'c' to continue.")
            elif cf['_rip_from_device']:
                all_tracks_on_cd = jack_functions.gettoc(cf['_toc_prog'])
                if not jack_utils.cmp_toc_cd(jack_ripstuff.all_tracks_orig,
                                             all_tracks_on_cd,
                                             what=(NUM, LEN)):
                    while dae_queue:
                        track = dae_queue[0]
                        dae_queue = dae_queue[1:]
                        jack_status.dae_stat_upd(
                            track[NUM], "Wrong disc - aborting this track")
                    global_error = global_error + 1
                    this_is_ok = 0
            if this_is_ok:
                if cf['_only_dae']:
                    space_waiting = space_waiting + jack_functions.tracksize(
                        dae_queue[0])[WAV]
                    space = space - jack_functions.tracksize(dae_queue[0])[WAV]
                elif cf['_otf']:
                    space_waiting = space_waiting + jack_functions.tracksize(
                        dae_queue[0])[ENC]
                    space = space - jack_functions.tracksize(dae_queue[0])[ENC]
                else:
                    space_waiting = space_waiting + jack_functions.tracksize(
                        dae_queue[0])[BOTH]
                    space = space - jack_functions.tracksize(
                        dae_queue[0])[BOTH]
                dae_running = dae_running + 1
                track = dae_queue[0]
                dae_queue = dae_queue[1:]
                if cf['_otf']:
                    # note: image_reader can't do otf at the moment.
                    jack_status.dae_stat_upd(
                        track[NUM], ":DAE: waiting for status report...")
                    if cf['_encoder'] in ("lame", "gogo", "flac", "mppenc"):
                        jack_status.enc_stat_upd(
                            track[NUM],
                            "[no otf status for %s]" % cf['_encoder'])
                    else:
                        jack_status.enc_stat_upd(track[NUM],
                                                 "waiting for encoder.")
                    enc_running = enc_running + 1
                    if first_encoder:
                        first_encoder = 0
                        global_start = time.time()
                    data = jack_workers.start_new_otf(track, cf['_ripper'],
                                                      cf['_encoder'])
                    jack_children.children.append(data['rip'])
                    jack_children.children.append(data['enc'])
                else:
                    if jack_status.enc_status[track[NUM]]:
                        jack_status.enc_cache[
                            track[NUM]] = jack_status.enc_status[track[NUM]]
                        jack_status.enc_stat_upd(track[NUM], "[...]")
                    jack_status.dae_stat_upd(
                        track[NUM], ":DAE: waiting for status report...")
                    if cf['_rip_from_device']:
                        jack_children.children.append(
                            jack_workers.start_new_ripper(
                                track, cf['_ripper']))
                    elif cf['_image_file']:
                        jack_children.children.append(
                            jack_workers.ripread(track, track1_offset))
                    else:
                        jack_status.dae_stat_upd(
                            track[NUM], ":?AE: don't know how to rip this!")

                        # start new encoder subprocess

        if enc_queue and enc_running < cf['_encoders']:
            if jack_functions.tracksize(
                    enc_queue[0])[ENC] <= space + space_waiting:
                waiting_space = 0
                actual_load = jack_misc.loadavg()
                if actual_load < cf['_max_load']:
                    waiting_load = 0
                    enc_running = enc_running + 1
                    track = enc_queue[0]
                    enc_queue = enc_queue[1:]
                    jack_status.enc_stat_upd(track[NUM],
                                             "waiting for encoder...")
                    jack_children.children.append(
                        jack_workers.start_new_encoder(track, cf['_encoder']))
                    if first_encoder:
                        first_encoder = 0
                        global_start = time.time()
                else:
                    waiting_load = 1

                    # check for subprocess output

        readfd = [sys.stdin.fileno()]
        for i in jack_children.children:
            readfd.append(i['fd'])
        try:
            rfd, wfd, xfd = select.select(readfd, [], [],
                                          cf['_update_interval'])
        except:
            rfd, wfd, xfd = [], [], []
            jack_term.tmod.sig_winch_handler(None, None)

            # check for keyboard commands

        if sys.stdin.fileno() in rfd:
            last_update = last_update - cf['_update_interval']
            cmd = jack_term.tmod.getkey()
            sys.stdin.flush()
            if string.upper(cmd) == "Q":
                jack_display.exit()
            elif not pause and string.upper(cmd) == "P":
                pause = 1
                flags = flags[:1] + "P" + flags[2:]
            elif string.upper(
                    cmd) == "C" or pause and string.upper(cmd) == "P":
                pause = 0
                flags = flags[:1] + " " + flags[2:]
            elif not flags[3] == "e" and string.upper(cmd) == "E":
                for i in jack_children.children:
                    if i['type'] == "encoder":
                        os.kill(i['pid'], signal.SIGSTOP)
                        flags = flags[:3] + "e" + flags[4:]
            elif flags[3] == "e" and string.upper(cmd) == "E":
                for i in jack_children.children:
                    if i['type'] == "encoder":
                        os.kill(i['pid'], signal.SIGCONT)
                        flags = flags[:3] + " " + flags[4:]
            elif not flags[2] == "r" and string.upper(cmd) == "R":
                for i in jack_children.children:
                    if i['type'] == "ripper":
                        os.kill(i['pid'], signal.SIGSTOP)
                        flags = flags[:2] + "r" + flags[3:]
            elif flags[2] == "r" and string.upper(cmd) == "R":
                for i in jack_children.children:
                    if i['type'] == "ripper":
                        os.kill(i['pid'], signal.SIGCONT)
                        flags = flags[:2] + " " + flags[3:]
            elif string.upper(cmd) == "U":
                cycles = 29  # do periodic stuff _now_
            else:
                jack_term.tmod.move_pad(cmd)
                if cmd == 'KEY_RESIZE':
                    continue
                last_update = time.time()

        # read from file with activity
        for i in jack_children.children:
            if i['fd'] in rfd:
                if os.uname()[0] == "Linux" and i['type'] != "image_reader":
                    try:
                        x = i['file'].read()
                    except (IOError, ValueError):
                        pass
                else:
                    read_chars = 0
                    x = ""
                    while read_chars < jack_helpers.helpers[
                            i['prog']]['status_blocksize']:
                        try:
                            xchar = i['file'].read(1)
                        except (IOError, ValueError):
                            break
                        x = x + xchar
                        read_chars = read_chars + 1
                        try:
                            rfd2, wfd2, xfd2 = select.select([i['fd']], [], [],
                                                             0.0)
                        except:
                            rfd2, wfd2, xfd2 = [], [], []
                            jack_term.tmod.sig_winch_handler(None, None)
                        if i['fd'] not in rfd2:
                            break
                # put read data into child's buffer
                i['buf'] = i['buf'] + x

                if jack_helpers.helpers[i['prog']].has_key('filters'):
                    for fil in jack_helpers.helpers[i['prog']]['filters']:
                        i['buf'] = fil[0].sub(fil[1], i['buf'])

                i['buf'] = i['buf'][-jack_helpers.
                                    helpers[i['prog']]['status_blocksize']:]

        # check for exiting child processes
        if jack_children.children:
            respid, res = os.waitpid(-1, os.WNOHANG)
            if respid != 0:
                last_update = last_update - cf[
                    '_update_interval']  # ensure info is printed
                new_ch = []
                exited_proc = []
                for i in jack_children.children:
                    if i['pid'] == respid:
                        if exited_proc != []:
                            error("pid " + ` respid ` +
                                  " found at multiple child processes")
                        exited_proc = i
                    else:
                        new_ch.append(i)
                if not exited_proc:
                    error("unknown process (" + ` respid ` + ") has exited")
                jack_children.children = new_ch
                x = ""
                try:
                    x = exited_proc['file'].read()
                except (IOError, ValueError):
                    pass
                exited_proc['buf'] = (
                    exited_proc['buf'] +
                    x)[-jack_helpers.
                       helpers[exited_proc['prog']]['status_blocksize']:]
                exited_proc['file'].close()

                global_error = global_error + res
                track = exited_proc['track']
                num = track[NUM]
                stop_time = time.time()
                speed = (track[LEN] / float(CDDA_BLOCKS_PER_SECOND)) / (
                    stop_time - exited_proc['start_time'])

                if exited_proc['type'] in ("ripper", "image_reader"):
                    dae_running = dae_running - 1
                    if cf['_exec_when_done'] and exited_proc[
                            'type'] == "ripper" and dae_running == 0 and len(
                                dae_queue) == 0:
                        os.system(cf['_exec_rip_done'])
                    if not res:
                        if not exited_proc['otf']:
                            if os.path.exists(track[NAME] + ".wav"):
                                if jack_functions.tracksize(
                                        track)[WAV] != jack_utils.filesize(
                                            track[NAME] + ".wav"):
                                    res = 242
                                    jack_status.dae_stat_upd(
                                        num,
                                        jack_status.get_2_line(
                                            exited_proc['buf']))
                            else:
                                jack_status.dae_stat_upd(
                                    num,
                                    jack_status.get_2_line(exited_proc['buf']))
                                res = 243
                            global_error = global_error + res
                    if res and not cf['_sloppy']:
                        if os.path.exists(track[NAME] + ".wav"):
                            os.remove(track[NAME] + ".wav")
                            space = space + jack_functions.tracksize(
                                track)[WAV]
                            if cf['_otf']:
                                os.kill(exited_proc['otf-pid'], signal.SIGTERM)
                                if os.path.exists(track[NAME] + ext):
                                    os.remove(track[NAME] + ext)
                                space = space + jack_functions.tracksize(
                                    track)[ENC]
                            if not cf['_otf'] and not cf[
                                    '_only_dae'] and track not in jack_encstuff.mp3s_ready:
                                space = space + jack_functions.tracksize(
                                    track)[ENC]
                            jack_status.dae_stat_upd(
                                num, 'DAE failed with status ' + ` res ` +
                                ", wav removed.")
                    else:
                        if exited_proc['type'] == "image_reader":
                            jack_status.dae_stat_upd(
                                num,
                                jack_status.get_2_line(exited_proc['buf']))
                        else:
                            if exited_proc['otf'] and jack_helpers.helpers[
                                    exited_proc['prog']].has_key(
                                        'otf-final_status_fkt'):
                                exec(jack_helpers.helpers[exited_proc['prog']]
                                     ['otf-final_status_fkt']) in globals(
                                     ), locals()
                            else:
                                last_status = None  # (only used in cdparanoia)
                                exec(jack_helpers.helpers[exited_proc['prog']]
                                     ['final_status_fkt']) in globals(
                                     ), locals()
                            jack_status.dae_stat_upd(num, final_status)
                        if jack_status.enc_cache[num]:
                            jack_status.enc_stat_upd(
                                num, jack_status.enc_cache[num])
                            jack_status.enc_cache[num] = ""
                        jack_functions.progress(num, "dae",
                                                jack_status.dae_status[num])
                        if not cf['_otf'] and not cf[
                                '_only_dae'] and track not in jack_encstuff.mp3s_ready:
                            if waiting_space:
                                mp3s_todo.append(track)
                                space = space + jack_functions.tracksize(
                                    track)[ENC]
                            else:
                                jack_status.enc_stat_upd(
                                    num, 'waiting for encoder.')
                                enc_queue.append(track)
                    space_waiting = space_waiting - jack_functions.tracksize(
                        track)[WAV]

                elif exited_proc['type'] == "encoder":
                    enc_running = enc_running - 1
                    # completed vbr files shouldn't be to small, but this still
                    # caused confusion so again, vbr is an exception:
                    if not cf['_vbr'] and not res and jack_functions.tracksize(
                            track)[ENC] * 0.99 > jack_utils.filesize(
                                track[NAME] + ext):
                        res = 242
                        global_error = global_error + res
                    if res:
                        global_blocks = global_blocks - exited_proc['track'][
                            LEN]
                        global_start = global_start + exited_proc[
                            'elapsed'] / (enc_running + 1)
                        if global_start > time.time():
                            global_start = time.time()
                        if os.path.exists(track[NAME] + ext):
                            # mp3enc doesn't report errors when out of disk space...
                            os.remove(track[NAME] + ext)
                        space = space + jack_functions.tracksize(track)[ENC]
                        jack_status.enc_stat_upd(
                            num, 'coding failed, err#' + ` res `)
                    else:
                        global_done = global_done + exited_proc['track'][LEN]
                        if cf['_vbr']:
                            rate = int(
                                (jack_utils.filesize(track[NAME] + ext) *
                                 0.008) / (track[LEN] / 75.0))
                        else:
                            rate = track[RATE]
                        jack_status.enc_stat_upd(
                            num, "[coding @" +
                            '%s' % jack_functions.pprint_speed(speed) +
                            "x done, %dkbit" % rate)
                        jack_functions.progress(num, "enc", ` rate `,
                                                jack_status.enc_status[num])
                        if not cf['_otf'] and not cf['_keep_wavs']:
                            os.remove(track[NAME] + ".wav")
                            space = space + jack_functions.tracksize(
                                track)[WAV]

                else:
                    error("child process of unknown type (" +
                          exited_proc['type'] + ") exited")
                if global_error:
                    jack_display.smile = " :-["

        space_adjust += orig_space - space

        if last_update + cf['_update_interval'] <= time.time():
            last_update = time.time()

            # interpret subprocess output

            for i in jack_children.children:
                if i['type'] == "ripper":
                    if len(i['buf']) == jack_helpers.helpers[
                            i['prog']]['status_blocksize']:
                        if i['otf'] and jack_helpers.helpers[
                                i['prog']].has_key('otf-status_fkt'):
                            exec(jack_helpers.helpers[i['prog']]
                                 ['otf-status_fkt']) in globals(), locals()
                        else:
                            exec(jack_helpers.helpers[i['prog']]
                                 ['status_fkt']) in globals(), locals()
                        if new_status:
                            try:
                                jack_status.dae_stat_upd(
                                    i['track'][NUM], ":DAE: " + new_status)
                            except:
                                debug("error in dae_stat_upd")

                elif i['type'] == "encoder":
                    if len(i['buf']) == jack_helpers.helpers[
                            i['prog']]['status_blocksize']:
                        tmp_d = {'i': i.copy(), 'percent': 0}
                        try:
                            exec(jack_helpers.helpers[i['prog']]
                                 ['percent_fkt']) in globals(), tmp_d
                        except:
                            tmp_d['percent'] = 0
                            debug("error in percent_fkt of %s." % ` i `)
                        i['percent'] = tmp_d['percent']
                        if i['percent'] > 0:
                            i['elapsed'] = time.time() - i['start_time']
                            speed = ((i['track'][LEN] /
                                      float(CDDA_BLOCKS_PER_SECOND)) *
                                     (i['percent'] / 100)) / i['elapsed']
                            eta = (100 -
                                   i['percent']) * i['elapsed'] / i['percent']
                            eta_ms = "%02i:%02i" % (eta / 60, eta % 60)
                            jack_status.enc_stat_upd(
                                i['track'][NUM], '%2i%% done, ETA:%6s, %sx' %
                                (i['percent'], eta_ms,
                                 jack_functions.pprint_speed(speed)))
                            #jack_term.tmod.dae_stat_upd(i['track'][NUM], None, i['percent'])

                elif i['type'] == "image_reader":
                    line = string.strip(
                        jack_status.get_2_line(i['buf'], default=""))
                    if line:
                        jack_status.dae_stat_upd(i['track'][NUM], line)
                        if line.startswith("Error"):
                            global_error = global_error + 1

                else:
                    error("unknown subprocess type \"" + i['type'] + "\".")

            cycles = cycles + 1
            if cycles % 30 == 0:
                if cf['_recheck_space'] and not cf['space_from_argv'][
                        'history'][-1][0] == "argv":
                    actual_space = jack_functions.df()
                    if space_adjust:
                        diff = actual_space - space
                        if diff > space_adjust:
                            space = space + space_adjust
                            space_adjust = 0
                            waiting_space = 0
                        else:
                            space = space + diff
                            space_adjust = space_adjust - diff
                    else:
                        if actual_space < space:
                            space_adjust = space - actual_space
                            space = actual_space

            if space_adjust and enc_running == 0 and dae_running == 0:
                waiting_space = waiting_space + 1
            if not waiting_space >= 2 and not waiting_load and enc_running == 0 and dae_running == 0:
                blocked = blocked + 1
            else:
                blocked = 0

            total_done = global_done
            for i in jack_children.children:
                total_done = total_done + (i['percent'] /
                                           100) * i['track'][LEN]
            elapsed = time.time() - global_start
            if global_blocks > 0:
                percent = total_done / global_blocks
            else:
                percent = 0
            if percent > 0 and elapsed > 40:
                eta = ((1 - percent) * elapsed / percent)
                eta_hms = " ETA=%i:%02i:%02i" % (eta / 3600,
                                                 (eta % 3600) / 60, eta % 60)
            else:
                eta_hms = ""

            if string.strip(flags[1:-1]):
                print_flags = " " + flags
            else:
                print_flags = ""
            if dae_running:
                rot = rotate_ball[rot_count % rot_ball_cycle]
            else:
                rot = rotate[rot_count % rot_cycle]
            rot_count = rot_count + 1

            # print status

            if blocked > 2:
                jack_display.special_line = " ...I feel blocked - quit with 'q' if you get bored... "
                if blocked > 5:
                    space = jack_functions.df() - cf['_keep_free']
            elif waiting_load and waiting_space >= 2:
                jack_display.special_line = " ...waiting for load (%.2f)" % actual_load + ") < %.2f" % cf[
                    '_max_load'] + " and for " + jack_functions.pprint_i(
                        space_adjust, "%i %sBytes") + " to be freed... "
            elif waiting_space >= 2:
                jack_display.special_line = " ...waiting for " + jack_functions.pprint_i(
                    space_adjust, "%i %sBytes") + " to be freed.... "
            elif waiting_load:
                jack_display.special_line = " ...waiting for load (%.2f) to drop below %.2f..." % (
                    actual_load, cf['_max_load'])
            else:
                jack_display.special_line = None

            jack_display.bottom_line =  "(" + rot + ") " \
                + "SPACE:" * (space_adjust != 0) \
                + "space:" * (space_adjust == 0) \
                + jack_functions.pprint_i(space, "%i%sB") \
                + (" waiting_WAVs:%02i" % len(enc_queue)) \
                + " DAE:" + `cf['_rippers'] - dae_running` + "+" + `dae_running` \
                + " ENC:" + `cf['_encoders'] - enc_running` + "+" + `enc_running` \
                + eta_hms \
                + " errors: " + `global_error` \
                + jack_display.smile + print_flags

            jack_term.tmod.update(jack_display.special_line,
                                  jack_display.bottom_line)

    return global_error
Exemple #8
0
def tag(freedb_rename):
    global a_artist, a_title

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

    if cf['_vbr'] and not cf['_only_dae']:
        total_length = 0
        total_size = 0
        for i in jack_ripstuff.all_tracks_todo_sorted:
            total_length = total_length + i[LEN]
            total_size = total_size + jack_utils.filesize(i[NAME] + ext)

    if cf['_set_id3tag'] and not jack_targets.targets[jack_helpers.helpers[cf['_encoder']]['target']]['can_posttag']:
        cf['_set_id3tag'] = 0

    # maybe export?
    if jack_freedb.names_available:
        a_artist = track_names[0][0] # unicode
        a_title = track_names[0][1] # unicode
        p_artist = locale_names[0][0] # string
        p_title = locale_names[0][1] # string

    if cf['_set_id3tag'] or freedb_rename:
        jack_m3u.init()
        # use freedb year and genre data if available
        if cf['_id3_year'] == -1 and len(track_names[0]) >= 3:
            cf['_id3_year'] = track_names[0][2]
        if cf['_id3_genre'] == -1 and len(track_names[0]) == 4:
            cf['_id3_genre'] = track_names[0][3]

        print "Tagging",
        for i in jack_ripstuff.all_tracks_todo_sorted:
            sys.stdout.write(".") ; sys.stdout.flush()
            mp3name = i[NAME] + ext
            wavname = i[NAME] + ".wav"
            if track_names[i[NUM]][0]:
                t_artist = track_names[i[NUM]][0]
            else:
                t_artist = a_artist
            t_name = track_names[i[NUM]][1]
            t_comm = ""
            if not cf['_only_dae'] and cf['_set_id3tag']:
                if len(t_name) > 30:
                    if string.find(t_name, "(") != -1 and string.find(t_name, ")") != -1:
                        # we only use the last comment
                        t_comm = string.split(t_name, "(")[-1]
                        if t_comm[-1] == ")":
                            t_comm = t_comm[:-1]
                            if t_comm[-1] == " ":
                                t_comm = t_comm[:-1]
                            t_name2 = string.replace(t_name, " (" + t_comm + ") ", "")
                            t_name2 = string.replace(t_name2, " (" + t_comm + ")", "")
                            t_name2 = string.replace(t_name2, "(" + t_comm + ") ", "")
                            t_name2 = string.replace(t_name2, "(" + t_comm + ")", "")
                        else:
                            t_comm = ""
                if jack_helpers.helpers[cf['_encoder']]['target'] == "mp3":
                    if cf['_write_id3v2']:
                        _set_id3_tag(
                            mp3name, eyed3.id3.ID3_V2_4,  'utf-8', a_title,
                            t_name, (i[NUM],len(jack_ripstuff.all_tracks_orig)),
                            t_artist, cf['_id3_genre'], cf['_id3_year'], None,
                            int(i[LEN] * 1000.0 / 75 + 0.5)
                        )
                    if cf['_write_id3v1']:
                        # encoding ??
                        _set_id3_tag(
                            mp3name, eyed3.id3.ID3_V1_1,  'latin1',
                            a_title, t_name,
                            (i[NUM],len(jack_ripstuff.all_tracks_orig)),
                            t_artist, cf['_id3_genre'], cf['_id3_year'], t_comm,
                            int(i[LEN] * 1000.0 / 75 + 0.5)
                        )
                elif jack_helpers.helpers[cf['_encoder']]['target'] == "flac":
                    if flac:
                        f = flac.FLAC(mp3name)
                        if f.vc is None: f.add_vorbiscomment()
                        f.vc['ALBUM'] = a_title
                        f.vc['TRACKNUMBER'] = str(i[NUM])
                        f.vc['TITLE'] = t_name
                        f.vc['ARTIST'] = t_artist
                        if cf['_id3_genre'] != -1:
                            f.vc['GENRE'] = id3genres[cf['_id3_genre']]
                        if cf['_id3_year'] != -1:
                            f.vc['DATE'] = str(cf['_id3_year'])
                        f.save()
                    else:
                        print
                        print "Please install python-mutagen package."
                        print "Without it, you'll not be able to tag FLAC tracks."
                elif jack_helpers.helpers[cf['_encoder']]['target'] == "ogg":
                    vf = ogg.vorbis.VorbisFile(mp3name)
                    oggi = vf.comment()
                    oggi.clear()
                    oggi.add_tag('ALBUM', a_title.encode("utf-8"))
                    oggi.add_tag('TRACKNUMBER', `i[NUM]`)
                    oggi.add_tag('TITLE', t_name.encode("utf-8"))
                    oggi.add_tag('ARTIST', t_artist.encode("utf-8"))
                    if cf['_id3_genre'] != -1:
                        oggi.add_tag('GENRE', id3genres[cf['_id3_genre']])
                    if cf['_id3_year'] != -1:
                        oggi.add_tag('DATE', `cf['_id3_year']`)
                    oggi.write_to(mp3name)
            if freedb_rename:
                newname = jack_freedb.filenames[i[NUM]]
                try:
                    i[NAME] = unicode(i[NAME], "utf-8")
                except UnicodeDecodeError:
                    i[NAME] = unicode(i[NAME], "latin-1")
                if i[NAME] != newname:
                    p_newname = newname.encode(locale.getpreferredencoding(), "replace")
                    u_newname = newname
                    newname = newname.encode(cf['_charset'], "replace")
                    p_mp3name = i[NAME].encode(locale.getpreferredencoding(), "replace") + ext
                    p_wavname = i[NAME].encode(locale.getpreferredencoding(), "replace") + ".wav"
                    ok = 1
                    if os.path.exists(newname + ext):
                        ok = 0
                        print 'NOT renaming "' + p_mp3name + '" to "' + p_newname + ext + '" because dest. exists.'
                        if cf['_keep_wavs']:
                            print 'NOT renaming "' + p_wavname + '" to "' + p_newname + ".wav" + '" because dest. exists.'
                    elif cf['_keep_wavs'] and os.path.exists(newname + ".wav"):
                        ok = 0
                        print 'NOT renaming "' + p_wavname + '" to "' + p_newname + ".wav" + '" because dest. exists.'
                        print 'NOT renaming "' + p_mp3name + '" to "' + p_newname + ext + '" because WAV dest. exists.'
                    if ok:
                        if not cf['_only_dae']:
                            try:
                                os.rename(mp3name, newname + ext)
                            except OSError:
                                error('Cannot rename "%s" to "%s" (Filename is too long or has unusable characters)' % (p_mp3name, p_newname + ext))
                            jack_m3u.add(newname + ext)
                        if cf['_keep_wavs']:
                            os.rename(wavname, newname + ".wav")
                            jack_m3u.add_wav(newname + ".wav")
                        jack_functions.progress(i[NUM], "ren", "%s-->%s" % (i[NAME], u_newname))
                    elif cf['_silent_mode']:
                        jack_functions.progress(i[NUM], "err", "while renaming track")
        print

    if not cf['_silent_mode']:
        if jack_freedb.names_available:
            print "Done with \"" + p_artist + " - " + p_title + "\"."
        else:
            print "All done.",
        if cf['_set_id3tag'] and cf['_id3_year'] != -1:
            print "Year: %4i" % cf['_id3_year'],
            if cf['_id3_genre'] == -1: print
        if cf['_set_id3tag'] and cf['_id3_genre'] != -1:
            if cf['_id3_genre'] <0 or cf['_id3_genre'] > len(id3genres):
                print "Genre: [unknown]"
            else:
                print "Genre: %s" % id3genres[cf['_id3_genre']]
        if cf['_vbr'] and not cf['_only_dae']:
            print "Avg. bitrate: %03.0fkbit" % ((total_size * 0.008) / (total_length / 75))
        else:
            print

    if jack_m3u.m3u:
        os.environ["JACK_JUST_ENCODED"] = "\n".join(jack_m3u.m3u)
    if jack_m3u.wavm3u:
        os.environ["JACK_JUST_RIPPED"] = "\n".join(jack_m3u.wavm3u)
    jack_m3u.write()