###########################################################################
#
# Code for advancing and scanning 8mm film
# by controlling a dot matrix printer connected through the parallel port
# and an Epson 3490 flatbed scanner, controled through its twain driver
#
# (c) 2005 - Shay Mozes
#
###########################################################################

from Tkinter import *
import twain
import parallel
import time
import os
import string
#import process

TITLE="now scanning batch no. "
tmpfilename="tmp.xbm"
tmpfileprefix="tmp"

class MainWindow(Frame):
    def __init__(self, title,counter,stopat,dirname):
        Frame.__init__(self)
        self.master.title(title)
        self.master.geometry("150x150+100+100")
        MenuPanel = Frame(self, relief=RAISED, borderwidth=2)
        File = Menubutton(MenuPanel, text="File")
        File.menu = Menu(File)
##        File.menu.add_command(label="Connect", command=self.MnuOpenScanner)
##        File.menu.add_command(label="Acquire", command=self.MnuAcquire)
##        File.menu.add('separator')
        File.menu.add_command(label="Exit", command=self.MnuQuit)
        File['menu'] = File.menu
        File.pack(side="left")
        MenuPanel.pack(side="top", fill=X, expand=1)
        self.tk_menuBar(File)
        self.pack(fill="both")
        (self.SD, self.SM) = (None, None)
        self.bind('<Destroy>', self.OnQuit)
        self.MnuOpenScanner()
        self.counter=counter
	self.stopat=stopat
	self.dirname = dirname
        self.title = title
        self.master.title(self.title+str(self.counter))
        self.p = parallel.Parallel()
        self.MnuAcquire()
        

    def MnuQuit(self, event=None):
        self.unbind('<Destroy>')
        if self.SD: self.SD.destroy()
        if self.SM: self.SM.destroy()
        self.quit()

    def OnQuit(self, event=None):
        if self.SD: self.SD.destroy()
        if self.SM: self.SM.destroy()

    def MnuOpenScanner(self, event=None):
        if not self.SM:
            self.SM = twain.SourceManager(self.winfo_id(), ProductName="Simple Tk Demo")
        if not self.SM:
            return
        self.SD = self.SM.OpenSource('EPSON Perfection 2480/2580')
        if self.SD:
            self.master.title("Simple TWAIN Demo: " + self.SD.GetSourceName())

    def MnuAcquire(self, event=None):
        if not self.SD:
            self.MnuOpenScanner(event)
        if not self.SD: return
##        self.SD.SetCapability(twain.ICAP_YRESOLUTION, twain.TWTY_FIX32, 50.0) # Scale image to 50%
##        self.SD.SetCapability(twain.ICAP_PIXELTYPE, twain.TWTY_UINT16, twain.TWPT_BW) # Black & White
##        self.SD.RequestAcquire(0) # do not show user interface

        self.SD.SetCapability(twain.ICAP_LIGHTPATH,4,twain.TWLP_TRANSMISSIVE)
        self.SD.SetCapability(twain.ICAP_UNITS,twain.TWTY_UINT16,twain.TWUN_PIXELS)
        self.SD.SetCapability(twain.ICAP_XRESOLUTION,twain.TWTY_FIX32,4800.0)
        self.SD.SetCapability(twain.ICAP_YRESOLUTION,twain.TWTY_FIX32,4800.0)
        self.SD.SetCapability(twain.ICAP_CONTRAST,twain.TWTY_FIX32,25.0)
#        self.SD.SetCapability(twain.ICAP_BRIGHTNESS,twain.TWTY_FIX32,125.0)        
#        self.SD.SetImageLayout((234.0,3268.0,3766.0,4800.0),1,1,1) #2400x4800DPI
#        self.SD.SetImageLayout((234.0,1634.0,3766.0,2400.0),1,1,1) #2400x2400DPI
#        self.SD.SetImageLayout((468.0,3268.0,7532.0,4800.0),1,1,1) #4800x4800DPI
#        self.SD.SetImageLayout((936.0,6536.0,15064.0,9600.0),1,1,1) #9600x9600DPI

#        self.SD.SetImageLayout((1.0,190.0,140.0,213.0),1,1,1) #72DPI
#        self.SD.SetImageLayout((0.0,6400.0,5000.0,7113.0),1,1,1) #2400x2400DPI                        
        self.SD.SetImageLayout((0.0,12850.0,10000.0,14250.0),1,1,1) #4800x4800DPI                        

##        print "before RequestAcquire ", self.counter,
        self.SD.RequestAcquire(0,1)
##        print ". after."
        self.filename = "D:\\Shay\\8mm\\"+self.dirname+"\\frame"+str(self.counter)
        self.SD.SetXferFileName(self.filename+".bmp",twain.TWFF_BMP)

        self.TwainMessage = None
        self.after(250, self.OnIdleTimer)
        self.SM.SetCallback(self.OnTwainEvent)
    
    def ProcessXFer(self, event=None):
        self.SD.XferImageByFile()
#        self.SD.SetCapability(twain.ICAP_LIGHTPATH,4,twain.TWLP_REFLECTIVE)
#        time.sleep(5)
        for i in range(1,29):
            self.p.setData(10); self.p.setDataStrobe(0); time.sleep(0.005); self.p.setDataStrobe(1)
        self.counter = self.counter+1
        self.master.title(self.title+str(self.counter))
#        subprocess.Popen("convert -compress Lossless "+self.filename+".bmp "+self.filename+".jpg",shell=True)
        os.system("convert -compress Lossless "+self.filename+".bmp "+self.filename+".jpg")
        os.remove(self.filename+".bmp")
	if self.counter==self.stopat:
            self.unbind('<Destroy>')
            if self.SD: self.SD.destroy()
            if self.SM: self.SM.destroy()
            self.quit()
	    sys.exit(0)
##        if self.counter%75==0:
##            self.SD.SetCapability(twain.ICAP_LIGHTPATH,4,twain.TWLP_REFLECTIVE)
##            self.SD.SetCapability(twain.ICAP_XRESOLUTION,twain.TWTY_FIX32,4800.0)
##            self.SD.SetCapability(twain.ICAP_YRESOLUTION,twain.TWTY_FIX32,4800.0)
##            self.SD.SetImageLayout((0.0,0.0,10.0,10.0),1,1,1)
##            self.SD.RequestAcquire(0,1)
##            self.SD.SetXferFileName("D:\\Shay\\8mm\\garbage.bmp",twain.TWFF_BMP)
##            self.SD.XferImageByFile()
##            time.sleep(600)
        self.TwainMessage = "NEXT_IMAGE"

##        (handle, more_to_come) = self.SD.XferImageNatively()
##        if 0:
##                res = twain.DIBToXBMFile(handle, tmpfileprefix)
##                fp=open("xxx.xbm", 'wb')
##                fp.write(res)
##                fp.close()
##                twain.GlobalHandleFree(handle)
##                l = Label(self, bitmap="@xxx.xbm")
##        else:
##                twain.DIBToXBMFile(handle, tmpfileprefix, tmpfilename)
##                twain.GlobalHandleFree(handle)
##                l = Label(self, bitmap="@" + tmpfilename)
##        print "handle freed."
##        l.pack(side="left", fill="both", expand=1)
    
    def OnTwainEvent(self, event=None):
        self.TwainMessage = event

    def OnIdleTimer(self):
        if not self.TwainMessage:
            self.after(250, self.OnIdleTimer)
            return
#        print "received twain event: ", self.TwainMessage        
        if self.TwainMessage == twain.MSG_XFERREADY:
            self.TwainMessage = None
            self.ProcessXFer(self.TwainMessage)
#            self.SD = None
            self.after(250, self.OnIdleTimer)
        elif self.TwainMessage == twain.MSG_CLOSEDSREQ:
            self.SD = None
            self.TwainMessage = None
        elif self.TwainMessage == "NEXT_IMAGE":
            self.TwainMessage = None
            self.MnuAcquire()
        else:
            print "received twain event: ", self.TwainMessage

MainWindow(TITLE,string.atoi(sys.argv[1]),string.atoi(sys.argv[2]),sys.argv[3]).mainloop()
 
