]> code.delx.au - monosys/commitdiff
Mythtv music importer
authorJames Bunton <jamesbunton@fastmail.fm>
Fri, 14 Mar 2008 13:09:04 +0000 (00:09 +1100)
committerJames Bunton <jamesbunton@fastmail.fm>
Fri, 14 Mar 2008 13:09:04 +0000 (00:09 +1100)
mythtv/mythmusic_importm3u.py [new file with mode: 0755]

diff --git a/mythtv/mythmusic_importm3u.py b/mythtv/mythmusic_importm3u.py
new file mode 100755 (executable)
index 0000000..2c5102b
--- /dev/null
@@ -0,0 +1,171 @@
+#!/usr/bin/env python
+
+# This script reads in m3u playlists and inserts them into the mythtv database
+
+# Copyright 2008 James Bunton <jamesbunton@fastmail.fm>
+# Licensed for distribution under the GPL version 2
+
+# Copyright 2005 Patrick Riley (http://pathacks.blogspot.com/). You are
+# free to use and modify this code as you see fit, but it comes with
+# no warranty whatsoever.
+
+
+import logging, optparse, os.path, re, sys
+
+import MySQLdb
+
+class PlaylistBuilder(object):
+       findPlaylistQuery = """
+               SELECT playlist_id
+               FROM music_playlists
+               WHERE playlist_name = %s
+       """
+       findItemQuery = """
+               SELECT song.song_id
+               FROM music_directories dir JOIN music_songs song ON dir.directory_id = song.directory_id
+               WHERE concat(dir.path, '/', song.filename) = %s
+       """
+       insertPlaylistQuery = """
+               INSERT INTO
+               music_playlists(playlist_name, playlist_songs)
+               VALUES(%s, %s)
+       """
+       updatePlaylistQuery = """
+               UPDATE music_playlists
+               SET playlist_songs = %s
+               WHERE playlist_id = %s
+       """
+
+       def __init__(self, dbHost, dbUser, dbPassword, dbName="mythconverg"):
+               self.dbconnection = MySQLdb.connect(db=dbName, host=dbHost, user=dbUser, passwd=dbPassword)
+               self.cursor = self.dbconnection.cursor()
+               
+       def startPlaylist(self, name):
+               self.playlistName = name
+               self.playlistId = -1
+               self.cursor.execute(self.findPlaylistQuery, [self.playlistName])
+               if self.cursor.rowcount < 0:
+                       raise ValueError("rowcount < 0?")
+               elif self.cursor.rowcount > 0:
+                       assert self.cursor.rowcount == 1, "More than one playlist with the same name?"
+                       self.playlistId = self.cursor.fetchone()[0]
+               self.ids = []
+
+       def addFile(self, filename):
+               self.cursor.execute(self.findItemQuery, [filename])
+               if self.cursor.rowcount != 1:
+                       logging.warning("Did not find an entry for '%s' (return=%d)" % (filename, self.cursor.rowcount))
+                       return
+               self.ids.append("%d" % self.cursor.fetchone()[0])
+
+       def finishPlaylist(self):
+               idsString = ",".join(self.ids)    
+               logging.info("Playlist '%s' is: %s" % (self.playlistName, idsString))
+               if self.playlistId < 0:
+                       self.cursor.execute(self.insertPlaylistQuery, [self.playlistName, idsString])
+               else:
+                       self.cursor.execute(self.updatePlaylistQuery, [idsString, self.playlistId])
+               # We can't check the rowcount here because update will say 0 if no values actually changed
+               # assert cursor.rowcount == 1, "Insert/update failed? %d" % (playlistId)
+
+
+def stripComments(it):
+       re_comment = re.compile(r"^\s*#")
+       re_all_whitespace = re.compile(r"^\s*$")
+
+       for line in it:
+               if re_comment.match(line):
+                       continue
+               if re_all_whitespace.match(line):
+                       continue
+               line = line.strip()
+               yield line
+
+
+def readMysqlTxt(filename, vars):
+       for line in stripComments(open(filename)):
+               try:
+                       key, value = line.split("=")
+               except:
+                       logging.warning("Couldn't parse mysql.txt line -- %s" % line)
+               vars[key.lower().strip()] = value.strip()
+
+def readArgs(vars):
+       parser = optparse.OptionParser(usage="""%prog [options] Playlist.m3u [Another.m3u] ...
+
+Converts m3u style playlists into playlists for MythTV
+
+A m3u file is a list of filenames where # begins comments. This script
+makes one playlist for each m3u file you give it (stripping the extention
+from the filename to get the playlist name)
+                       
+This script works by connecting to your MythTV MySQL database and querying
+for the filenames found in the .m3u file.
+
+The database connection settings will be read from the .mythtv/mysql.txt
+file if possible, otherwise specify them on the command line.
+       """)
+       parser.add_option("--dbhost", help="MythTV database host to connect to",
+                       action="store", dest="host", default=vars["dbhostname"])
+       parser.add_option("--dbuser", help="MythTV database username",
+                       action="store", dest="user", default=vars["dbusername"])
+       parser.add_option("--dbpassword", help="MythTV database password",
+                       action="store", dest="password", default=vars["dbpassword"])
+       parser.add_option("--dbname", help="MythTV database name",
+                       action="store", dest="database", default=vars["dbname"])
+       parser.add_option("--strip", help="Number of directories to strip from the start of each file in the playlists",
+                       action="store", type="int", dest="stripn", default=0)
+       parser.add_option("-v", "--verbose", help="Be verbose",
+                       action="store_true", dest="verbose")
+
+       options, filenames = parser.parse_args()
+       vars["dbhostname"] = options.host
+       vars["dbusername"] = options.user
+       vars["dbpassword"] = options.password
+       vars["dbname"] = options.database
+       vars["strip"] = options.stripn
+       if options.verbose:
+               logging.basicConfig(level=logging.INFO)
+       else:
+               logging.basicConfig(level=logging.WARNING)
+       
+       return filenames
+
+
+def main():
+       vars = {
+               "dbhostname": "localhost",
+               "dbusername": "mythtv",
+               "dbpassword": "mythtv",
+               "dbname": "mythconverg",
+       }
+
+       found = False
+       for path in ["~/.mythtv/mysql.txt", "~mythtv/.mythtv/mysql.txt", "/etc/mythtv/mysql.txt"]:
+               try:
+                       readMysqlTxt(os.path.expanduser(path), vars)
+                       found = True
+                       break
+               except IOError:
+                       continue
+       filenames = readArgs(vars)
+       if not found:
+               logging.warning("Could not read mysql.txt, try running as the mythtv user.")
+
+       strip = vars["strip"]
+       builder = PlaylistBuilder(vars["dbhostname"], vars["dbusername"], vars["dbpassword"], vars["dbname"])
+       for filename in filenames:
+               playlistName = os.path.basename(filename)
+               playlistName = playlistName.rsplit(".", 1)[0]
+               logging.info("Processing '%s' as playlist '%s'" % (filename, playlistName))
+
+               builder.startPlaylist(playlistName)
+               for line in stripComments(open(filename)):
+                       line = line.split(os.path.sep, strip)[-1]
+                       builder.addFile(line)
+               builder.finishPlaylist()
+
+
+if __name__ == '__main__':
+  main()
+