-
Notifications
You must be signed in to change notification settings - Fork 0
/
play_list.py
175 lines (160 loc) · 4.89 KB
/
play_list.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
"""
playlist.py
Description: Playing with iTunes Playlists.
Author: Marc Zhao
Website: marcsteven.top
"""
import re, argparse
import sys
from matplotlib import pyplot
import plistlib
import numpy as np
def findCommonTracks(fileNames):
"""
Find common tracks in given playlist files, and save them
to common.txt.
"""
# a list of sets of track names
trackNameSets = []
for fileName in fileNames:
# create a new set
trackNames = set()
# read in playlist
plist = plistlib.readPlist(fileName)
# get the tracks
tracks = plist['Tracks']
# iterate through tracks
for trackId, track in tracks.items():
try:
# add name to set
trackNames.add(track['Name'])
except:
# ignore
pass
# add to list
trackNameSets.append(trackNames)
# get set of common tracks
commonTracks = set.intersection(*trackNameSets)
# write to file
if len(commonTracks) > 0:
f = open("common.txt", 'wb')
for val in commonTracks:
s = "%s\n" % val
f.write(s.encode("UTF-8"))
f.close()
print("%d common tracks found. "
"Track names written to common.txt." % len(commonTracks))
else:
print("No common tracks!")
def plotStats(fileName):
"""
Plot some statistics by readin track information from playlist.
"""
# read in playlist
plist = plistlib.readPlist(fileName)
# get the tracks
tracks = plist['Tracks']
# create lists of ratings and duration
ratings = []
durations = []
# iterate through tracks
for trackId, track in tracks.items():
try:
ratings.append(track['Album Rating'])
durations.append(track['Total Time'])
except:
# ignore
pass
# ensure valid data was collected
if ratings == [] or durations == []:
print("No valid Album Rating/Total Time data in %s." % fileName)
return
# cross plot
x = np.array(durations, np.int32)
# convert to minutes
x = x/60000.0
y = np.array(ratings, np.int32)
pyplot.subplot(2, 1, 1)
pyplot.plot(x, y, 'o')
pyplot.axis([0, 1.05*np.max(x), -1, 110])
pyplot.xlabel('Track duration')
pyplot.ylabel('Track rating')
# plot histogram
pyplot.subplot(2, 1, 2)
pyplot.hist(x, bins=20)
pyplot.xlabel('Track duration')
pyplot.ylabel('Count')
# show plot
pyplot.show()
def findDuplicates(fileName):
"""
Find duplicate tracks in given playlist.
"""
print('Finding duplicate tracks in %s...' % fileName)
# read in playlist
plist = plistlib.readPlist(fileName)
# get the tracks
tracks = plist['Tracks']
# create a track name dict
trackNames = {}
# iterate through tracks
for trackId, track in tracks.items():
try:
name = track['Name']
duration = track['Total Time']
# is there an entry already?
if name in trackNames:
# if name and duration matches, increment count
# duration rounded to nearest second
if duration//1000 == trackNames[name][0]//1000:
count = trackNames[name][1]
trackNames[name] = (duration, count+1)
else:
# add entry - duration and count
trackNames[name] = (duration, 1)
except:
# ignore
pass
# store duplicates as (name, count) tuples
dups = []
for k, v in trackNames.items():
if v[1] > 1:
dups.append((v[1], k))
# save dups to file
if len(dups) > 0:
print("Found %d duplicates. Track names saved to dup.txt" % len(dups))
else:
print("No duplicate tracks found!")
f = open("dups.txt", 'w')
for val in dups:
f.write("[%d] %s\n" % (val[0], val[1]))
f.close()
# Gather our code in a main() function
def main():
# create parser
descStr = """
This program analyzes playlist files (.xml) exported from iTunes.
"""
parser = argparse.ArgumentParser(description=descStr)
# add a mutually exclusive group of arguments
group = parser.add_mutually_exclusive_group()
# add expected arguments
group .add_argument('--common', nargs = '*', dest='plFiles', required=False)
group .add_argument('--stats', dest='plFile', required=False)
group .add_argument('--dup', dest='plFileD', required=False)
# parse args
args = parser.parse_args()
if args.plFiles:
# find common tracks
findCommonTracks(args.plFiles)
elif args.plFile:
# plot stats
plotStats(args.plFile)
elif args.plFileD:
# find duplicate tracks
findDuplicates(args.plFileD)
else:
print("These are not the tracks you are looking for.")
# main method
if __name__ == '__main__':
main()