#!/usr/bin/python # Copyright 2010 Lars Wirzenius # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os import re import shutil import sys import ttystatus def parse_playlist(filename): pat = re.compile(r'^File\d+=(?P.*)$') f = open(filename) for line in f: m = pat.match(line) if m: yield m.group('filename') f.close() class Playlist(object): def __init__(self, filename): self.media_filenames = list(parse_playlist(filename)) prefix = os.path.commonprefix(self.media_filenames) i = prefix.rfind('/') if i >= 0: self.dirname = prefix[:i] self.media_filenames = [x[i+1:] for x in self.media_filenames] else: self.dirname = '.' self.dirname = os.path.join(os.path.dirname(filename), self.dirname) def identical(source, target): source_st = os.lstat(source) try: target_st = os.lstat(target) except OSError: return False return source_st.st_size == target_st.st_size def cleanup(pathname): badchars = ':?*[]' for c in badchars: pathname = '_'.join(pathname.split(c)) return pathname def main(): ts = ttystatus.TerminalStatus() target_dir = '/media/Nokia N900/music' playlists = [] ts['done'] = 0 ts['total'] = 0 for filename in sys.argv[1:]: playlist = Playlist(filename) playlists.append(playlist) for x in playlist.media_filenames: xx = os.path.join(playlist.dirname, x) ts['total'] += os.path.getsize(xx) ts.add(ttystatus.ElapsedTime()) ts.add(ttystatus.Literal(' ')) ts.add(ttystatus.RemainingTime('done', 'total')) ts.add(ttystatus.Literal(' ')) ts.add(ttystatus.ByteSize('done')) ts.add(ttystatus.Literal('/')) ts.add(ttystatus.ByteSize('total')) ts.add(ttystatus.Literal(' ')) ts.add(ttystatus.ProgressBar('done', 'total')) for playlist in playlists: for relative_name in playlist.media_filenames: source = os.path.join(playlist.dirname, relative_name) target = os.path.join(target_dir, cleanup(relative_name)) if not identical(source, target): x = os.path.dirname(target) if not os.path.exists(x): os.makedirs(x) source_f = open(source) target_f = file(target, 'wb') while True: data = source_f.read(4096) if not data: break target_f.write(data) ts['done'] += len(data) source_f.close() target_f.close() else: ts['done'] += os.path.getsize(source) ts.finish() if __name__ == '__main__': main()