All pastes #621626 Raw Edit

uPod investigator

public python v1 · immutable
#621626 ·published 2007-07-16 09:19 UTC
rendered paste body
import ID3import sysimport osimport os.pathimport wximport shutildef gen_ipod_structure(path_root = "E:\\"):    ''' Returns the path on an iPod where music should reside'''    return path_root + 'iPod_Control\\Music\\'def parse_ipod_structure(path):    ''' Takes a path to an iPod-type iPod_control directory (really any directory    with a bunch of mp3 files or subdirectories with mp3 files) and returns    a list of tuples (ID3_tags_dict, path_to_music_file) '''    tagged_critters = []    untaggable_critters = []    for root, dirs, files in os.walk(path):        for music_file in files:            file_path = root + '\\' + music_file            try:                #keeping the ID3 object around keeps the file open                tags = ID3.ID3(file_path).as_dict()                tagged_critters.append((tags, file_path))            except ID3.InvalidTagError, message:                untaggable_critters.append(file_path)    return tagged_critters, untaggable_crittersclass ipod_explorer_frame(wx.Frame):    columns = {0: ("Track Title", 'TITLE'), 1: ("Artist", "ARTIST"), 2: ("Album", "ALBUM")}    ID_NEW_DRIVE = 101    ID_RIP = 102    def __init__(self):        global parse_ipod_structure, gen_ipod_structure                wx.Frame.__init__(self, None, 100, 'uPod Investigator', size=wx.Size(600, 600))        self.sz = wx.BoxSizer(wx.VERTICAL)                       #        # Set up ListControl to show track info        #        self.lc = wx.ListCtrl(self, -1, style=wx.LC_REPORT, size=wx.Size(590, 500))        for i in self.columns:            self.lc.InsertColumn(i, self.columns[i][0])            self.lc.SetColumnWidth(i, 570 / len(self.columns))                #        # Start with our first iPod        #        self.new_drive()        #        # Create Menu Bar        #        menubar = wx.MenuBar()        file = wx.Menu()        edit = wx.Menu()                #        # Construct File menu        #        file.Append(self.ID_NEW_DRIVE, '&Open new iPod\tCTRL-O')        file.Append(self.ID_RIP, '&Rip my unlicensed music!\tCTRL-R')        file.AppendSeparator()        file.Append(wx.ID_EXIT, 'E&xit\tCTRL-Q')                self.Connect(wx.ID_EXIT, -1, wx.wxEVT_COMMAND_MENU_SELECTED, self.on_exit)        self.Connect(self.ID_NEW_DRIVE, -1, wx.wxEVT_COMMAND_MENU_SELECTED, self.new_drive)        self.Connect(self.ID_RIP, -1, wx.wxEVT_COMMAND_MENU_SELECTED, self.do_rip)                menubar.Append(file, '&File')        self.SetMenuBar(menubar)        self.txt = wx.StaticText(self, -1, 'Select as many songs as you want from the list (CTRL for multiple), then go to file -> rip', style=wx.ALIGN_CENTER)        self.sz.Add(self.txt)        self.sz.Add(self.lc, wx.EXPAND)        self.lc.Fit()        self.sz.Fit(self)        self.SetBackgroundColour(wx.WHITE)        self.SetSizer(self.sz)        self.Center()        self.Show()            def new_drive(self, *args):        ''' Starts the app (over) with a new iPod. '''        root_dir = self.pick_drive_letter()                #        # Load all songs with ID3 tags in %(root_dir)s/iPod_Control/*/        #        struct = gen_ipod_structure(root_dir)        songs = parse_ipod_structure(struct)[0]        # Eliminate songs that don't have proper ID3 tags        songs = [i for i in songs if i[0].has_key('TITLE')]        self.songs = songs        self.load_song_list()            def pick_drive_letter(self):        ''' Prompts the user for their iPod's drive letter '''        root_dir = None        while root_dir is None or not os.path.exists(root_dir + '\\iPod_Control\\Music\\'):            if root_dir is not None:                title = "Previous selection has no iPod_Control directory"            else:                title = "Select your iPod's drive letter"            root = wx.DirDialog(self, title, "/", style=wx.EXPAND)            root.ShowModal()            root_dir = root.GetPath()        return root_dir            def on_exit(self, *args):        self.Close(True)            def load_song_list(self, sortby='TITLE'):        ''' Reloads the song list from self.songs '''        self.lc.DeleteAllItems()                self.sort_list(sortby)                for i, tup in enumerate(self.songs):            song, file = tup            self.insert_row(song, file, i)            def insert_row(self, song, file, index):        ''' Inserts a row into the ListCtrl, accounting for which columns        we want to use (modify self.columns) '''        last = self.lc.GetItemCount()        self.lc.InsertStringItem(last, song.get(self.columns[0][1],'N/A'))        #self.lc.SetStringItem(last, 1, song.get('ARTIST','N/A'))        for i in self.columns:            if i != 0:                self.lc.SetStringItem(last, i, song.get(self.columns[i][1],'N/A'))        self.lc.SetItemData(last, index)            def do_rip(self, *args):        ''' Walks the user through ripping their music to their computer'''        to_rip = self.selected_songs()        dest_dir = wx.DirDialog(self, 'Where do you want to rip to?', '/')        dest_dir.ShowModal()        dest_dir = dest_dir.GetPath()                for song,file in to_rip:            # Give each artist their own dir            new_name = dest_dir + '\\%(ARTIST)s\\%(ALBUM)s\\%(TITLE)s.' % song            # and add a file extension            new_name += file.split('.')[-1]                        print 'COPYING %s -> %s...' % (file, new_name),            try:                head, tail = os.path.split(new_name)                if not os.path.exists(head):                    os.makedirs(head)                                shutil.copy(file, new_name)                print 'DONE.'            except Exception, e:                print 'ERROR!', e            def selected_songs(self):        ''' Returns all the songs currently selected on the ListCtrl'''        songs = []        max = self.lc.GetItemCount()        i = self.lc.GetNextSelected(-1)        while i < max and i != -1:            songs.append(self.songs[i])            i = self.lc.GetNextSelected(i)        return songs        def sort_list(self, by = 'ARTIST'):        ''' Sorts the list by a particular dictionary key '''        def cmp_titles(x,y):            x = x[0].get(by, 0)            y = y[0].get(by, 0)            if x < y:                return -1            elif x == y:                return 0            return 1        self.songs.sort(cmp_titles)app = wx.App(redirect=False)frame = ipod_explorer_frame()app.MainLoop()