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

Report this snippet  

You need to login to post a comment.