DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world
Scarf_song_titles.py
This prints a list of songs from the iTunes db based on search terms
that you place inside the program for each run. Crude, I know...
Works fine, though.
Requires python3.1
#!/usr/bin/env python3.1
# scarf_song_titles.py
# rev 1 (rev 0 lives at http://snippets.dzone.com/user/paul618)
# written just for fun, by xlforum.net/paul618 AKA L3P7ON
# PM me on xlforum.net with bugs or suggestions
# Q:: Isn"t this cheating?
# A:: Not if everybody was using it.
# This runs on python3.1 on any platform you can imagine.
# Tested on a Mac (v. 10.6.3)
# the paths defined in this section might be different on a PC or Gnu/Linux
# To run this on a Mac, Gnu/Linux or PC:
# 0) uncomment the two lines below the WARNING.
# this gives the program PERMISSION to read your db and write a datafile
# 1) download python3.1
# 2) paste this program into a file called scarf_song_titles.py
# 3) fire up IDLE at Applications/Python 3.1/IDLE
# 4) File/Open scarf_song_titles.py
# 5) put your search criteria into two spots indicated
# 5) hit F5 to Run
# 6) click in the IDLE and goto step 5
# IMPORTANT:
# USE AT YOUR OWN RISK! The author does not warrent the reliability of this program.
# IFF you will allow this program to read your iTunes_Music_Library.xml
# fix the path and uncomment the next line...
#XMLfile = "/Users/paul/Music/iTunes/*.xml"
# I have to create an ASCII-only version of that file to avoid a program error.
# IFF you will allow this program to create such a file
# fix the path and uncomment the next line...
#datafile = "/Users/paul/song_title_game_data.xml"
# remove this file after you have installed some new tunes
# so that my datafile will be re-created
# --------------------------------------------------------------------------------------------
searchstring0 = "Red" # PUT YOUR FIRST SEARCHSTRING HERE BEFORE EACH RUN; hit command-s F5
searchstring1 = "Rain" # PUT YOUR SECOND SEARCHSTRING HERE BEFORE EACH RUN; hit command-s F5
# --------------------------------------------------------------------------------------------
import re, os, sys, stat, time, struct
import glob
# you can subsitiute your own favs here
Amazons = ("Joni M", "Emmylou", "Rickie ", "Natalie", "Avril L", "Alison", "Gillian", "Cindi L"
"Bonnie R", "Flora P", "Gillian", "Maura M", "Lucinda", "Sheryl C", "Alanis", "Patti S")
# ---- subrs
def uniqify(items):
seen = set()
ret = []
for i in items:
if not i in seen:
ret.append(i)
seen.add(i)
return ret
def cleanline(L):
L = L.replace("&", "and")
i = L.rindex("<string>")
return L[i+8:-10] # trimmed
def report(data):
d = uniqify(data)
for s, t in d:
# bug may not support multiple ppl doin the same song...
print(" %s -- %s" % (s, t))
#print("site:lyrics.filestube.com %s -- %s" % (s, t))
# ---- end subr
# datafile will be the iTunes XML file cleaned of non-ASCII chars
# this is only created once, at the path defined in the preamble
if not os.path.exists(datafile):
# datafile has not been created yet
fn = glob.glob(XMLfile)[0]
if 1: print("fn = >>>%s<<<" % (fn))
buffersize = os.stat(fn)[stat.ST_SIZE]
print("Your XML db is %d bytes.\nCreating %s.\nProcessing 160 songs per second...." % (buffersize, datafile))
buffersize *= 1.1 # do I need this?
buffersize = int(buffersize)
# read
with open(fn, 'rb', buffersize) as fh0:
red_data = fh0.read()
fh0.close()
# write
fh1 = open(datafile, "wb")
for byte in red_data:
# delete non-ASCII chars
if -128 <= byte <= 127:
c = struct.pack('b', byte)
fh1.write(c)
fh1.close()
time.sleep(.05) # let it close
# ---- main
dolls = []
guys = []
title = "" # need this binding here
toggle = True
pattern0 = "<key>Name</key>"
pattern1 = "<key>Artist</key>"
q_pattern = "<key>Playlists</key>"
print("Searching %s. This will take a minute..." % (datafile))
file = open(datafile, "r")
for line in file.readlines():
mo2 = re.search(searchstring0, line) #, flags=re.IGNORECASE) you want it to match case
mo3 = re.search(searchstring1, line) #, flags=re.IGNORECASE)
mo0 = re.search(pattern0, line) # Title
mo1 = re.search(pattern1, line) # Artist
mo4 = re.search(q_pattern, line) # quit before examining Playlists
if mo4:
continue # lookin at Playlists, which are past the data of interest
if mo0 and (mo2 or mo3):
# collect song title
title = cleanline(line)
toggle = True # prepare to print the Artist
if mo1 and toggle:
if 0: print("I see an Artist for %s" % (title))
# collect artist
artist = cleanline(line)
if 0: print(" %s --> %s " % (title, artist))
flag = False
for gf in Amazons:
if artist.startswith(gf):
if 0: print("I see an Amazon: %s -- %s" % (title, artist))
dolls.append((title, artist))
if 0: print("I see somebody: %s -- %s" % (title, artist))
# for/else!!!!!!!!!!!!!! my first one ever. woohoo!!!!!!!!!!!!!!
else:
guys.append((title, artist))
toggle = False
print("----")
print("---- Amazons:")
print("----")
dolls.sort()
report(dolls)
print("----")
print("---- everybody else:")
print("----")
guys.sort()
report(guys)
print("---- done.")
# ----
# ----
mail = '''
>
> How do I write binary data to a file?
> I can open a file with 'wb' as mode but if I do:
>
> b = open('bin.dat','wb')
> for i in range(50): b.write(i)
>
> I get an error.
This is an error because the write method can only output a string.
Strings in Python are not strictly 7-bit characters, but 8-bit bytes.
So you can use the struct module to convert Python data into binary
strings, which can then be written to the file.
>>> import struct
>>> binfile = open('bin.dat', 'wb')
>>> for num in range(50):
... data = struct.pack('i', num)
... binfile.write(data)
...
>>> binfile = open('bin.dat', 'rb')
>>> intsize = struct.calcsize('i')
>>> while 1:
>>> data = binfile.read(intsize)
... if data == '':
... break
... num = struct.unpack('i', data)
... print num
'''
typical_record = '''
<key>2056</key>
<dict>
<key>Track ID</key><integer>2056</integer>
<key>Name</key><string>Ornithology</string>
<key>Artist</key><string>Charlie Parker</string>
<key>Composer</key><string>Parker, C. - Harris, B.</string>
<key>Album</key><string>Ken Burns Jazz</string>
<key>Genre</key><string>Jazz</string>
<key>Kind</key><string>AAC audio file</string>
<key>Size</key><integer>2892331</integer>
<key>Total Time</key><integer>181026</integer>
<key>Track Number</key><integer>7</integer>
<key>Track Count</key><integer>16</integer>
<key>Year</key><integer>2000</integer>
<key>Date Modified</key><date>2008-06-06T20:07:06Z</date>
<key>Date Added</key><date>2007-03-01T21:59:06Z</date>
<key>Bit Rate</key><integer>128</integer>
<key>Sample Rate</key><integer>44100</integer>
<key>Play Count</key><integer>3</integer>
<key>Play Date</key><integer>3350641115</integer>
<key>Play Date UTC</key><date>2010-03-05T17:38:35Z</date>
<key>Persistent ID</key><string>4BA3750063A2DDFC</string>
<key>Track Type</key><string>File</string>
<key>File Type</key><integer>1295270176</integer>
<key>Location</key><string>file://localhost/Users/paul/Music/iTunes/iTunes%20Music/Unknown%20Artist/Unknown%20Album/07%20Track%2007.m4a</string>
<key>File Folder Count</key><integer>4</integer>
<key>Library Folder Count</key><integer>1</integer>
</dict>
'''





