#!/usr/bin/env python

# Jouni Paulus, jouni.paulus@iki.fi, 23.11.2006
#
# Based on cddb-info.py from:
# Written 17 Nov 1999 by Ben Gertzfield <che@debian.org>
# This work is released under the GNU GPL, version 2 or later.

import DiscID, CDDB, sys, os, math, MySQLdb

dev = None
cdrom = None

# MySQL db settings
dbHost = "localhost"
dbPort = 3306
dbUser = "user"
dbPass = "password"

strEncoding = "latin-1"

# if True, the db inserts are skipped and just printed instead
doDry = False
#doDry = True

if len(sys.argv) >= 2:
    dev = sys.argv[1]

if dev:
    cdrom = DiscID.open(dev)
else:
    cdrom = DiscID.open()

print "Getting disc id in CDDB format...\n"

disc_id = DiscID.disc_id(cdrom)

print "Disc ID: %08lx Num tracks: %d\n" % (disc_id[0], disc_id[1])
print "Querying CDDB for info on disc...\n"

print "Disc info:\n"
for i in range(0, disc_id[1]):
    startF = disc_id[i+2]
    if i == disc_id[1] - 1:
        stopF = disc_id[i+3]*75.0
    else:
        stopF = disc_id[i+3]-1

    durF = stopF - startF + 1
    durMin = int(math.floor(durF/75.0/60.0))
    durSec = int(math.floor(durF/75.0 - durMin*60.0))
    durFrac = int((durF/75.0 - durMin*60.0 - durSec*1.0)*100.0)
        
    print "Track %.02d: [%d:%s.%s]" % \
          (i+1, durMin, str(durSec).zfill(2), str(durFrac).zfill(2))

(query_stat, query_info) = CDDB.query(disc_id)

if query_stat == 202:
    # "No match found"
    print "No match found, insert the data yourself.\n"
    sys.exit("Bye...")
   
elif query_stat == 403:
    # "Error, database entry corrupt"
    print "Failure getting disc info, status %i, meaning \"Database entry corrupt\".\n" % query_stat
    sys.exit("Bye...")

elif query_stat == 409:
    # "Error, no handshake"
    print "Failure getting disc info, status %i, meaning \"No handshake\".\n" % query_stat
    sys.exit("Bye...")

elif query_stat == 210 or query_stat == 211:
    # "Multiple exact matches found" or "Multiple inexact matches found"
    print "Query successfull. Found multiple (in)exact matches:"
    j = 0
    for i in query_info:
	print "%d: Category: %s, Title: %s" % (j, i['category'], i['title'])
        j = j + 1

    while (True):
        print "Please input the number of the matching disc."
        multiIdx = int(raw_input("#: "))
        if multiIdx >= 0 and multiIdx < j:
            break

    qInfo = query_info[multiIdx]
    
if query_stat == 200:
    # "Success"
    print ("Success!\nQuerying CDDB for track info of `%s'...\n" % query_info['title'])

    qInfo = query_info

# Fetch more detailed info
(read_stat, read_info) = CDDB.read(qInfo['category'], qInfo['disc_id'])
if read_stat == 401:
    print "Error, specified entry not found in CDDB.\n"
    sys.exit("Bye...")

elif read_stat == 402:
    print "Error, server error.\n"
    sys.exit("Bye...")

elif read_stat == 403:
    print "Error, database entry is corrupt.\n"
    sys.exit("Bye...")

elif read_stat == 409:
    print "Error, no handshake.\n"
    sys.exit("Bye...")

elif read_stat == 417:
    print "Error, access limit exceeded.\n"
    sys.exit("Bye...")

elif read_stat == 210:
    print "Query successfull.\n"
    discIdStr = hex(disc_id[0])
    discIdStr = discIdStr[2:(len(discIdStr)-2)] # clip the 0x from the beginning

    titleStr = read_info['DTITLE']
    tmpPair = titleStr.split('/',1)
    artistStr = tmpPair[0].lstrip().rstrip().decode(strEncoding)
    titleStr = tmpPair[1].lstrip().rstrip().decode(strEncoding)
    artistStr=artistStr.replace("'","\\'")
    titleStr=titleStr.replace("'","\\'")

    print "Disc genre %s, release year %s, id %s\n" % \
          (read_info['DGENRE'], read_info['DYEAR'], discIdStr)
    for i in range(0, disc_id[1]):
        startF = disc_id[i+2]
        if i == disc_id[1] - 1:
            stopF = disc_id[i+3]*75.0
        else:
            stopF = disc_id[i+3]-1

        durF = stopF - startF + 1
        durMin = int(math.floor(durF/75.0/60.0))
        durSec = int(math.floor(durF/75.0 - durMin*60.0))
        durFrac = int((durF/75.0 - durMin*60.0 - durSec*1.0)*100.0)
        
        print "Track %.02d: %s [%d:%s.%s]" % \
              (i+1, read_info['TTITLE' + `i`], durMin, str(durSec).zfill(2), str(durFrac).zfill(2))

    print "Do you want to insert this disc to the database? [y/N]"
    insChoise = raw_input("#: ")
    if (insChoise !="y") and (insChoise != "Y"):
        sys.exit("Bye...");

### Ok, now ne have all the data collected, so let's insert it to the db.

# connect to db
db = MySQLdb.connect(host=dbHost, port=dbPort, user=dbUser, passwd=dbPass, db="myCDDB")
# get a cursor to operate with
dbCursor = db.cursor()

# check if there is already a disc woth thos id in the db
sqlCommand = "SELECT cddbid FROM cds WHERE cddbid = '%s'" % discIdStr
dbCursor.execute(sqlCommand)
resultRows = dbCursor.fetchall()

if len(resultRows) != 0:
    # something found with this id
    print "There seems to be a CD in the db with the same id, so I'll stop here.\n"
    sys.exit("Bye...")

# insert this disc

yearStr = "%s" % read_info['DYEAR']
if len(yearStr) == 0:
    yearStr = "0000"

genreStr = "%s" % read_info['DGENRE']
if len(genreStr) == 0:
    genreStr = qInfo['category']
    
sqlCommand = "INSERT INTO cds (cddbid, artist, title, category, year, comment) VALUES ('%s', '%s', '%s', '%s', '%s', '%s')" \
             % (discIdStr, artistStr, titleStr, genreStr, yearStr, "")
if doDry:
    print "%s\n" % (sqlCommand)
else:
    dbCursor.execute(sqlCommand)

# insert all tracks, one by one
for i in range(0, disc_id[1]):
    startF = disc_id[i+2]
    if i == disc_id[1] - 1:
        stopF = disc_id[i+3]*75.0
    else:
        stopF = disc_id[i+3]-1

    durF = stopF - startF + 1
    durHour = int(math.floor(durF/75.0/3600.0))
    durMin = int(math.floor(durF/75.0/60.0 - durHour*60.0))
    durSec = int(math.floor(durF/75.0 - durMin*60.0 - durHour*3600.0))
    durFrac = int((durF/75.0 - durHour*3600.0 - durMin*60.0 - durSec*1.0)*100.0)

    timeStr = "%.2d:%.2d:%.2d.%.2d" % (durHour, durMin, durSec, durFrac)
    
    sqlCommand = "INSERT INTO tracks (cddbid, artist, title, trackno, time) VALUES ('%s', '%s', '%s', '%.02d', '%s')" \
                 % (discIdStr, artistStr, read_info['TTITLE' + `i`].replace("'","\\'").decode(strEncoding), i+1, timeStr);
    if doDry:
        print "%s\n" % (sqlCommand)
    else:
        dbCursor.execute(sqlCommand)
    

print "All is done. Bye."
