2 iPod Shuffle database access
4 File format documentation:
5 - http://ipodlinux.org/ITunesDB#iTunesSD_file and further
7 Author: Artem Baguinski
10 from __future__
import with_statement
18 Field(Uint24(), 'len(tracks)'),
19 Field(Uint24(), const
= 0x010800),
20 Field(Uint24(), '%reclen%', check
= True),
22 ListField('tracks', Record([
23 Field(Uint24(), '%reclen%', check
= True),
25 Field(Uint24(), 'starttime', default
= 0),
27 Field(Uint24(), 'stoptime', default
= 0),
29 Field(Uint24(), 'volume', default
= 0x64),
30 # for the following fileds there is no sensible default
31 Field(Uint24(), 'file_type'),
33 Field(ZeroPaddedString(522, 'UTF-16-LE'), 'filename'),
34 Field(Bool8(), 'shuffleflag'),
35 Field(Bool8(), 'bookmarkflag'),
40 iTunesStats
= Record([
41 Field( Uint24(), 'len(tracks)'),
43 ListField('tracks', Record([
44 Field( Uint24(), '%reclen%', check
= True),
45 Field( Int24(), 'bookmarktime', default
= -1),
47 Field( Uint24(), 'playcount', default
= 0),
48 Field( Uint24(), 'skippedcount', default
= 0)],
52 # Here I disagree with the format from URL, but I'm not sure about nothing
53 iTunesPState
= Record([
54 Field( Uint8(), 'volume', default
= 29 ),
55 Field( Uint24(), 'shufflepos', default
= 0 ),
56 Field( Uint24(), 'trackno', default
= 0 ),
57 Field( Bool24(), 'shuffleflag', default
= False),
58 Field( Uint24(), 'trackpos', default
= 0),
63 supported_file_types
= (".mp3", ".aa", ".m4a", ".m4b", ".m4p", ".wav")
65 def write_iTunesSD(self
, tracks
):
66 with
open('iTunesSD', WRITE
) as file:
67 iTunesSD
.write(file, {'tracks':tracks
})
70 def read_iTunesSD(self
):
71 with
open('iTunesSD', READ
) as file:
72 return iTunesSD
.read(file)['tracks']
74 def write_iTunesStats(self
, tracks
):
75 with
open('iTunesStats', WRITE
) as file:
76 iTunesStats
.write(file, {'tracks':tracks
})
79 def read_iTunesStats(self
, tracks
):
80 with
open('iTunesStats', READ
) as file:
81 iTunesStats
.read(file,{'tracks':tracks
})['tracks']
83 def write_iTunesPState(self
, pstate
):
84 with
open('iTunesPState', WRITE
) as file:
85 iTunesPState
.write(file, pstate
)
88 def read_iTunesPState(self
):
89 with
open('iTunesPState', READ
) as file:
90 return iTunesPState
.read(file)
93 tracks
= self
.read_iTunesSD()
94 self
.read_iTunesStats(tracks
)
95 pstate
= self
.read_iTunesPState()
96 return (tracks
, pstate
)
98 def write_all(self
, tracks
, pstate
):
99 self
.write_iTunesSD(tracks
)
100 self
.write_iTunesStats(tracks
)
101 self
.write_iTunesPState(pstate
)
103 def set_old_tracks(self
, lst
):
105 for i
in xrange(len(lst
)):
107 self
.old_tracks
[t
['filename']] = t
108 self
.old_tracks
[i
] = t
110 def make_track_record(self
, filename
):
111 if self
.old_tracks
.has_key(filename
):
112 return self
.old_tracks
[filename
]
115 iTunesSD_track
.make_default(dict)
116 iTunesStats_track
.make_default(dict)
118 dict['filename'] = filename
119 if filename
.endswith((".mp3",".aa")):
120 dict['file_type'] = 1
121 elif filename
.endswith((".m4a", ".m4b", ".m4p")):
122 dict['file_type'] = 2
123 elif filename
.endswith(".wav"):
124 dict['file_type'] = 4
126 raise "%s: unsupported file type" % (filename
)
127 dict['bookmarkflag'] = filename
.endswith((".aa",".m4b"))
128 dict['shuffleflag'] = not dict['bookmarkflag']
131 #####################################################################
132 if __name__
== '__main__':
137 if len(sys
.argv
) > 1:
139 start_dir
= os
.getcwd()
140 os
.chdir(sys
.argv
[1])
142 tracks
, pstate
= db
.read_all()
146 if len(sys
.argv
) > 2:
149 os
.chdir(sys
.argv
[2])
150 db
.write_all(tracks
, pstate
)