"""Written 04 august 2004 by Fred Dubuy <effediwhy@gmail.com>
The CD template is from Yves Ceccone <yves@yeccoe.org>
This work is released under the GNU GPL, version 2 or later.

This script reads the ID of the CD in the drive
and queries CDDB to get the album and song titles
The songs are displayed in a frame text on the back side
There are no font settings, they are up to you...
This script only avoid having to type the songs titles
It is possible to choose to add or not track number and track time

Version 3 : added multiple CDDB answers support

Make sure you have python-cddb installed
(http://cddb-py.sourceforge.net/)

Change the dev value below according to your configuration

10/16/2004 - Petr Vanek <petr@yarpen.cz>
Some strange artists use strange characters in names of their artworks.
You need specify the right encoding for these texts. The system encoding
 is taken as default. If you're using Scribus 1.2.1cvs or later you
can change it in the GUI dialog.
Or set e.g.:
encoding = 'utf8'
or whatever on line 36
"""

from scribus import *
#following import moved at the end of the script with test
#import DiscID, CDDB,cdrom
from Tkinter import *
import locale

import locale
language, encoding = locale.getdefaultlocale()

dev = "/dev/cdrom"

class Warning2(Frame):
	"class to display a message for import problems"
	def __init__(self,parent,message):
		Frame.__init__(self)
		frame = Frame(parent)
		self.parent=parent
		lab2=Label(frame,text=message)
		lab2.pack()
		button=Button(frame,text='OK',command=self.parent.destroy)
		button.pack()
		frame.pack()

class Warning(Toplevel):
	"generic class to display a message in a new dialog"
	def __init__(self,parent,message):
		Toplevel.__init__(self)
		lab2=Label(self,text=message)
		lab2.pack()
		button=Button(self,text='OK',command=self.quit)
		button.pack()
		self.geometry("+%d+%d" % ( (w-150)/2, (h-50)/2 ) )
	def quit(self):
		app.only_once=0
		self.destroy()



class Multiple(Toplevel):
	"opens a dialog to choose between multiples CDDB answers"
	def __init__(self,parent,query_info):
		Toplevel.__init__(self)
		self.parent=parent
		self.title=("Multiple choice")
		mlabel=Label(self,text="Multiple entries found, select one :")
		mlabel.pack()
		length=0
		count=0
		for i in query_info:
			count+=1
			if len(i['title'])>length:
				length=len(i['title'])
		self.list = Listbox(self, height=count, width=length)
		for i in query_info:
			self.list.insert(END, i['title'])
		self.list.bind("<Double-Button-1>", self.choice2)
		self.list.pack()
		b1=Button(self,text='Select',command=self.choice)
		b1.pack(side=LEFT)
		b2=Button(self,text='Cancel',command=self.cancel_multiple)
		b2.pack(side=RIGHT)
		#wi=self.winfo_width()
		#hg=self.winfo_height()
		self.geometry("+%d+%d" % ( (w-300)/2, (h-150)/2 ) )
	def choice(self):
        #no current selection
		if len(map(int,self.list.curselection()))==0:
			return
		app.sel_index=map(int,self.list.curselection())[0]
		self.destroy()
	def choice2(self,event):
		self.choice()
	def cancel_multiple(self):
		app.only_once=0
		self.destroy()

class Application(Frame):
	def __init__(self, parent):
		Frame.__init__(self)
		self.parent=parent
		frame = Frame(parent)
		parent.title("CD Cover creation")
		lab_ent=Label(frame,text="Enter your CD device :")
		lab_ent.grid(row=0, columnspan=2)
		self.ent=Entry(frame)
		self.ent.insert(0,dev)
		self.ent.icursor(len(dev))
		self.ent.grid(row=1,columnspan=2)
		self.numbering = IntVar()
		self.ttime = IntVar()
		self.sel_index = -1
		self.only_once = 0
		c1 = Checkbutton(frame, text="Add track number", variable=self.numbering)
		c1.grid(row=2,column=0)
		c1.select()
		c2 = Checkbutton(frame, text="Add track time", variable=self.ttime)
		c2.grid(row=2,column=1)
		b_valid=Button(frame,text='Create Cover',command=self.get_device)
		b_valid.grid(row=3,column=0)
		b_cancel=Button(frame,text='Cancel',command=self.quit)
		b_cancel.grid(row=3,column=1)
		frame.pack()
	def get_device(self):
		#protection against multiple choice-window opening
		if self.only_once==1:
			return
		self.only_once=1
		self.build_cover(self.ent.get(),self.numbering.get(),self.ttime.get())

	def quit(self):
		self.parent.destroy()

	def build_cover(self,dev,putnumber,puttime):
		#Get info from CD as in python-cddb examples
		cdrom = None
		try:
			if dev:
				cdrom = DiscID.open(dev)
			else:
				cdrom = DiscID.open()
		except: 
			w=Warning(self,"Cannot access the device "+dev)
			return
		try:
			disc_id = DiscID.disc_id(cdrom)
		except:
			w=Warning(self,"Cannot read the device" +dev)
			return
		try:
			(query_stat, self.query_info) = CDDB.query(disc_id)
		except:
			w=Warning(self,"Cannot access to CDDB. Check your internet connection")
			return
	
		if query_stat == 200:
			(read_stat, read_info) = CDDB.read(self.query_info['category'], 
					       	self.query_info['disc_id'])
			if read_stat != 210:
				w=Warning(self,"Disc ID not found in CDDB")
				return
			else:
				album=self.query_info['title']
		elif query_stat == 210 or query_stat == 211:
			m=Multiple(self,self.query_info)
			self.wait_window(m)
			#window close but no choice made
			if self.sel_index == -1:
				return
			(read_stat, read_info) = CDDB.read(self.query_info[self.sel_index]['category'], self.query_info[self.sel_index]['disc_id'])
			album=self.query_info[self.sel_index]['title']
		else:
			w=Warning(self,"Disc ID not found in CDDB")
			return
		#here starts the template building
		SetUnit(1)
		Margins = (0, 0, 0, 0)
		Papier_A4 = (210, 297)
		if NewDoc(Papier_A4, Margins, Landscape, 1, Millimeters, NoFacingPages, FirstPageLeft):
			NewPage(-1)
			GotoPage(1)
			CreateLayer("crop")
			SetActiveLayer("crop")
			t1 = CreateLine(28.5, 38, 28.5, 43) 
			SetLineWidth(0.1, t1)
			t2 = CreateLine(148.5, 38, 148.5, 43)
			SetLineWidth(0.1, t2)
			t3 = CreateLine(268.5, 38, 268.5, 43) 
			SetLineWidth(0.1, t3)
			t4 = CreateLine(28.5, 172, 28.5, 167)
			SetLineWidth(0.1, t4)
			t5 = CreateLine(148.5, 172, 148.5, 167)
			SetLineWidth(0.1, t5) 
			t6 = CreateLine(268.5, 172, 268.5, 167)
			SetLineWidth(0.1, t6)
			t7 = CreateLine(21.5, 45, 26.5, 45)
			SetLineWidth(0.1, t7)
			t8 = CreateLine(21.5, 165, 26.5, 165)
			SetLineWidth(0.1, t8)
			t9 = CreateLine(270.5, 45, 275.5, 45)
			SetLineWidth(0.1, t9)
			t10 = CreateLine(270.5, 165, 275.5, 165)
			SetLineWidth(0.1, t10)
			CreateLayer("bleed")
			SetActiveLayer("bleed")
			img1 = CreateImage(24.35, 41.25 , 124.20, 127.95,)
			img2 = CreateImage(148.55, 41.25 , 124.20, 127.95,)
			CreateLayer("normal")
			SetActiveLayer("normal")
			a = CreateText(98.5, 20, 100, 10)
			SetText("CD cover template - Front side", a)
			SetFontSize(11, a)
			SetTextAlignment(1, a)	
			b = CreateText(28.5, 45, 120, 120)
			SetFillColor("None", b)
			c = CreateText(148.5, 45, 120, 120)
			SetFillColor("None", c)
			GotoPage(2)
			SetActiveLayer("normal")
			a2 = CreateText(98.5, 20, 100, 10)
			SetText('CD cover template - Back side', a2)
			SetFontSize(11, a2)
			SetTextAlignment(1, a2)
			a2t = CreateText(204, 44, 78, 9)
			SetText("Instructions :", a2t)
			SetFontSize(13, a2t)
			SetTextAlignment(1, a2t)	
			a21 = CreateText(204, 54, 78, 87)
			SetText('Modify either the text on the Normal layer, or the pictures on the "bleed" layers, or both. You can change the frame types (image to text frame or text to image,...). The bleeds are wider than the CD size, which avoid any blank margin when cutting the printed document. The external crop marks will allow you to cut the cover and the internal crop marks are here for the folding.\nYou can get the front picture of your CD using your favorite search engine\'s image search feature', a21)
			SetFontSize(11, a21)
			SetTextAlignment(0, a21)
			b2 = CreateText(28.5, 162.10, 117, 6)
			SetText(unicode(album, encoding), b2)
			SetFontSize(9, b2)
			SetTextAlignment(1, b2)
			RotateObjectAbs(90, b2)
			SetFillColor("None", b2)
			c2 = CreateText(34.5, 45, 137.5, 117)
			offset=0
			InsertText(unicode(album+"\n\n", encoding), offset,c2)
			offset=offset+len(album)+2
			for i in range(0, disc_id[1]):
				if putnumber == 1:
					song='%d - %s' % (i+1, read_info['TTITLE' + `i`]) 
				else:
					song='%s' % read_info['TTITLE' + `i`]
				if puttime == 1:
					if i < (disc_id[1]-1):
						ttime=(disc_id[i+3]-disc_id[i+2])/75
					else:
						ttime=disc_id[i+3]-disc_id[i+2]/75
					song+=' - %d:%.2d' % ((ttime/60),(ttime%60))
				InsertText(unicode(song+"\n", encoding),offset,c2)
				offset=offset+len(song)+1
			SetFillColor("None", c2)
			d2 = CreateText(28.5, 162.10, 117, 6)
			SetText(unicode(album, encoding), d2)
			SetFontSize(9, d2)
			SetTextAlignment(1, d2)
			RotateObjectAbs(90, d2)
			SetFillColor("None", d2)
			MoveObject(143.5, 0, d2)
			SetActiveLayer("bleed")
			img3 = CreateImage(24.35, 41.25 , 157.50, 126.50,)
			SetActiveLayer("crop")
			t21 = CreateLine(28.5, 38, 28.5, 43) 
			SetLineWidth(0.1, t21)
			t22 = CreateLine(34.5, 38, 34.5, 43)
			SetLineWidth(0.1, t22)
			t23 = CreateLine(172, 38, 172, 43)
			SetLineWidth(0.1, t23)
			t24 = CreateLine(178, 38, 178, 43)
			SetLineWidth(0.1, t24)
			t25 = CreateLine(28.5, 164.5, 28.5, 169.5) 
			SetLineWidth(0.1, t25)
			t26 = CreateLine(34.5, 164, 34.5, 169.5)
			SetLineWidth(0.1, t26)
			t27 = CreateLine(172, 164, 172, 169.5)
			SetLineWidth(0.1, t27)
			t28 = CreateLine(178, 164, 178, 169.5)
			SetLineWidth(0.1, t28)
			t29 = CreateLine(22.5, 45, 27.5, 45)
			SetLineWidth(0.1, t29)
			t30 = CreateLine(22.5, 162, 27.5, 162)
			SetLineWidth(0.1, t30)
			t31 = CreateLine(179.5, 45, 184.5, 45)
			SetLineWidth(0.1, t31)
			t32 = CreateLine(179.5, 162, 184.5, 162)
			SetLineWidth(0.1, t32)
			self.quit()

root=Tk()
w=root.winfo_screenwidth()
h=root.winfo_screenheight()
root.geometry("+%d+%d" % ( (w-300)/2, (h-100)/2 ) )
try:
	import DiscID, CDDB, cdrom
except:
	app=Warning2(root,"You need to install python-cddb!\n"+
					"see http://cddb-py.sourceforge.net/\n"
					+"Gentoo : emerge cddb-py\n"
					+"Debian : apt-get install python-cddb\n"
					+"Mandrake : urpmi python-CDDB")
else:
# be sure what encoding you use. this is available from 1.2.1cvs, 
# so this try/catch enable using it with previous versions
	try:
		encoding = valueDialog('CDDB Cover', 'If you are creating a cover for non-english record/artist<br>you may specify the right text encoding for the local characters.<br>You can get some errors using wrong encoding.<br>Your system setting is:', encoding)
	except:
		print 'Your encoding is: ' + encoding + '. You can change it manually at the beginning of this script. Or upgrade your Scribus ;)'	
	app=Application(root)
	
root.mainloop()
