### jack_tag: name information (ID3 among others) stuff for
### jack - tag audio from a CD and encode it using 3rd party software
### Copyright (C) 1999-2003  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

import string
import os, sys
import locale

import jack_functions
import jack_ripstuff
import jack_targets
import jack_helpers
import jack_freedb
import jack_utils
import jack_misc
import jack_m3u

from jack_init import ogg
from jack_init import eyeD3
from jack_init import flac
from jack_globals import *

track_names = None
locale_names = None
genretxt = None

a_artist = None
a_title = None

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()
        if len(track_names[0]) == 4:
            # use freedb year and genre data if available
            if cf['_id3_genre'] == -1:
                cf['_id3_genre'] = track_names[0][3]
            if cf['_id3_year'] == -1:
                cf['_id3_year'] = track_names[0][2]

        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"
            t_artist = track_names[i[NUM]][0]
            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']:
                        mp3file = file(mp3name, "rw")
                        tag = eyeD3.Tag()
                        tag.link(mp3file)
                        tag.header.setVersion(eyeD3.ID3_V2_4)
                        tag.setTextEncoding(eyeD3.UTF_8_ENCODING)
                        tag.setAlbum(a_title)
                        tag.setTitle(t_name)
                        tag.setTrackNum((i[NUM],len(jack_ripstuff.all_tracks_orig)))
                        tag.setTitle(t_name)
                        if t_artist:
                           tag.setArtist(t_artist)
                        else:
                            tag.setArtist(a_artist)
                        if cf['_id3_genre'] != -1:
                            tag.setGenre("(%d)" % (cf['_id3_genre']))
                        if cf['_id3_year'] != -1:
                            tag.setDate(cf['_id3_year'])
                        tag.setPlayCount(int(i[LEN] * 1000.0 / 75 + 0.5))
                        tag.update()
                        mp3file.close()
                    if cf['_write_id3v1']:
                        mp3file = file(mp3name, "rw")
                        tag = eyeD3.Tag()
                        tag.link(mp3file)

                        tag.header.setVersion(eyeD3.ID3_V1_1)
                        tag.setTextEncoding(eyeD3.LATIN1_ENCODING)
                        old_genre = tag.getGenre()

                        tag.setAlbum(a_title)
                        if t_comm:
                            tag.addComment(t_comm)
                            tag.setTitle(t_name2)
                        else:
                            tag.setTitle(t_name)
                        tag.setTrackNum((i[NUM],len(jack_ripstuff.all_tracks_orig)))
                        tag.setTitle(t_name)
                        if t_artist:
                            tag.setArtist(t_artist)
                        else:
                            tag.setArtist(a_artist)
                        if cf['_id3_genre'] != -1:
                            tag.setGenre("(%d)" % (cf['_id3_genre']))
                        elif old_genre == None:
                            tag.setGenre("(255)") # unknown
                        if cf['_id3_year'] != -1:
                            tag.setDate(cf['_id3_year'])
                        try:
                            tag.update()
                        except UnicodeEncodeError:
                            if not cf['_write_id3v2']:
                                print
                                print "Track %02d contains data not supported by id3v1; please use --write-id3v2" % i[NUM]
                        mp3file.close()
                elif jack_helpers.helpers[cf['_encoder']]['target'] == "flac":
                    if flac:
                        chain = flac.metadata.Chain()
                        chain.read(mp3name)
                        it = flac.metadata.Iterator()
                        it.init(chain)
                        while 1:
                            if it.get_block_type() == flac.metadata.VORBIS_COMMENT:
                                block = it.get_block()
                                vc = flac.metadata.VorbisComment(block)
                                break
                            if not it.next():
                                break
                        if vc:
                            vc.comments['ALBUM'] = a_title.encode("utf-8")
                            vc.comments['TRACKNUMBER'] = `i[NUM]`
                            vc.comments['TITLE'] = t_name.encode("utf-8")
                            if t_artist:
                                vc.comments['ARTIST'] = t_artist.encode("utf-8")
                            else:
                                vc.comments['ARTIST'] = a_artist.encode("utf-8")
                            if cf['_id3_genre'] != -1:
                                vc.comments['GENRE'] = id3genres[cf['_id3_genre']]
                            if cf['_id3_year'] != -1:
                                vc.comments['DATE'] = `cf['_id3_year']`
                            chain.write(True, True)
                    else:
                        print
                        print "Please install the pyflac module available at"
                        print "http://www.sacredchao.net/quodlibet/wiki/Download"
                        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"))
                    if t_artist:
                        oggi.add_tag('ARTIST', t_artist.encode("utf-8"))
                    else:
                        oggi.add_tag('ARTIST', a_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:
                if t_artist:    # 'Various Artists'
                    replacelist = (("%n", cf['_rename_num'] % i[NUM]), ("%a", t_artist), ("%t", t_name), ("%l", a_title), ("%y", `cf['_id3_year']`), ("%g", genretxt))
                    newname = jack_misc.multi_replace(cf['_rename_fmt_va'], replacelist)
                    
                else:
                    replacelist = (("%n", cf['_rename_num'] % i[NUM]), ("%a", a_artist), ("%t", t_name), ("%l", a_title))
                    newname = jack_misc.multi_replace(cf['_rename_fmt'], replacelist)
                exec("newname = newname" + cf['_char_filter'])
                for char_i in range(len(cf['_unusable_chars'])):
                    newname = string.replace(newname, cf['_unusable_chars'][char_i], cf['_replacement_chars'][char_i])
                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()

