diff options
-rwxr-xr-x | bindings/python/examples/add_song.py | 51 | ||||
-rw-r--r-- | bindings/python/ipod.py | 126 |
2 files changed, 129 insertions, 48 deletions
diff --git a/bindings/python/examples/add_song.py b/bindings/python/examples/add_song.py index 6a37bb6..c28fd4b 100755 --- a/bindings/python/examples/add_song.py +++ b/bindings/python/examples/add_song.py @@ -38,11 +38,11 @@ def download(path): size = int(remotefile.info()['Content-Length']) except KeyError: size = None - hndl, tempfilename = tempfile.mkstemp() + hndl, tempfilename = tempfile.mkstemp('.mp3') temp = open(tempfilename,"wb") fetched = 0 while 1: - buf = remotefile.read(1024*10) + buf = remotefile.read(1024*20) if not buf: break temp.write(buf) fetched += len(buf) @@ -74,52 +74,47 @@ if len(args) == 0: db = gpod.Database(options.mountpoint) + playlist = None if options.playlist: for pl in db.Playlists: if pl.name == options.playlist: playlist = pl if not playlist: - print "Creating new playlist" - playlist = gpod.Playlist(db,title=options.playlist) + playlist = db.new_Playlist(title=options.playlist) + print "Created new playlist %s" % playlist + + +deleteWhenDone = [] for path in args: - deleteWhenDone = [] transport = urlparse.urlsplit(path)[0] if transport: path = download(path) deleteWhenDone.append(path) - if not eyeD3.isMp3File(path): - sys.stderr.write("%s it not recognised as an mp3 file by eyeD3 tag library.\n" % path) - if transport: - sys.stderr.write("Leaving for inspection.\n") - deleteWhenDone.pop() - continue - try: - track = gpod.Track(from_file=path, podcast=options.ispodcast) + track = db.new_Track(filename=path, podcast=options.ispodcast) except gpod.TrackException, e: print "Exception handling %s: %s" % (path, e) - continue - db.add(track) - - if options.ispodcast: - playlists = [db.Podcasts, playlist] - print "Adding Podcast %s (%s)" % (path,track) - else: - playlists = [db.Master, playlist] - print "Adding Song %s (%s)" % (path,track) + continue # skip this track + + print "Added %s to database" % track - for pl in playlists: - if pl: - print " adding to playlist %s" % pl - pl.add(track) + if playlist: + print " adding to playlist %s" % playlist + playlist.add(track) - track.copy_to_ipod() +def print_progress(database, track, i, total): + sys.stdout.write("Copying to iPod %04d/%d: %s\r" % (i,total,track)) + sys.stdout.flush() + +print "Copying to iPod" +db.copy_delayed_files(callback=print_progress) - [os.unlink(f) for f in deleteWhenDone] +[os.unlink(f) for f in deleteWhenDone] +print "Saving database" db.close() print "Saved db" diff --git a/bindings/python/ipod.py b/bindings/python/ipod.py index 3e021dc..d63f12b 100644 --- a/bindings/python/ipod.py +++ b/bindings/python/ipod.py @@ -13,14 +13,23 @@ class TrackException(RuntimeError): pass class Database: - def __init__(self, mountpoint="/mnt/ipod"): - self._itdb = itdb = gpod.itdb_parse(mountpoint, - None) - if not self._itdb: - raise DatabaseException("Unable to parse iTunes database at mount point %s" % mountpoint) + def __init__(self, mountpoint="/mnt/ipod", local=False, localdb=None): + if local: + if localdb: + self._itdb_file = localdb + else: + self._itdb_file = os.path.join(os.environ['HOME'], + ".gtkpod", + "local_0.itdb") + self._itdb = gpod.itdb_parse_file(self._itdb_file, None) else: - self._itdb.mountpoint = mountpoint - + self._itdb = gpod.itdb_parse(mountpoint, None) + if not self._itdb: + raise DatabaseException("Unable to parse iTunes database at mount point %s" % mountpoint) + else: + self._itdb.mountpoint = mountpoint + self._itdb_file = os.path.join(self._itdb.mountpoint, + "iPod_Control","iTunes","iTunesDB") self._load_gtkpod_extended_info() def __str__(self): @@ -33,17 +42,16 @@ class Database: len(self)) def _load_gtkpod_extended_info(self): - self._itdb_file = os.path.join(self._itdb.mountpoint, - "iPod_Control","iTunes","iTunesDB") - self._itdbext_file = os.path.join(self._itdb.mountpoint, - "iPod_Control","iTunes","iTunesDB.ext") - if os.path.exists(self._itdb_file) and os.path.exists(self._itdbext_file): - gtkpod.parse(self._itdbext_file, self, self._itdb_file) + itdbext_file = "%s.ext" % (self._itdb_file) + + if os.path.exists(self._itdb_file) and os.path.exists(itdbext_file): + gtkpod.parse(itdbext_file, self, self._itdb_file) def close(self): - if not gpod.itdb_write(self._itdb, None): - raise DatabaseException("Unable to save iTunes database at %s" % mountpoint) - gtkpod.write(self._itdbext_file, self, self._itdb_file) + if not gpod.itdb_write_file(self._itdb, self._itdb_file, None): + raise DatabaseException("Unable to save iTunes database %s" % self) + itdbext_file = "%s.ext" % (self._itdb_file) + gtkpod.write(itdbext_file, self, self._itdb_file) def __getitem__(self, index): if type(index) == types.SliceType: @@ -68,6 +76,35 @@ class Database: def add(self, track, pos=-1): gpod.itdb_track_add(self._itdb, track._track, pos) + def remove(self, item, harddisk=False, ipod=True): + if isinstance(item, Playlist): + if ipod or harddisk: + # remove all the tracks that were in this playlist + for track in item: + self.remove(track, ipod=ipod, harddisk=harddisk) + if gpod.itdb_playlist_exists(self._itdb, item._pl): + gpod.itdb_playlist_remove(item._pl) + else: + raise DatabaseException("Playlist %s was not in %s" % (item, self)) + elif isinstance(item, Track): + for pl in self.Playlists: + if item in pl: + pl.remove(item) + if harddisk: + try: + filename = item['userdata']['filename_locale'] + except KeyError, e: + raise TrackException("Unable to remove %s from hard disk, no filename available." % item) + os.unlink(filename) + if ipod: + filename = item.ipod_filename() + if filename and os.path.exists(filename): + os.unlink(filename) + print "unlinked %s" % filename + gpod.itdb_track_unlink(item._track) + else: + raise DatabaseException("Unable to remove a %s from database" % type(item)) + def get_master(self): return Playlist(self,proxied_playlist=gpod.itdb_playlist_mpl(self._itdb)) @@ -84,6 +121,38 @@ class Database: def smart_update(self): gpod.itdb_spl_update_all(self._itdb) + def new_Playlist(self,**kwargs): + return Playlist(self, **kwargs) + + def new_Track(self,**kwargs): + track = Track(**kwargs) + self.add(track) + if kwargs.has_key('podcast') and kwargs['podcast'] == True: + self.Podcasts.add(track) + else: + self.Master.add(track) + return track + + def copy_delayed_files(self,callback=False): + if not gpod.itdb_get_mountpoint(self._itdb): + # we're not working with a real ipod. + return + to_copy=[] + for track in self: + try: + transferred = int(track['userdata']['transferred']) + except KeyError: + transferred = 1 + if not transferred: + to_copy.append(track) + i = 0 + total = len(to_copy) + for track in to_copy: + if callback: + i=i+1 + callback(self,track, i, total) + track.copy_to_ipod() + class Track: # Note we don't free the underlying structure, as it's still used # by the itdb. @@ -105,10 +174,13 @@ class Track: "chapterdata_raw","chapterdata_raw_length","artwork", "usertype") - def __init__(self, from_file=None, proxied_track=None, podcast=False): + def __init__(self, filename=None, from_file=None, + proxied_track=None, podcast=False): if from_file: + filename = from_file + if filename: self._track = gpod.itdb_track_new() - self['userdata'] = {'filename_locale': from_file, + self['userdata'] = {'filename_locale': filename, 'transferred': 0} try: audiofile = eyeD3.Mp3AudioFile(self['userdata']['filename_locale']) @@ -156,12 +228,15 @@ class Track: def copy_to_ipod(self): self['userdata']['md5_hash'] = gtkpod.sha1_hash( self['userdata']['filename_locale']) + if not gpod.itdb_get_mountpoint(self._track.itdb): + return False self['userdata']['transferred'] = 1 if gpod.itdb_cp_track_to_ipod(self._track, self['userdata']['filename_locale'], None) != 1: raise TrackException('Unable to copy %s to iPod as %s' % ( self['userdata']['filename_locale'], self)) + return True def ipod_filename(self): return gpod.itdb_filename_on_ipod(self._track) @@ -305,8 +380,7 @@ class _Playlists: proxied_playlist=pl) else: raise KeyError("Playlist with number %s not found." % repr(number)) - - + class Playlist: def __init__(self, parent_db, proxied_playlist=None, title="New Playlist", smart=False, pos=-1): @@ -389,5 +463,17 @@ class Playlist: def __nonzero__(self): return True + def __contains__(self, track): + if gpod.itdb_playlist_contains_track(self._pl, track._track): + return True + else: + return False + def add(self, track, pos=-1): gpod.itdb_playlist_add_track(self._pl, track._track, pos) + + def remove(self, track): + if self.__contains__(track): + gpod.itdb_playlist_remove_track(self._pl, track._track) + else: + raise DatabaseException("Playlist %s does not contain %s" % (self, track)) |