Recent Changes - Search:

Bob Brandt

Linux Projects


Server Projects

Desktop Projects

Novell Projects


VMware Projects


N900 (Maemo) Projects


Python Projects


OpenOffice.org Projects


Other Projects


PmWiki

edit SideBar

Playlist Sync

N900.PlaylistSync History

Hide minor edits - Show changes to markup

March 12, 2010, at 03:03 PM by 137.191.238.232 -
Added lines 9-10:

This is a work in progress so nothing is guaranteed! Right now I am using my Wiki as a means of transferring code between different sites.

March 10, 2010, at 03:48 PM by 137.191.238.232 -
Added lines 1-201:

(:title Playlist Sync:)

While the N900 is AWESOME, it is really new and some things are just not quite perfect yet! One of these things is the playlist editor for the default Media Player. That is to say that there ISN'T a playlist editor!!

Now my computer at home has an many, many great playlist editors... So why not use them??

This program will sync playlists between your N900 and your home machine. (Actually it will sync playlists between any two machines)

(:div style="border-style:ridge; border-width:2px; background-color:#ffffcc; margin-left:50px; overflow:auto; font-size:small; width:650px; height:500px;":)


#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
    PlaylistSync by Bob Brandt (projects@brandt.ie).
    Licensed under GPL version 3
    Created on 10 March 2010
"""  
import sys, os, optparse, re
version = "0.1"

class playlistsync(object):
    '''
    This class is used to sync a playlist from one device to another and all relevant files
    '''

    def __init__(self, sourceRoot, destMountPoint, destRoot = None, hierarchical = False, debug = False):
        if os.path.isdir(sourceRoot):
            self.__sourceRoot = sourceRoot
        else:
            raise IOError, "There is no such directory: '%s'" % sourceRoot
        if os.path.isdir(destMountPoint):
            self.__destMountPoint = destMountPoint
        else:
            raise IOError, "There is no such directory: '%s'" % destMountPoint     
        if not destRoot: destRoot = destMountPoint
        self.__destRoot = destRoot
        self.__hierarchical = bool(hierarchical)
        self.__sourcePlaylists = self.__loadplaylists(self.__sourceRoot)
        self.__destPlaylists = self.__loadplaylists(self.__destMountPoint)
        self.__playlists = {}
        for playlist in self.__sourcePlaylists.keys():
            if playlist in self.__destPlaylists.keys():
                self.__playlists[playlist] = {"source":self.__sourcePlaylists[playlist], "dest":self.__destPlaylists[playlist]}


    playlistextenstions = property(lambda self: (".m3u",".pls") )
    sourcePlaylists = property(lambda self: self.__sourcePlaylists )
    destPlaylists = property(lambda self: self.__destPlaylists )
    playlists = property(lambda self: self.__playlists )

    def __loadplaylists(self, root):
        playlists = {}
        def checknames(junk, dirpath, namelist):
            for name in namelist:
                if os.path.splitext(name)[1].lower() in self.playlistextenstions:
                    playlists[os.path.splitext(name)[0].lower()] = os.path.join(dirpath,name)
        os.path.walk(root, checknames, None)
        return playlists

    def __isInPlaylist(self, Playlist, PlayLists):
        Playlist = str(Playlist).lower()
        if Playlist in PlayLists.keys():
            return {"name":Playlist, "path":PlayLists[Playlist] }
        for tmp in PlayLists.keys():
            if Playlist == str(PlayLists[tmp]).lower():
                return {"name":Playlist, "path":PlayLists[tmp] }
        return None

    def addPlaylist(self, Playlist):
        tmpPlaylist = str(Playlist).lower()
        path = ""
        if self.__isInPlaylist(tmpPlaylist, self.__playlists):
            raise ValueError, "%s is already being synced." % Playlist
        self.__convertplaylist(tmpPlaylist)

    def __convertplaylist(self, Playlist):
        if not self.__isInPlaylist(Playlist, self.__sourcePlaylists):
            raise IOError, "There is no such playlist: '%s' underneath: %s" % ( Playlist , self.__sourceRoot )  

        f = open(self.__isInPlaylist(Playlist, self.__sourcePlaylists)["path"], "r")
        playlisttext = f.read()
        f.close()

        pathseperator = os.path.normpath("/")
        extension = os.path.splitext(self.__isInPlaylist(Playlist, self.__sourcePlaylists)["path"])[1].lower()
        if extension == ".m3u" and self.__hierarchical:
            search = re.compile("^" + self.__sourceRoot + pathseperator, re.IGNORECASE | re.MULTILINE | re.UNICODE)
            replace = self.__destRoot + pathseperator
        elif extension == ".m3u" and not self.__hierarchical:
            search = re.compile("^" + self.__sourceRoot + ".*" + pathseperator, re.IGNORECASE | re.MULTILINE | re.UNICODE)
            replace = self.__destRoot + pathseperator
        elif extension == ".pls" and self.__hierarchical:
            search = re.compile("=" + self.__sourceRoot + pathseperator, re.IGNORECASE | re.MULTILINE | re.UNICODE)
            replace = "=" + self.__destRoot + pathseperator
        elif extension == ".pls" and not self.__hierarchical:
            search = re.compile("=" + self.__sourceRoot + ".*" + pathseperator, re.IGNORECASE | re.MULTILINE | re.UNICODE)
            replace = "=" + self.__destRoot + pathseperator
        else:
            search = None
            replace = None

        if not (search and replace) :
            raise ValueError, "Invalid Extension or Hierarchical Setting: %s, %s" % ( str(extension), str(self.__hierarchical) )

        playlisttext = search.sub(replace, playlisttext)

        if self.__hierarchical:        
            search = re.compile("^/home/BrandtB/Desktop/playlists-orig.*" + pathseperator, re.IGNORECASE | re.MULTILINE | re.UNICODE)
        else:
            search = re.compile("^/home/BrandtB/Desktop/playlists-orig" + pathseperator, re.IGNORECASE | re.MULTILINE | re.UNICODE)
        replace = "/home/BrandtB/Desktop/playlists-dest" + pathseperator        
        filename = search.sub(replace, self.__isInPlaylist(Playlist, self.__sourcePlaylists)["path"])

        f = open(filename, "w")
        f.write(playlisttext)
        f.flush()
        f.close()

    def removePlaylist(self, Playlist):
        tmpPlaylist = str(Playlist).lower()
        path = ""
        if not self.__isInPlaylist(tmpPlaylist, self.__playlists):
            raise ValueError, "%s is not being synced." % Playlist
        os.remove(self.__destPlaylists[tmpPlaylist])

    def listPlayLists(self):
        allplaylists = {}
        for playlist in self.__sourcePlaylists.keys(): 
            allplaylists[playlist] = {"source":True, "dest":False}
        for playlist in self.__destPlaylists.keys():
            if allplaylists.has_key(playlist):
                allplaylists[playlist]["dest"] = True
            else:
                allplaylists[playlist] = {"dest":True, "source":False}

        length = 0
        for playlist in allplaylists.keys():
            if len(playlist) > length: length = len(playlist)

        print "Playlists:"
        for playlist in allplaylists.keys():
            if allplaylists[playlist]["source"] and allplaylists[playlist]["dest"]:
                print playlist + " " * (length - len(playlist)) + "\t" + "Sync"
            else:
                print playlist + " " * (length - len(playlist)) + "\t" + "Available"
        print "\n"

    def syncPlaylists(self):
        pass

    def cleanupPlaylists(self):
        pass

if __name__ == '__main__':
    usageText="usage: %prog [options] Source Destination RemotePath"
    versionText =  "\n" + " ".join(["GNU","%prog",str(version)]) + "\n"
    versionText += "This program is distributed in the hope that it will be useful,\n"
    versionText += "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
    versionText += "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
    versionText += "GNU General Public License for more details.\n\n"
    versionText += "Originally written by Bob Brandt <projects@brandt.ie>.\n"

    parser = optparse.OptionParser(usage=usageText, version=versionText)
    parser.add_option("-a", "--add", dest="add", default="", type="string", help="Add playlist to sync list.")
    parser.add_option("-r", "--remove", dest="remove", default="", type="string", help="Remove playlist from sync list.")    
    parser.add_option("-l", "--list", dest="list", action="store_true", default=False, help="List all playlists and whether or not they will be synced.")
    parser.add_option("-c", "--cleanup", dest="cleanup", action="store_true", default=False, help="Remove all media not specified in the playlists.")    
    parser.add_option("-t", "--tree",  dest="tree",  action="store_true", default=False, help="Keep tree structure when copying files.")
    parser.add_option("-d", "--debug",  dest="debug",  action="store_true", default=False, help="To run the command in Debug mode.")

    (options, args) = parser.parse_args()

#    Source = args[0]
#    Destination = args[1]
#    RemotePath = args[2]

    Source = "/home/BrandtB/Desktop/playlists-orig"
    Destination = "/home/BrandtB/Desktop/playlists-dest"
    RemotePath = "/home/user/MyDocs/Music"
    options.tree = False
    options.list = True

    temp = playlistsync(Source, Destination, RemotePath, options.tree, options.debug)

    if options.add:
        temp.addPlaylist(options.add)
    if options.remove:
        temp.removePlaylist(options.remove)
    if options.list:
        temp.listPlayLists()
    if not (options.add or options.remove or options.list or options.cleanup):
        temp.syncPlaylists()
        if options.cleanup:
            temp.cleanupPlaylists()        

sys.exit()


(:divend:)

Edit - History - Print - Recent Changes - Search
Page last modified on March 12, 2010, at 03:03 PM