#!/usr/bin/python

#Audio Tools, a module and set of tools for manipulating audio data
#Copyright (C) 2007-2010  Brian Langenberger

#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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA


import sys
import os
import os.path
import audiotools
import gettext

gettext.install("audiotools",unicode=True)

if (__name__ == '__main__'):
    parser = audiotools.OptionParser(
        usage=_(u'%prog [options] [-x filename] <track 1> [track 2] ...'),
        version="Python Audio Tools %s" % (audiotools.VERSION))

    parser.add_option('-V','--verbose',
                      action='store',
                      dest='verbosity',
                      choices=["quiet","normal","debug"],
                      default="normal",
                      help=_(u'the verbosity level to execute at'))

    parser.add_option('-x','--xmcd',action='store',
                      type='string',dest='xmcd',default='-',
                      metavar='FILENAME',
                      help=_(u'FreeDB XMCD file or MusicBrainz XML output file'))

    server = audiotools.OptionGroup(parser,_(u"Server Options"))

    server.add_option('--musicbrainz-server',action='store',
                      type='string',dest='musicbrainz_server',
                      default=audiotools.MUSICBRAINZ_SERVER,
                      metavar='HOSTNAME')
    server.add_option('--musicbrainz-port',action='store',
                      type='int',dest='musicbrainz_port',
                      default=audiotools.MUSICBRAINZ_PORT,
                      metavar='PORT')

    server.add_option('--freedb-server',action='store',
                      type='string',dest='freedb_server',
                      default=audiotools.FREEDB_SERVER,
                      metavar='HOSTNAME')
    server.add_option('--freedb-port',action='store',
                      type='int',dest='freedb_port',
                      default=audiotools.FREEDB_PORT,
                      metavar='PORT')

    server.add_option('--no-musicbrainz',action='store_false',
                      dest='use_musicbrainz',default=True,
                      help='do not query MusicBrainz for metadata')
    server.add_option('--no-freedb',action='store_false',
                      dest='use_freedb',default=True,
                      help='do not query FreeDB for metadata')

    server.add_option('-D','--default',
                      action='store_const',const=1,default=None,
                      help=_(u'when multiple choices are available, select the first one automatically'))

    parser.add_option_group(server)

    parser.add_option('-m','--metadata',action='store_true',
                      dest='metadata',default=False,
                      help=_(u'pull metadata from tracks rather than from server'))

    parser.add_option('--cue',
                      action='store',
                      type='string',
                      dest='cuesheet',
                      metavar='FILENAME',
                      help=_(u'the cuesheet to use for track boundaries'))


    (options,args) = parser.parse_args()
    msg = audiotools.Messenger("track2xmcd",options)

    audiofiles = audiotools.open_files(args,messenger=msg)

    if (len(audiofiles) < 1):
        msg.error(_(u"You must specify at least 1 supported audio file"))
        sys.exit(1)

    if (options.xmcd == '-'):
        outfile = sys.stdout
    else:
        try:
            if (not os.path.isfile(options.xmcd)):
                outfile = file(options.xmcd,"w")
            else:
                msg.error(_(u"Refusing to overwrite \"%s\"") % \
                              (msg.filename(options.xmcd)))
                sys.exit(1)
        except IOError,e:
            msg.error(_(u"Unable to write \"%s\"") % \
                          (msg.filename(options.xmcd)))
            sys.exit(1)

    if (options.metadata):   #pull XML/XMCD data from AudioFile metadata
        returnval = 0

        if (options.use_musicbrainz):
            output_class = audiotools.MusicBrainzReleaseXML
        else:
            output_class = audiotools.XMCD

        if (len(audiofiles) == 1):
            if (options.cuesheet is not None):
                try:
                    outfile.write(output_class.from_cuesheet(
                            audiotools.read_sheet(options.cuesheet),
                            audiofiles[0].total_frames(),
                            audiofiles[0].sample_rate(),
                            audiofiles[0].get_metadata()).build())
                except audiotools.SheetException,err:
                    msg.error(unicode(err))
                    sys.exit(1)
            elif (audiofiles[0].get_cuesheet() is not None):
                outfile.write(output_class.from_cuesheet(
                        audiofiles[0].get_cuesheet(),
                        audiofiles[0].total_frames(),
                        audiofiles[0].sample_rate(),
                        audiofiles[0].get_metadata()).build())
            else:
                outfile.write(output_class.from_files(audiofiles).build())
        else:
            outfile.write(output_class.from_files(audiofiles).build())
    else:                     #grab XML/XMCD data from MusicBrainz/FreeDB
        if (len(audiofiles) == 1):
            file = audiofiles[0]
            if (file.get_cuesheet() is not None):
                musicbrainz_discid = audiotools.MBDiscID(
                    [(length * 75) / file.sample_rate() for length in
                     file.get_cuesheet().pcm_lengths(file.total_frames())])

                freedb_discid = audiotools.DiscID(
                    [(length * 75) / file.sample_rate() for length in
                     file.get_cuesheet().pcm_lengths(file.total_frames())])
            elif (options.cuesheet is not None):
                try:
                    cuesheet = audiotools.read_sheet(options.cuesheet)
                except audiotools.SheetException,err:
                    msg.error(unicode(err))
                    sys.exit(1)

                musicbrainz_discid = audiotools.MBDiscID(
                    [(length * 75) / file.sample_rate() for length in
                     cuesheet.pcm_lengths(file.total_frames())])

                freedb_discid = audiotools.DiscID(
                    [(length * 75) / file.sample_rate() for length in
                     cuesheet.pcm_lengths(file.total_frames())])
            else:
                musicbrainz_discid = audiotools.MBDiscID(
                    [file.cd_frames() for file in audiofiles])

                freedb_discid = audiotools.DiscID(
                    [file.cd_frames() for file in audiofiles])
        else:
            musicbrainz_discid = audiotools.MBDiscID(
                [file.cd_frames() for file in audiofiles])

            freedb_discid = audiotools.DiscID(
                [file.cd_frames() for file in audiofiles])

        returnval = 0
        musicbrainz_matches = 0
        freedb_matches = 0
        if (options.use_musicbrainz):
            try:
                musicbrainz_matches = audiotools.get_mbxml(
                    musicbrainz_discid,
                    outfile,
                    options.musicbrainz_server,
                    options.musicbrainz_port,
                    msg,
                    options.default)
                returnval = 0
            except IOError,e:
                msg.error(unicode(e))
                returnval = 1

        if ((musicbrainz_matches == 0) and options.use_freedb):
            try:
                freedb_matches = audiotools.get_xmcd(
                    freedb_discid,
                    outfile,
                    options.freedb_server,
                    options.freedb_port,
                    msg,
                    options.default)
                returnval = 0
            except IOError,e:
                msg.error(unicode(e))
                returnval = 1

        #if musicbrainz_matches and freedb_matches are both 0
        #output a MusicBrainzReleaseXML file instead of a FreeDB one
        #since XML is better for editing by end users
        #(none of that " / "-handling nonsense)
        if ((musicbrainz_matches == 0) and (freedb_matches == 0)):
            if (options.use_musicbrainz):
                musicbrainz_discid.toxml(outfile)
            else:
                freedb_discid.toxmcd(outfile)
            msg.info(_(u"%s written") % (msg.filename(options.xmcd)))
            outfile.close()

    if (returnval != 0):
        sys.exit(1)

