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
Beispiel #2
0
 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)
Beispiel #3
0
    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)
Beispiel #4
0
    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
Beispiel #5
0
    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
Beispiel #6
0
    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)
Beispiel #7
0
                        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
Beispiel #8
0
    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)
Beispiel #9
0
    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
Beispiel #10
0
                            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):