#!/usr/bin/python
# Written by Moon, Hyun-Jin <moonhyunjin@gmail.com>

# argv usage
import sys

from os import *

# Interpret strings as packed binary data.
from struct import *

# convert between eucKR and UTF-8
import codecs
(UTF8_encode, UTF8_decode, UTF8_streamreader, UTF8_streamwriter) = codecs.lookup('UTF-8')
(EUCKR_encode, EUCKR_decode, EUCKR_streamreader, EUCKR_streamwriter) = codecs.lookup('euc-kr')
(UTF16_encode, UTF16_decode, UTF16_streamreader, UTF16_streamwriter) = codecs.lookup('UTF-16')

# for GUI
import pygtk
pygtk.require('2.0')
import gtk

def euckr_to_utf8(msg):
    (umsg, ulen) = UTF8_encode(unicode(msg, "euc-kr"))
    return umsg

def utf8_to_euckr(msg):
    (umsg, ulen) = UTF8_decode(msg)
    (euc_msg, byte_used) = EUCKR_encode(umsg)
    return euc_msg

def utf8_to_utf16(msg):
    (umsg, ulen) = UTF8_decode(msg)
    (utf16_msg, byte_used) = UTF16_encode(umsg)
    return utf16_msg

def utf16_to_utf8(msg) :
    (umsg, ulen) = UTF16_decode(msg)
    (utf8_msg, byte_used) = UTF8_encode(umsg)
    return utf8_msg

def getSynchsafeInteger( realbyte ) :
    SynchsafeInteger = realbyte & 127
    realbyte = ( realbyte & 4294967168 ) << 1 # pow(2,32) - 1 - 127 thus FF FF FF 80

    SynchsafeInteger += realbyte & 32512      # 00 00 7F 00 as Big endian
    realbyte = ( realbyte & 4294934528 ) << 1 # FF FF 80 00

    SynchsafeInteger += realbyte & 8323072    # 00 7F 00 00
    realbyte = ( realbyte & 4286578688 ) << 1 # FF 80 00 00

    SynchsafeInteger += realbyte & 2130706432 # 7F 00 00 00
                   
    return SynchsafeInteger

openedFileDIC = dict()

class mainWindow :
    def destroy(self, widget, data=None):
        gtk.main_quit()

    def listClicked(self, treeview, path, view_column) :
        model = treeview.get_model()
        iter = model.get_iter(path)
        self.fileDICtoWindow( model.get_value(iter, 0) )
        return

    def SAVEclicked(self, button) :
        selectedFilename = openedFileDIC['CURRENT']
        id3 = openedFileDIC[selectedFilename]
        openedFileDIC[selectedFilename].fileDIC['TIT2'] = self.id3v2TitleTE.get_text()
        openedFileDIC[selectedFilename].fileDIC['TPE1'] = self.id3v2ArtistTE.get_text()
        openedFileDIC[selectedFilename].fileDIC['TPE2'] = self.id3v2AlbumArtistTE.get_text()
        openedFileDIC[selectedFilename].fileDIC['TALB'] = self.id3v2AlbumTE.get_text()
        openedFileDIC[selectedFilename].fileDIC['TCON'] = self.id3v2GenreTE.get_text()
        openedFileDIC[selectedFilename].fileDIC['TRCK'] = self.id3v2TrackTE.get_text()
        openedFileDIC[selectedFilename].fileDIC['TYER'] = self.id3v2YearTE.get_text()
        openedFileDIC[selectedFilename].fileDIC['TCOM'] = self.id3v2ComposerTE.get_text()
        openedFileDIC[selectedFilename].fileDIC['WXXX'] = self.id3v2URLTE.get_text()
        openedFileDIC[selectedFilename].fileDIC['TENC'] = self.id3v2EncodedbyTE.get_text()
        openedFileDIC[selectedFilename].fileDIC['TCOP'] = self.id3v2CopyrightTE.get_text()
        openedFileDIC[selectedFilename].fileDIC['TOPE'] = self.id3v2OrigartistTE.get_text()
        openedFileDIC[selectedFilename].fileDIC['COMM'] = self.id3v2CommentTE.get_text()

        openedFileDIC[selectedFilename].writeV23()
        
        openedFileDIC[selectedFilename] = allAboutID3(selectedFilename)
        return True

    def clickquit(self , widget ) :
        gtk.main_quit()
        return False

    def delete_event(self, widget, event, data=None) :
        gtk.main_quit()
        return False

    def OPENclicked(self, widget) :
        dialog = gtk.FileChooserDialog("Open..",
                                       None,
                                       gtk.FILE_CHOOSER_ACTION_OPEN,
                                       (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                       gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        dialog.set_select_multiple(True)
        response = dialog.run()

        if response == gtk.RESPONSE_OK:
            # make ID3 instances of selected file and
            # show filelist on mainwindow
            selected_filelist = dialog.get_filenames()
            for count in range( len(selected_filelist) ) :
                id3class = allAboutID3( selected_filelist[count] )
                # if the file is not MP3
                if 0 == len( id3class.fileDIC ) :
                    continue

                openedFileDIC[ selected_filelist[count]] = id3class
                self.liststore.append([ selected_filelist[count] , True])
            
        elif response == gtk.RESPONSE_CANCEL:
            print 'Closed, no files selected'

        dialog.destroy()
        return False

               
    def fileDICtoWindow(self, clickedFilename) :
        openedFileDIC['CURRENT'] = clickedFilename
        try :
            self.id3v2TitleTE.set_text( openedFileDIC[clickedFilename].fileDIC['TIT2'] )
        except : pass
        try :
            self.id3v2ArtistTE.set_text( openedFileDIC[clickedFilename].fileDIC['TPE1'] )
        except : pass
        try :
            self.id3v2AlbumTE.set_text( openedFileDIC[clickedFilename].fileDIC['TALB'] )
        except : pass
        try :
            self.id3v2GenreTE.set_text( openedFileDIC[clickedFilename].fileDIC['TCON'] )
        except : pass
        try :
            self.id3v2TrackTE.set_text( openedFileDIC[clickedFilename].fileDIC['TRCK'] )
        except : pass
        try :
            self.id3v2YearTE.set_text( openedFileDIC[clickedFilename].fileDIC['TYER'] )
        except : pass
        try :
            self.id3v2ComposerTE.set_text( openedFileDIC[clickedFilename].fileDIC['TCOM'] )
        except : pass
        try :
            self.id3v2CopyrightTE.set_text( openedFileDIC[clickedFilename].fileDIC['TCOP'] )
        except : pass
        try :
            self.id3v2URLTE.set_text( openedFileDIC[clickedFilename].fileDIC['WXXX'] )
        except : pass
        try :
            self.id3v2EncodedbyTE.set_text( openedFileDIC[clickedFilename].fileDIC['TENC'] )
        except : pass
        try :
            self.id3v2OrigartistTE.set_text( openedFileDIC[clickedFilename].fileDIC['TOPE'] )
        except : pass
        try :
            self.id3v2AlbumArtistTE.set_text( openedFileDIC[clickedFilename].fileDIC['TPE2'] )
        except : pass
        try :
            self.id3v2CommentTE.set_text( openedFileDIC[clickedFilename].fileDIC['COMM'] )
        except : pass

    def __init__(self) :
        # make basic boxes

        # make small widgets
        id3v1Label = gtk.Label("ID3v1")
        id3v1TrackLabel = gtk.Label("Track")
        self.id3v1TrackTE = gtk.Entry(0)
        id3v1LabelTrackHbox = gtk.HBox(False, 0)
        id3v1LabelTrackHbox.pack_start(id3v1Label, True, True, 0)
        id3v1LabelTrackHbox.pack_start(id3v1TrackLabel, True, True, 0)
        id3v1LabelTrackHbox.pack_start(self.id3v1TrackTE, True, True, 0)

        id3v1TitleHBox = gtk.HBox(False, 0)
        id3v1TitleLabel = gtk.Label("Title")
        self.id3v1TitleTE = gtk.Entry(0)
        id3v1TitleHBox.pack_start(id3v1TitleLabel, True, True, 0)
        id3v1TitleHBox.pack_start(self.id3v1TitleTE, True, True, 0)

        self.id3v1ArtistHBox = gtk.HBox(False, 0)
        self.id3v1ArtistLabel = gtk.Label("Artist")
        self.id3v1ArtistTE = gtk.Entry(0)
        self.id3v1ArtistHBox.pack_start(self.id3v1ArtistLabel, True, True, 0)
        self.id3v1ArtistHBox.pack_start(self.id3v1ArtistTE, True, True, 0)

        
        self.id3v1AlbumHBox = gtk.HBox(False, 0)
        self.id3v1AlbumLabel = gtk.Label("Album")
        self.id3v1AlbumTE = gtk.Entry(0)
        self.id3v1AlbumHBox.pack_start(self.id3v1AlbumLabel, True, True, 0)
        self.id3v1AlbumHBox.pack_start(self.id3v1AlbumTE, True, True, 0)

        self.id3v1YearGenreHBox = gtk.HBox(False, 0)
        self.id3v1YearLabel = gtk.Label("Year")
        self.id3v1YearTE = gtk.Entry(4)
        self.id3v1GenreLabel = gtk.Label("Genre")
        self.id3v1GenreTE = gtk.Entry(0)
        self.id3v1YearGenreHBox.pack_start(self.id3v1YearLabel, True, True, 0)
        self.id3v1YearGenreHBox.pack_start(self.id3v1YearTE, True, True, 0)
        self.id3v1YearGenreHBox.pack_start(self.id3v1GenreLabel, True, True, 0)
        self.id3v1YearGenreHBox.pack_start(self.id3v1GenreTE, True, True, 0)

        self.id3v1CommentHBox = gtk.HBox(False, 0)
        self.id3v1CommentLabel = gtk.Label("Comment")
        self.id3v1CommentTE = gtk.Entry(128) # comment size of id3V1 is 128
        self.id3v1CommentHBox.pack_start(self.id3v1CommentLabel, True, True, 0)
        self.id3v1CommentHBox.pack_start(self.id3v1CommentTE, True, True, 0)

        id3v2Label = gtk.Label("ID3v2")
        id3v2TrackLabel = gtk.Label("Track #")
        self.id3v2TrackTE = gtk.Entry(0)
        id3v2LabelTrackHBox = gtk.HBox(False, 0)
        id3v2LabelTrackHBox.pack_start(id3v2Label, True, True, 0)
        id3v2LabelTrackHBox.pack_start(id3v2TrackLabel, True, True, 0)
        id3v2LabelTrackHBox.pack_start(self.id3v2TrackTE, True, True, 0)

        self.id3v2TitleHBox = gtk.HBox(False, 0)
        self.id3v2TitleLabel = gtk.Label("Title")
        self.id3v2TitleTE = gtk.Entry(0)
        self.id3v2TitleHBox.pack_start(self.id3v2TitleLabel, True, True, 0)
        self.id3v2TitleHBox.pack_start(self.id3v2TitleTE, True, True, 0)
        
        self.id3v2ArtistHBox = gtk.HBox(False, 0)
        self.id3v2ArtistLabel = gtk.Label("Artist")
        self.id3v2ArtistTE = gtk.Entry(0)
        self.id3v2ArtistHBox.pack_start(self.id3v2ArtistLabel, True, True, 0)
        self.id3v2ArtistHBox.pack_start(self.id3v2ArtistTE, True, True, 0)

        self.id3v2AlbumHBox = gtk.HBox(False, 0)
        self.id3v2AlbumLabel = gtk.Label("Album")
        self.id3v2AlbumTE = gtk.Entry(0)
        self.id3v2AlbumHBox.pack_start(self.id3v2AlbumLabel, True, True, 0)
        self.id3v2AlbumHBox.pack_start(self.id3v2AlbumTE, True, True, 0)

        self.id3v2YearGenreHBox = gtk.HBox(False, 0)
        self.id3v2YearLabel = gtk.Label("Year")
        self.id3v2YearTE = gtk.Entry(4)
        self.id3v2GenreLabel = gtk.Label("Genre")
        self.id3v2GenreTE = gtk.Entry(0)
        self.id3v2YearGenreHBox.pack_start(self.id3v2YearLabel, True, True, 0)
        self.id3v2YearGenreHBox.pack_start(self.id3v2YearTE, True, True, 0)
        self.id3v2YearGenreHBox.pack_start(self.id3v2GenreLabel, True, True, 0)
        self.id3v2YearGenreHBox.pack_start(self.id3v2GenreTE, True, True, 0)

        self.id3v2CommentHBox = gtk.HBox(False, 0)
        self.id3v2CommentLabel = gtk.Label("Comment")
        self.id3v2CommentTE = gtk.Entry(0)
        self.id3v2CommentHBox.pack_start(self.id3v2CommentLabel, True, True, 0)
        self.id3v2CommentHBox.pack_start(self.id3v2CommentTE, True, True, 0)

        self.id3v2ComposerHBox = gtk.HBox(False, 0)
        self.id3v2ComposerLabel = gtk.Label("Composer")
        self.id3v2ComposerTE = gtk.Entry(0)
        self.id3v2ComposerHBox.pack_start(self.id3v2ComposerLabel, True, True, 0)
        self.id3v2ComposerHBox.pack_start(self.id3v2ComposerTE, True, True, 0)

        self.id3v2OrigartistHBox = gtk.HBox(False, 0)
        self.id3v2OrigartistLabel = gtk.Label("Orig. artist")
        self.id3v2OrigartistTE = gtk.Entry(0)
        self.id3v2OrigartistHBox.pack_start(self.id3v2OrigartistLabel, True, True, 0)
        self.id3v2OrigartistHBox.pack_start(self.id3v2OrigartistTE, True, True, 0)

        self.id3v2AlbumArtistHBox = gtk.HBox(False, 0)
        self.id3v2AlbumArtistLabel = gtk.Label("Album Artist")
        self.id3v2AlbumArtistTE = gtk.Entry(0)
        self.id3v2AlbumArtistHBox.pack_start(self.id3v2AlbumArtistLabel, True, True, 0)
        self.id3v2AlbumArtistHBox.pack_start(self.id3v2AlbumArtistTE, True, True, 0)
            
        self.id3v2CopyrightHBox = gtk.HBox(False, 0)
        self.id3v2CopyrightLabel = gtk.Label("Copyright")
        self.id3v2CopyrightTE = gtk.Entry(0)
        self.id3v2CopyrightHBox.pack_start(self.id3v2CopyrightLabel, True, True, 0)
        self.id3v2CopyrightHBox.pack_start(self.id3v2CopyrightTE, True, True, 0)

        self.id3v2URLHBox = gtk.HBox(False, 0)
        self.id3v2URLLabel = gtk.Label("URL")
        self.id3v2URLTE = gtk.Entry(0)
        self.id3v2URLHBox.pack_start(self.id3v2URLLabel, True, True, 0)
        self.id3v2URLHBox.pack_start(self.id3v2URLTE, True, True, 0)

        self.id3v2EncodedbyHBox = gtk.HBox(False, 0)
        self.id3v2EncodedbyLabel = gtk.Label("Encoded by")
        self.id3v2EncodedbyTE = gtk.Entry(0)
        self.id3v2EncodedbyHBox.pack_start(self.id3v2EncodedbyLabel, True, True, 0)
        self.id3v2EncodedbyHBox.pack_start(self.id3v2EncodedbyTE, True, True, 0)

        # Buttons at bottom
        HButton_box = gtk.HButtonBox()
        HButton_box.set_layout(gtk.BUTTONBOX_EDGE)

        button = gtk.Button(stock=gtk.STOCK_SAVE)
        HButton_box.add(button)
        button.connect("clicked", self.SAVEclicked )

        button = gtk.Button(stock=gtk.STOCK_CANCEL)
        HButton_box.add(button)

        button = gtk.Button(stock=gtk.STOCK_QUIT)
        button.connect("clicked", self.clickquit )
        HButton_box.add(button)

        # create the TreeView to display the File List
        cell = gtk.CellRendererText()
        cell.set_property('cell-background', 'cyan')

        tvcolumn = gtk.TreeViewColumn('File Name' )
        tvcolumn.pack_start(cell, True)
        tvcolumn.set_attributes(cell, text = 0 )

        self.liststore = gtk.ListStore(str, 'gboolean')
        #self.liststore.append(['FILENAME is here', True])

        treeview = gtk.TreeView(self.liststore)
        treeview.append_column(tvcolumn)
        # if one-click happen filelist, then change Tagbox
        treeview.connect('row-activated',
                         self.listClicked )

        scrolledwindow = gtk.ScrolledWindow()
        scrolledwindow.add(treeview)

        # open and close buttons for MP3 files
        openbutton = gtk.Button(stock=gtk.STOCK_OPEN)
        openbutton.connect("clicked", self.OPENclicked )

        closebutton = gtk.Button(stock=gtk.STOCK_CLOSE)
        #closebutton.connect("clicked",  )
        
	openHBox = gtk.HBox(False, 0)
       	openHBox.pack_start(openbutton, False, True, 1)
        openHBox.pack_start(closebutton, False, True, 1)



        # set window
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title("sid3e")
        self.window.connect("delete_event", self.delete_event)
        self.window.connect("destroy", self.destroy)
        self.window.set_border_width(30)
        self.window.set_default_size(height = 600, width = False)
        #self.window.set_size_request(900,700)

        # packing
	# GtkWindow can only contain one widget at a time.
        self.mainvbox = gtk.VBox(False, 0)
        self.window.add(self.mainvbox)

        tagHBox = gtk.HBox(False, 0)

        self.mainvbox.pack_start(openHBox, False, True, 0)
        self.mainvbox.pack_start(scrolledwindow, True, True, 0)
        self.mainvbox.pack_start(tagHBox, False, True, 0)

        # packing depth level 1
        v1vbox = gtk.VBox(False, 0)
        v2vbox = gtk.VBox(False, 0)

        tagHBox.pack_start(v1vbox, True, True, 0)
        tagHBox.pack_start(v2vbox, True, True, 0)
        
        # packing depth level 2
        v1vbox.pack_start(id3v1LabelTrackHbox, False, True, 1)
        v1vbox.pack_start(id3v1TitleHBox, False, True, 1)
        v1vbox.pack_start(self.id3v1ArtistHBox, False, True, 1)
        v1vbox.pack_start(self.id3v1AlbumHBox, False, True, 1)
        v1vbox.pack_start(self.id3v1YearGenreHBox, False, True, 1)
        v1vbox.pack_start(self.id3v1CommentHBox, False, True, 1)

        v2vbox.pack_start(id3v2LabelTrackHBox, False, False, 0)
        v2vbox.pack_start(self.id3v2TitleHBox, False, False, 0)
        v2vbox.pack_start(self.id3v2ArtistHBox, True, True, 0)
        v2vbox.pack_start(self.id3v2AlbumHBox, True, True, 0)
        v2vbox.pack_start(self.id3v2YearGenreHBox, True, True, 0)
        v2vbox.pack_start(self.id3v2CommentHBox, True, True, 0)
        v2vbox.pack_start(self.id3v2ComposerHBox, True, True, 0)
        v2vbox.pack_start(self.id3v2OrigartistHBox, True, True, 0)
        v2vbox.pack_start(self.id3v2AlbumArtistHBox, True, True, 0)
        v2vbox.pack_start(self.id3v2CopyrightHBox, True, True, 0)
        v2vbox.pack_start(self.id3v2URLHBox, True, True, 0)
        v2vbox.pack_start(self.id3v2EncodedbyHBox, True, True, 0)
        v2vbox.pack_start(HButton_box, True, True, 0)

        # show me the money!!
        self.window.show_all()

# class allAboutID3 can identify the file had ID3 tag or not.
#             can read ID3 tag from the file and write ID3 tag to the file.
class allAboutID3 :
    def readV23(self) :
        while True :
            if self.fileObject.tell() >= self.id3v2RealSize :
                # if the Extended Header doesn't exist,
                # Last position  will be  HEADER SIZE + 10
                print "Last position : " , self.fileObject.tell()
                break
            
            frameID = self.fileObject.read(4)
            # unpack().The result is a tuple even if it contains exactly one item.
            # above is from Python Library Reference
            currentFrameSize = unpack( '>i' , self.fileObject.read(4) )[0]
            if currentFrameSize == 0 :
                print "Last position : " , self.fileObject.tell()
                break

            # 2 bytes Flag is skipped. because always ZERO. ^^
            self.fileObject.read(2)

            contents = self.fileObject.read(currentFrameSize)
            if '\x01' == contents[0] : #'\x01' means contents is UTF-16
                try : contents = utf16_to_utf8( contents[1:] )
                except : pass
            else : #'\x00' means contents is ACSII or EUC-KR
                try : contents = euckr_to_utf8( contents[1:] )
                except : pass

            self.fileDIC[frameID] = contents
          
            for i in range( len(self.frameIDList) ) :
                if frameID == self.frameIDList[i] :
                    print 'Frame ID : ' , frameID
                    print 'Size : ' , currentFrameSize
                    print 'Contents : ' , self.fileDIC[frameID]
                    print '=========================================='
        print 'Frame ID : ' , self.fileObject.read(4)

        print self.fileDIC

    def readV24(self) :
        while True :
            if self.fileObject.tell() >= self.id3v2RealSize :
                # if the Extended Header doesn't exist,
                # Last position  will be  HEADER SIZE + 10
                print "Last position : " , self.fileObject.tell()
                break
            
            frameID = self.fileObject.read(4)
            # unpack().The result is a tuple even if it contains exactly one item.
            # above is from Python Library Reference
            sizeByte = unpack( '>i' , self.fileObject.read(4) )[0]
            currentFrameSize = (sizeByte & 255 ) + ( ( sizeByte & 65280 ) >> 1 ) + ( ( sizeByte & 16711680 ) >> 2 ) + ( ( sizeByte & 4278190080 ) >> 3 )

            if currentFrameSize == 0 :
                print "Last position : " , self.fileObject.tell()
                break

            # 2 bytes Flag is skipped. because always ZERO. ^^
            self.fileObject.read(2)

            content = self.fileObject.read(currentFrameSize)

            # '\x03' means content is UTF-8. Terminated with '\x00'
            if '\x03' == content[0] :
                content = content[1:]

            # '\x02' means content is UTF-16 Big Endian without BOM.
            # Terminated with '\x00\x00'
            elif '\x02' == content[0] :
                try : content = utf16_to_utf8( content[1:] )
                except : pass

            # '\01' means content is UTF-16 with BOM. Terminated with '\x00\x00'
            elif '\x01' == content[0] : #'\x01' means contents is UTF-16
                try : content = utf16_to_utf8( content[1:] )
                except : pass

            # '\x00' means content is ACSII or EUC-KR
            else :
                try : content = euckr_to_utf8( content[1:] )
                except : pass

            self.fileDIC[frameID] = content

            for i in range( len(self.frameIDList) ) :
                if frameID == self.frameIDList[i] :
                    print 'Frame ID : ' , frameID
                    print 'Size : ' , currentFrameSize
                    print 'Contents : ' , self.fileDIC[frameID]
                    print '=========================================='
        print 'Frame ID : ' , self.fileObject.read(4)

        print self.fileDIC

    def writeV23(self, srcfile = None ) :
        # this function is simple.
        # save to tmpfile
        # delete the srcfile
        # rename tmpfile to srcfile
        if srcfile == None :
            srcfile = openedFileDIC['CURRENT']

        tmpfile = openedFileDIC['CURRENT'] + '69'
        tmpfo = file(tmpfile,"wr")
        ID3stuff = 'ID3'
        ID3stuff += pack('b',3) # majorVersion 
        ID3stuff += pack('b',0) # reVersion
        ID3stuff += pack('b',0) # ID3v2 flags is almost 0

        stuff_of_frame = ''
        for frameID in self.fileDIC.keys() :
            if self.fileDIC[frameID] == '' :
                continue
            
#            try : frameContent = utf8_to_euckr( self.fileDIC[frameID] )
            try : frameContent = utf8_to_utf16( self.fileDIC[frameID] )
            except : pass
            stuff_of_frame += frameID
            stuff_of_frame += pack( '>i', getSynchsafeInteger( len(frameContent)+1 ) )
            stuff_of_frame += pack('h', 0) # flag is always zero. 2bytes
#            stuff_of_frame += pack('B', 255)
#            stuff_of_frame += pack('B', 254)
            stuff_of_frame += pack('B', 1) # before content, perhaps this means that content is cp949
            stuff_of_frame += frameContent

        ID3stuff += pack( '>i', getSynchsafeInteger( len(stuff_of_frame)+10 ) )
        ID3stuff += stuff_of_frame
        tmpfo.write(ID3stuff)

        # reopen to read sound from srcfile
        srcfo = file(srcfile,'r')
        srcfo.seek( self.id3v2RealSize )
        
        tmpfo.write( srcfo.read() )
        tmpfo.close()
        srcfo.close()

        # delete the srcfile
        remove(srcfile)

        # rename tmpfile to srcfile
        rename(tmpfile, srcfile)

    def writeV24() :
        print "writeV24"

    # in __init__, we will parse 10 bytes header of 2.3 and 2.4
    def __init__(self, fromfilename) :
        self.fileDIC = dict()
        self.frameIDList = ['COMM', # Comments
                            'TIT2', # Title
                            'TPE1', # Artist
                            'TPE2', # Album Artist
                            'TALB', # Album
                            'TCON', # Genre
                            'TRCK', # Track
                            'TYER', # Year
                            'TOPE', # Orig. Artist
                            'TCOM', # Composer
                            'TCOP', # Copyright
                            'WXXX', # URL
                            'TENC'] # Encoded by

        self.fileObject = file(fromfilename,'r')

        # check the ID3 Header
        if self.fileObject.read(3) != 'ID3' :
            print "This file doesn't have ID3v2 tag"
            return

        # read version info. 2 bytes
        majorVersion = unpack('b',self.fileObject.read(1))[0]
        reVersion = unpack('b',self.fileObject.read(1))[0]
        if (majorVersion == 255) or (reVersion == 255) : 
            print "This file doesn't have ID3v2 tag"
            return

        # read flags. 1byte        
        headerFlags = unpack( 'b' , self.fileObject.read(1) )[0]

        # classify flags
        unsyncFlagOfHeader = headerFlags & 128
        if unsyncFlagOfHeader == 0 :
            print "no unsync"
            
        EHFlagOfHeader = headerFlags & 64
        if EHFlagOfHeader == 0 :
            print "no extendedHeader"


#        for x in range(0,4) :
#            if unpack('b' , self.fileObject.read(1))[0] > 96 :
#                # wrong header
#                return

        # get the Header Size
        # read size(4 bytes) as big-endian from file
        sizeByte = unpack( '>i' , self.fileObject.read(4) )[0]
        # convert syncfsafe to realsize
        self.id3v2RealSize = (sizeByte & 255 ) + ( ( sizeByte & 65280 ) >> 1 ) + ( ( sizeByte & 16711680 ) >> 2 ) + ( ( sizeByte & 4278190080 ) >> 3 )
        print 'size in header : ' , self.id3v2RealSize
        
        # Read Extended header. if it exist
        # almost MP3 doesn't have Extended header. so.. skip ^^
        if EHFlagOfHeader > 0 :
            f.read(10)

        if majorVersion == 3 :
            self.readV23()
        elif majorVersion == 4 :
            self.readV24()
        else :
            print "This file is not MP3"
            return

        self.fileObject.close()


def main():
    gtk.main()
    return 0

if __name__ == '__main__' :
    if len(sys.argv) == 1  :
	sys.argv.append("/home/fat32/Music/Abba - Dancing Queen.mp3")
    MW = mainWindow()
    main()
