def send_file_to_ipod(self, itdb, fname, tags): if not os.path.exists(fname): logger.error("File '%s' does not exist" % fname) return False logger.debug("Copying file '%s' to iPod..." % fname) podcasts = gpod.itdb_playlist_podcasts(itdb) track = gpod.itdb_track_new() track.visible = 1 track.filetype = "mp3" track.ipod_path = fname track.album = str(tags['album']) track.artist = str(tags['artist']) track.title = str(tags['title']) track.genre = str(tags['genre']) track.tracklen = tags['length'] track.playcount = 0 gpod.itdb_track_add(itdb, track, -1) gpod.itdb_playlist_add_track(podcasts, track, -1) is_copied = gpod.itdb_cp_track_to_ipod(track, fname, None) if is_copied: logger.info("File '%s' has been successfully copied to iPod" % fname) else: # roll back logger.error("File '%s' could not be copied to iPod" % fname) gpod.itdb_playlist_remove_track(podcasts, track) gpod.itdb_track_remove(track) track = None gpod.itdb_write(itdb, None) return is_copied
def copyToiPod(self,itdb,filename): """ Copy file to iPod via gpod library. """ track = gpod.itdb_track_new() pl=gpod.itdb_playlist_podcasts(itdb) audiofile = eyeD3.Mp3AudioFile(filename) tag = audiofile.getTag() for func, attrib in (('getArtist','artist'), ('getTitle','title'), ('getBPM','BPM'), ('getPlayCount','playcount'), ('getAlbum','album')): value = getattr(tag,func)() if value: value = value.encode("utf-8") setattr(track,attrib,value) track.skip_when_shuffling=0x01 track.remember_playback_position=0x01 track.mediatype = 0x00000004 track.mark_unplayed = 0x02 #track.flag4=0x01 track.tracklen = audiofile.getPlayTime() * 1000 gpod.itdb_track_add(itdb, track, -1) gpod.itdb_playlist_add_track(pl, track, -1) if gpod.itdb_cp_track_to_ipod(track,filename, None)!= 1: raise Exception('Unable to copy %s to iPod' % filename)
def __init__(self, filename=None, mediatype=gpod.ITDB_MEDIATYPE_AUDIO, proxied_track=None, podcast=False, ownerdb=None): """Create a Track object. If from_file or filename is set, the file specified will be used to create the track. The mediatype parameter sets the mediatype for the track. It defaults to audio, unless 'podcast' is True, in which case it is set to podcast. See gpod.ITDB_MEDIATYPE_* for other valid mediatypes. If proxied_track is set, it is expected to be an Itdb_Track object. If podcast is True then the track will be setup as a Podcast, unless proxied_track is set. """ if filename: self._track = gpod.itdb_track_new() self['userdata'] = {'transferred': 0, 'hostname': socket.gethostname(), 'charset':defaultencoding} self['userdata']['pc_mtime'] = os.stat(filename).st_mtime self._set_userdata_utf8('filename',filename) possible_image = os.path.join(os.path.split(filename)[0],'folder.jpg') if os.path.exists(possible_image): self.set_coverart_from_file(possible_image) try: audiofile = MP3(self._userdata_into_default_locale('filename')) except Exception, e: raise TrackException(str(e)) for tag, attrib in (('TPE1','artist'), ('TIT2','title'), ('TBPM','BPM'), ('TCON','genre'), ('TALB','album'), ('TPOS',('cd_nr','cds')), ('TRCK',('track_nr','tracks'))): try: value = audiofile[tag] if isinstance(value,mutagen.id3.NumericPartTextFrame): parts = map(int,value.text[0].split("/")) if len(parts) == 2: self[attrib[0]], self[attrib[1]] = parts elif len(parts) == 1: self[attrib[0]] = parts[0] elif isinstance(value,mutagen.id3.TextFrame): self[attrib] = value.text[0].encode('UTF-8','replace') except KeyError: pass if self['title'] is None: self['title'] = os.path.splitext( os.path.split(filename)[1])[0].decode( defaultencoding).encode('UTF-8') self['tracklen'] = int(audiofile.info.length * 1000) self.set_podcast(podcast)
def add_track(self, episode, reporthook=None): self.notify('status', _('Adding %s') % episode.title) tracklist = gpod.sw_get_playlist_tracks(self.podcasts_playlist) podcasturls = [track.podcasturl for track in tracklist] if episode.url in podcasturls: # Mark as played on iPod if played locally (and set podcast flags) self.set_podcast_flags(tracklist[podcasturls.index(episode.url)], episode) return True original_filename = episode.local_filename(create=False) # The file has to exist, if we ought to transfer it, and therefore, # local_filename(create=False) must never return None as filename assert original_filename is not None local_filename = original_filename if util.calculate_size(original_filename) > self.get_free_space(): logger.error('Not enough space on %s, sync aborted...', self.mountpoint) d = {'episode': episode.title, 'mountpoint': self.mountpoint} message = _( 'Error copying %(episode)s: Not enough free space on %(mountpoint)s' ) self.errors.append(message % d) self.cancelled = True return False local_filename = episode.local_filename(create=False) (fn, extension) = os.path.splitext(local_filename) if extension.lower().endswith('ogg'): logger.error('Cannot copy .ogg files to iPod.') return False track = gpod.itdb_track_new() # Add release time to track if episode.published has a valid value if episode.published > 0: try: # libgpod>= 0.5.x uses a new timestamp format track.time_released = gpod.itdb_time_host_to_mac( int(episode.published)) except: # old (pre-0.5.x) libgpod versions expect mactime, so # we're going to manually build a good mactime timestamp here :) # # + 2082844800 for unixtime => mactime (1970 => 1904) track.time_released = int(episode.published + 2082844800) track.title = str(episode.title) track.album = str(episode.channel.title) track.artist = str(episode.channel.title) track.description = str(util.remove_html_tags(episode.description)) track.podcasturl = str(episode.url) track.podcastrss = str(episode.channel.url) track.tracklen = get_track_length(local_filename) track.size = os.path.getsize(local_filename) if episode.file_type() == 'audio': track.filetype = 'mp3' track.mediatype = 0x00000004 elif episode.file_type() == 'video': track.filetype = 'm4v' track.mediatype = 0x00000006 self.set_podcast_flags(track, episode) gpod.itdb_track_add(self.itdb, track, -1) gpod.itdb_playlist_add_track(self.master_playlist, track, -1) gpod.itdb_playlist_add_track(self.podcasts_playlist, track, -1) copied = gpod.itdb_cp_track_to_ipod(track, str(local_filename), None) reporthook(episode.file_size, 1, episode.file_size) # If the file has been converted, delete the temporary file here if local_filename != original_filename: util.delete_file(local_filename) return True
def add_track(self, episode,reporthook=None): self.notify('status', _('Adding %s') % episode.title) tracklist = gpod.sw_get_playlist_tracks(self.podcasts_playlist) podcasturls=[track.podcasturl for track in tracklist] if episode.url in podcasturls: # Mark as played on iPod if played locally (and set podcast flags) self.set_podcast_flags(tracklist[podcasturls.index(episode.url)], episode) return True original_filename = episode.local_filename(create=False) # The file has to exist, if we ought to transfer it, and therefore, # local_filename(create=False) must never return None as filename assert original_filename is not None local_filename = original_filename if util.calculate_size(original_filename) > self.get_free_space(): logger.error('Not enough space on %s, sync aborted...', self.mountpoint) d = {'episode': episode.title, 'mountpoint': self.mountpoint} message =_('Error copying %(episode)s: Not enough free space on %(mountpoint)s') self.errors.append(message % d) self.cancelled = True return False local_filename = episode.local_filename(create=False) (fn, extension) = os.path.splitext(local_filename) if extension.lower().endswith('ogg'): logger.error('Cannot copy .ogg files to iPod.') return False track = gpod.itdb_track_new() # Add release time to track if episode.published has a valid value if episode.published > 0: try: # libgpod>= 0.5.x uses a new timestamp format track.time_released = gpod.itdb_time_host_to_mac(int(episode.published)) except: # old (pre-0.5.x) libgpod versions expect mactime, so # we're going to manually build a good mactime timestamp here :) # # + 2082844800 for unixtime => mactime (1970 => 1904) track.time_released = int(episode.published + 2082844800) track.title = str(episode.title) track.album = str(episode.channel.title) track.artist = str(episode.channel.title) track.description = str(util.remove_html_tags(episode.description)) track.podcasturl = str(episode.url) track.podcastrss = str(episode.channel.url) track.tracklen = get_track_length(local_filename) track.size = os.path.getsize(local_filename) if episode.file_type() == 'audio': track.filetype = 'mp3' track.mediatype = 0x00000004 elif episode.file_type() == 'video': track.filetype = 'm4v' track.mediatype = 0x00000006 self.set_podcast_flags(track, episode) gpod.itdb_track_add(self.itdb, track, -1) gpod.itdb_playlist_add_track(self.master_playlist, track, -1) gpod.itdb_playlist_add_track(self.podcasts_playlist, track, -1) copied = gpod.itdb_cp_track_to_ipod(track, str(local_filename), None) reporthook(episode.file_size, 1, episode.file_size) # If the file has been converted, delete the temporary file here if local_filename != original_filename: util.delete_file(local_filename) return True
def __init__(self, filename=None, mediatype=gpod.ITDB_MEDIATYPE_AUDIO, proxied_track=None, podcast=False, ownerdb=None): """Create a Track object. If from_file or filename is set, the file specified will be used to create the track. The mediatype parameter sets the mediatype for the track. It defaults to audio, unless 'podcast' is True, in which case it is set to podcast. See gpod.ITDB_MEDIATYPE_* for other valid mediatypes. If proxied_track is set, it is expected to be an Itdb_Track object. If podcast is True then the track will be setup as a Podcast, unless proxied_track is set. """ if filename: self._track = gpod.itdb_track_new() self['userdata'] = { 'transferred': 0, 'hostname': socket.gethostname(), 'charset': defaultencoding } self['userdata']['pc_mtime'] = os.stat(filename).st_mtime self._set_userdata_utf8('filename', filename) possible_image = os.path.join( os.path.split(filename)[0], 'folder.jpg') if os.path.exists(possible_image): self.set_coverart_from_file(possible_image) try: audiofile = MP3(self._userdata_into_default_locale('filename')) except Exception, e: raise TrackException(str(e)) for tag, attrib in (('TPE1', 'artist'), ('TIT2', 'title'), ('TBPM', 'BPM'), ('TCON', 'genre'), ('TALB', 'album'), ('TPOS', ('cd_nr', 'cds')), ('TRCK', ('track_nr', 'tracks'))): try: value = audiofile[tag] if isinstance(value, mutagen.id3.NumericPartTextFrame): parts = map(int, value.text[0].split("/")) if len(parts) == 2: self[attrib[0]], self[attrib[1]] = parts elif len(parts) == 1: self[attrib[0]] = parts[0] elif isinstance(value, mutagen.id3.TextFrame): self[attrib] = value.text[0].encode('UTF-8', 'replace') except KeyError: pass if self['title'] is None: self['title'] = os.path.splitext(os.path.split( filename)[1])[0].decode(defaultencoding).encode('UTF-8') self['tracklen'] = int(audiofile.info.length * 1000) self.set_podcast(podcast)
elif len(parts) == 1: self[attrib[0]] = parts[0] elif isinstance(value, mutagen.id3.TextFrame): self[attrib] = value.text[0].encode('UTF-8', 'replace') except KeyError: pass if self['title'] is None: self['title'] = os.path.splitext(os.path.split( filename)[1])[0].decode(defaultencoding).encode('UTF-8') self['tracklen'] = int(audiofile.info.length * 1000) self.set_podcast(podcast) elif proxied_track: self._track = proxied_track self.__database = ownerdb # so the db doesn't get gc'd else: self._track = gpod.itdb_track_new() self.set_podcast(podcast) if not 'mediatype' in self: self['mediatype'] = mediatype def _set_userdata_utf8(self, key, value): self['userdata']['%s_locale' % key] = value try: self['userdata']['%s_utf8' % key] = value.decode( self['userdata']['charset']).encode('UTF-8') except UnicodeDecodeError, e: # string clearly isn't advertised charset. I prefer to # not add the _utf8 version as we can't actually generate # it. Maybe we'll have to populate a close-fit though. pass
def action(path): from os import sep, stat from os.path import relpath from mutagen.m4a import M4AInfo relative_path = relpath(path, mountpoint) ipod_path = ":" + relative_path.replace(sep, ":") md_hard, md_easy = get_metadata(path) info = md_easy.info c = is_compilation(md_easy) track = gpod.itdb_track_new() track.title = get_first_utf8(md_easy, "title") track.artist = get_first_utf8(md_easy, "artist") track.album = get_first_utf8(md_easy, "album") track.compilation = c track.tracklen = int(info.length * 1000) track.bitrate = int(info.bitrate) track.samplerate = int(info.sample_rate) track.ipod_path = ipod_path track.size = stat(path).st_size if isinstance(info, M4AInfo): track.filetype = "M4A-file" else: track.filetype = "MP3-file" mb_albumid = get_first_utf8(md_easy, "musicbrainz_albumid", None) if mb_albumid is not None: existing_artwork = get_artwork(mb_albumid) if existing_artwork is not None: _log.debug( "found existing artwork for track %r (%r-%r)", path, get_first(md_easy, "artist"), get_first(md_easy, "album"), ) artwork = existing_artwork else: artwork_data = get_any_artwork(md_hard) if artwork_data is not None: _log.debug("storing artwork for track %r", path) artwork = store_artwork(artwork_data, mb_albumid) else: artwork = None else: artwork = None if artwork is not None: track.artwork = gpod.itdb_artwork_duplicate(artwork) try: track_number = get_first(md_easy, "tracknumber") disc_number = get_first(md_easy, "discnumber", "1") track_n = track_number.split("/") disc_n = disc_number.split("/") track.track_nr = int(track_n[0]) track.cd_nr = int(disc_n[0]) if len(track_n) > 1: track.tracks = int(track_n[1]) if len(disc_n) > 1: track.cds = int(disc_n[1]) except Exception, e: _log.error("%r %r", e, md_easy)
def add_track(self, episode): self.notify('status', _('Adding %s') % episode.title) for track in gpod.sw_get_playlist_tracks(self.podcasts_playlist): if episode.url == track.podcasturl: if track.playcount > 0: gl.history_mark_played(track.podcasturl) # Mark as played on iPod if played locally (and set podcast flags) self.set_podcast_flags(track) return True original_filename=str(episode.local_filename()) local_filename=original_filename # Reserve 10 MiB for iTunesDB writing (to be on the safe side) RESERVED_FOR_ITDB=1024*1024*10 space_for_track=util.get_free_disk_space(self.mountpoint) - RESERVED_FOR_ITDB needed=util.calculate_size(local_filename) if needed > space_for_track: log('Not enough space on %s: %s available, but need at least %s', self.mountpoint, util.format_filesize(space_for_track), util.format_filesize(needed), sender=self) self.errors.append( _('Error copying %s: Not enough free disk space on %s') % (episode.title, self.mountpoint)) self.cancelled=True return False (fn, extension)=os.path.splitext(original_filename) if libconverter.converters.has_converter(extension): log('Converting: %s', original_filename, sender=self) callback_status=lambda percentage: self.notify('sub-progress', int(percentage)) local_filename=libconverter.converters.convert(original_filename, callback=callback_status) if not libtagupdate.update_metadata_on_file(local_filename, title=episode.title, artist=episode.channel.title): log('Could not set metadata on converted file %s', local_filename, sender=self) if local_filename is None: log('Cannot convert %s', original_filename, sender=self) return False else: local_filename=str(local_filename) (fn, extension)=os.path.splitext(local_filename) if extension.lower().endswith('ogg'): log('Cannot copy .ogg files to iPod.', sender=self) return False track=gpod.itdb_track_new() # Add release time to track if pubDate is parseable ipod_date=email.Utils.parsedate(episode.pubDate) if ipod_date is not None: try: # libgpod>= 0.5.x uses a new timestamp format track.time_released=gpod.itdb_time_host_to_mac(int(time.mktime(ipod_date))) except: # old (pre-0.5.x) libgpod versions expect mactime, so # we're going to manually build a good mactime timestamp here :) # # + 2082844800 for unixtime => mactime (1970 => 1904) track.time_released=int(time.mktime(ipod_date) + 2082844800) track.title=str(episode.title) track.album=str(episode.channel.title) track.artist=str(episode.channel.title) track.description=str(episode.description) track.podcasturl=str(episode.url) track.podcastrss=str(episode.channel.url) track.tracklen=get_track_length(local_filename) track.size=os.path.getsize(local_filename) if episode.file_type() == 'audio': track.filetype='mp3' track.mediatype=0x00000004 elif episode.file_type() == 'video': track.filetype='m4v' track.mediatype=0x00000006 self.set_podcast_flags(track) self.set_cover_art(track, local_filename) gpod.itdb_track_add(self.itdb, track, -1) gpod.itdb_playlist_add_track(self.podcasts_playlist, track, -1) gpod.itdb_cp_track_to_ipod( track, local_filename, None) # If the file has been converted, delete the temporary file here if local_filename != original_filename: util.delete_file(local_filename) return True
self[attrib[0]] = parts[0] elif isinstance(value,mutagen.id3.TextFrame): self[attrib] = value.text[0].encode('UTF-8','replace') except KeyError: pass if self['title'] is None: self['title'] = os.path.splitext( os.path.split(filename)[1])[0].decode( defaultencoding).encode('UTF-8') self['tracklen'] = int(audiofile.info.length * 1000) self.set_podcast(podcast) elif proxied_track: self._track = proxied_track self.__database = ownerdb # so the db doesn't get gc'd else: self._track = gpod.itdb_track_new() self.set_podcast(podcast) if not 'mediatype' in self: self['mediatype'] = mediatype def _set_userdata_utf8(self, key, value): self['userdata']['%s_locale' % key] = value try: self['userdata']['%s_utf8' % key] = value.decode(self['userdata']['charset']).encode('UTF-8') except UnicodeDecodeError, e: # string clearly isn't advertised charset. I prefer to # not add the _utf8 version as we can't actually generate # it. Maybe we'll have to populate a close-fit though. pass def _userdata_into_default_locale(self, key):