Posted By

illuzian on 12/04/10


Tagged

playlist xspf m3u resolver


Versions (?)

xspf2m3u.py


 / Published in: Python
 

URL: http://hostzen.com.au/downloads/xspf2m3u.py

  1. #!/usr/bin/env python
  2. #This file is part of xspf2m3u
  3. #Creator: Anthony Hawkes
  4. #Created On: 3/12/2010
  5. #Last Modified:
  6. #Last Modified By:
  7. #xspf2m3u is free software: you can redistribute it and/or modify
  8. #it under the terms of the GNU General Public License as published by
  9. #the Free Software Foundation, either version 3 of the License, or
  10. #(at your option) any later version.
  11. #xspf2m3u is distributed in the hope that it will be useful,
  12. #but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. #GNU General Public License for more details.
  15. #See <http://www.gnu.org/licenses/>
  16. from mutagen.easyid3 import EasyID3
  17. from BeautifulSoup import BeautifulStoneSoup
  18. import os,sys,getopt,sqlite3,xml,re
  19. database = ("./musicdb.sqlite")
  20. m3u_file = ("./xspf.m3u")
  21. media = ['.mp3']
  22. write_to_m3u = []
  23. verbose = 0
  24. def main(argv):
  25. """Main program"""
  26. global m3u_file, verbose
  27. try:
  28. opts, args = getopt.getopt(argv, "hb:x:m:v", ["help","build=","xspf=","m3u=",'verbose'])
  29. except getopt.GetoptError:
  30. usage()
  31. sys.exit(2)
  32. for opt, arg in opts:
  33. if opt in ("-h", "--help"):
  34. usage()
  35. sys.exit(2)
  36. elif opt in ("-b", "--build"):
  37. builddb(arg)
  38. sys.exit(0)
  39. elif opt in ("-m", "--m3u"):
  40. m3u_file = arg
  41. elif opt in ("-x", "--xspf"):
  42. xspf = arg
  43. if not os.path.exists(xspf):
  44. print
  45. print "***xspf not found***"
  46. print
  47. usage()
  48. sys.exit(2)
  49. elif opt in ("-v", "--verbose"):
  50. verbose = 1
  51. try:
  52. xspf
  53. except NameError:
  54. print
  55. print "***No XSPF file specified***"
  56. print
  57. usage()
  58. sys.exit(2)
  59. no_db = not os.path.exists(database)
  60. if no_db:
  61. print
  62. print "***DB does not exist, try build with -b***"
  63. print
  64. usage()
  65. sys.exit(1)
  66. connection = sqlite3.connect(database)
  67. process_xspf(xspf, connection)
  68. write_m3u(write_to_m3u, m3u_file)
  69. def builddb(music_path):
  70. """This kicks off building the database, other subroutines called in order are: addtodb"""
  71. global database
  72. connection = connectdb(database)
  73. print "Now building DB this may take some time..."
  74. for dirpath, dirnames, filenames in os.walk(music_path):
  75. for file in filenames:
  76. if os.path.splitext(file)[1] in media:
  77. filename_path = os.path.join(dirpath, file)
  78. info = EasyID3(filename_path)
  79. artist = info['artist'][0]
  80. title = info['title'][0]
  81. addtodb(filename_path, artist, title, connection)
  82.  
  83. def addtodb(filename_path, artist, title, db):
  84. """This file adds data to the database in see sub connectdb for structure and details. Other subroutines claled in order are: None"""
  85. if verbose:
  86. print "Adding ", filename_path, artist, title, "to db"
  87. cursor = db.cursor()
  88. cursor.execute("INSERT INTO lib (path, artist, title) VALUES(?, ?, ?)", (filename_path, artist, title))
  89. db.commit()
  90. def connectdb(db):
  91. """This is a BUILD DB subroutine only - it is desinged to purge db if exists or create if not exists"""
  92. create = not os.path.exists(db)
  93. db = sqlite3.connect(db)
  94. db.text_factory = str
  95. if create:
  96. cursor = db.cursor()
  97. cursor.execute("CREATE TABLE lib ("
  98. "id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, "
  99. "path TEXT UNIQUE NOT NULL, "
  100. "artist TEXT, "
  101. "title TEXT)")
  102. db.commit()
  103. else:
  104. cursor = db.cursor()
  105. cursor.execute("DELETE FROM lib")
  106. cursor.execute("VACUUM")
  107. db.commit()
  108. return db
  109. def process_xspf(xspf, db):
  110. """This reads the xspf file"""
  111. soup = BeautifulStoneSoup(open(xspf).read())
  112. for trk in soup.findAll('track'):
  113. title = trk.title.string
  114. artist = trk.creator.string
  115. do_find(artist, title, db)
  116. def do_find(artist, title, db):
  117. """This does the find on the database and adds path to the list of paths to be appened to the m3u"""
  118. global write_to_m3u
  119. a = re.sub( r"[^A-Za-z0-9]",'%',artist)
  120. t = re.sub( r"[^A-Za-z0-9]",'%',title)
  121. #db = sqlite3.connect(db)
  122. db.text_factory = str
  123. cursor = db.cursor()
  124. #query = "SELECT path FROM lib WHERE artist LIKE '"+a+"' AND title LIKE '"+t+"' LIMIT 1"
  125. #print query
  126. cursor.execute("SELECT path FROM lib WHERE artist LIKE ? AND title LIKE ? LIMIT 1",(a, t))
  127. try:
  128. path = cursor.fetchone()[0]
  129. if verbose:
  130. print artist, title, "Found adding to m3u"
  131. write_to_m3u.append(path)
  132. except:
  133. if verbose:
  134. print artist, title, "Not Found"
  135. else:
  136. pass
  137. def write_m3u(contents, filename):
  138. """This actually writes the m3u file"""
  139. handle = open(filename, 'w')
  140. for line in contents:
  141. print >> handle, line
  142. def usage():
  143. """The funky usage"""
  144. print """Usage: xspf2m3u [OPTIONS]
  145.  
  146. Tries to convert a XSPF file to a local format
  147. eg. xspf -x xspf_file.xspf -m m3u_file_to_create.m3u
  148.  
  149. Notes:
  150. -Processes MP3 only.
  151. -Will ignore special characters eg.
  152. If the xspf contains: Marcel Woods - Advanced(Original Mix) this
  153. will also match to Marcel Woods - Advanced - Original Mix,
  154. this feature is useful for Beatport and other site users.
  155.  
  156. Options:
  157. -b, --buid=[MUSIC DB LOCATION] Builds the music database
  158. -v, --verbose Outputs everything loudly
  159. -h, --help Shows this...
  160. -x, --xspf=[XSPF FILENAME] Use to specific the xspf file to process
  161. -m, --m3u=[M3U FILE TO CREATE] Use this to specific m3u filename
  162. Optional - defaults to ./xspf.m3u
  163.  
  164. Make sure you build your database first with xspf2m3u -b
  165. """
  166. #call the main sub
  167. main(sys.argv[1:])

Report this snippet  

You need to login to post a comment.