-
Notifications
You must be signed in to change notification settings - Fork 3
/
repod.py
executable file
·179 lines (144 loc) · 4.57 KB
/
repod.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
176
177
178
179
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import eyed3
import os
import sqlite3 as sl
import shutil
eyed3.require("0.7")
pod = '/media/ipod-backup'
dst = '/media/ipod-music-export'
dbf = '%s/iTunes_Control/iTunes/MediaLibrary.sqlitedb' % pod
print '>>> using database file %s' % dbf
con = sl.connect(dbf)
cur = con.cursor()
cur.execute('SELECT SQLITE_VERSION()')
data = cur.fetchone()
print 'SQLite version: %s' % data
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
con.row_factory = dict_factory
con.text_factory = str
cur = con.cursor()
sql = """
SELECT
a.album AS album
, aa.album_artist AS artist
, g.genre AS genre
, ie.YEAR AS year
, lk.kind AS kind
, i.disc_number AS disc_number
, i.track_number AS track_number
, ie.title AS title
, bl.path AS path
, ie.location AS location
, st.user_rating AS user_rating
, st.play_count_user AS play_count
FROM
item i
, album a
, album_artist aa
, genre g
, item_extra ie
, location_kind lk
, base_location bl
, item_stats st
WHERE 1
AND i.album_pid = a.album_pid
AND i.album_artist_pid = aa.album_artist_pid
AND i.genre_id = g.genre_id
AND i.item_pid = ie.item_pid
AND i.location_kind_id = lk.location_kind_id
AND i.base_location_id = bl.base_location_id
AND i.item_pid = st.item_pid
ORDER BY
artist ASC
, year ASC
, album ASC
, disc_number ASC
, track_number ASC
"""
# get all items, skip some, cleanup others
cur.execute(sql)
rows = cur.fetchall()
keep = []
for row in rows:
if row['path'] == '':
continue
if row['location'] == '':
continue
if row['artist'] == '':
row['artist'] = 'unknown'
if row['album'] == '':
row['album'] = 'unknown'
if row['title'] == '':
row['title'] = 'unknown'
row['artist'] = row['artist'].strip().replace('/', '-')
row['album' ] = row['album' ].strip().replace('/', '-')
row['title' ] = row['title' ].strip().replace('/', '-')
keep.append(row)
#print "{path}/{location} ({user_rating: 3d}) => {artist}/{year:04d} - {album}/CD{disc_number}/{track_number:02} - {title}.{filetype}".format( **row )
print '>>> total %d files (%d filtered)' % (len(keep), len(rows) - len(keep))
con.close()
# remove files if they already exist
shutil.rmtree(dst)
# go trough all files and
count = 0
total = len(keep)
for row in keep:
count += 1
row['podDir'] = pod
row['dstDir'] = dst
row['filetype'] = row['location'].split('.')[1]
srcFile = "{podDir}/{path}/{location}".format( **row )
dstDir = "{dstDir}/{artist}/{year:04d} - {album}/CD{disc_number}".format( **row )
dstFile = dstDir + "/{track_number:02} - {title}.{filetype}".format( **row )
if not os.path.isfile(srcFile):
continue
print "[ % 7d / % 7d ] %s (%3d) => %s" % (count, total, srcFile, row['user_rating'], dstFile)
if not os.path.isdir(dstDir):
os.makedirs(dstDir)
shutil.copyfile(srcFile, dstFile)
try:
mp3 = eyed3.load(dstFile)
except BaseException as error:
print '>>> Error processing file'
continue
if mp3 is None or mp3.tag == None:
print '>>> skipping file because not an mp3'
continue
# get rid of all comments
for c in mp3.tag.comments:
mp3.tag.comments.remove(c.description)
# stupid unicode
mp3.tag.album = u'%s' % row['album' ].decode('UTF-8')
mp3.tag.artist = u'%s' % row['artist'].decode('UTF-8')
mp3.tag.title = u'%s' % row['title' ].decode('UTF-8')
# handle genre, which might be missing
genre = u'%s' % row['genre'].decode('UTF-8')
if mp3.tag.genre is None:
mp3.tag.genre = eyed3.id3.Genre(genre)
else:
mp3.tag.genre.name = genre
# some simple numbers
mp3.tag.disc_num = row['disc_number']
mp3.tag.play_count = row['play_count']
# requires a tuple of track# and totalcount
mp3.tag.track_num = (row['track_number'], None)
# it appears 0 is not valid as a year, haven't tested negative values ;)
if row['year'] > 0:
mp3.tag.release_date = eyed3.core.Date(row['year'])
mp3.tag.recording_date = eyed3.core.Date(row['year'])
# not sure if the popularimeter stuff works as intended
for p in mp3.tag.popularities:
mp3.tag.popularities.remove(p.email)
rating = int(2.55 * int(row['user_rating']))
mp3.tag.popularities.set('rating@mp3.com', rating, row['play_count'])
# it seems some frames can't be converted to v2.4
for name in ('TYER', 'RGAD', 'RVAD', 'TSO2'):
if name in mp3.tag.frame_set:
del mp3.tag.frame_set[name]
# commit
mp3.tag.save(version = eyed3.id3.ID3_V2_4)