Example #1
0
            def resume_sync(episode_urls, channel_urls, progress):
                if progress is not None:
                    progress.on_finished()

                # rest of sync process should continue here
                self.commit_changes_to_database()
                for current_channel in self.channels:
                    # only sync those channels marked for syncing
                    if (self._config.device_sync.device_type == 'filesystem'
                            and current_channel.sync_to_mp3_player
                            and self._config.device_sync.playlists.create):

                        # get playlist object
                        playlist = gPodderDevicePlaylist(
                            self._config, current_channel.title)
                        # need to refresh episode list so that
                        # deleted episodes aren't included in playlists
                        episodes_for_playlist = sorted(
                            current_channel.get_episodes(
                                gpodder.STATE_DOWNLOADED),
                            key=lambda ep: ep.published)
                        # don't add played episodes to playlist if skip_played_episodes is True
                        if self._config.device_sync.skip_played_episodes:
                            episodes_for_playlist = [
                                ep for ep in episodes_for_playlist if ep.is_new
                            ]
                        playlist.write_m3u(episodes_for_playlist)

                # enable updating of UI, but mark it as tasks being added so that a
                # adding a single task that completes immediately doesn't turn off the
                # ui updates again
                self.set_download_list_state(gPodderSyncUI.DL_ADDING_TASKS)

                if (self._config.device_sync.device_type == 'filesystem'
                        and self._config.device_sync.playlists.create):
                    title = _('Update successful')
                    message = _(
                        'The playlist on your MP3 player has been updated.')
                    self.notification(message, title)

                # called from the main thread to complete adding tasks
                def add_downloads_complete():
                    self.set_download_list_state(gPodderSyncUI.DL_ADDED_TASKS)

                # Finally start the synchronization process
                @util.run_in_background
                def sync_thread_func():
                    device.add_sync_tasks(episodes,
                                          force_played=force_played,
                                          done_callback=done_callback)
                    util.idle_add(add_downloads_complete)

                return
Example #2
0
            def resume_sync(episode_urls, channel_urls, progress):
                if progress is not None:
                    progress.on_finished()

                # rest of sync process should continue here
                self.commit_changes_to_database()
                for current_channel in self.channels:
                    # only sync those channels marked for syncing
                    if (self._config.device_sync.device_type == 'filesystem'
                            and current_channel.sync_to_mp3_player
                            and self._config.device_sync.playlists.create):

                        # get playlist object
                        playlist = gPodderDevicePlaylist(self._config,
                                                         current_channel.title)
                        # need to refresh episode list so that
                        # deleted episodes aren't included in playlists
                        episodes_for_playlist = sorted(current_channel.get_episodes(gpodder.STATE_DOWNLOADED),
                                                       key=lambda ep: ep.published)
                        # don't add played episodes to playlist if skip_played_episodes is True
                        if self._config.device_sync.skip_played_episodes:
                            episodes_for_playlist = [ep for ep in episodes_for_playlist if ep.is_new]
                        playlist.write_m3u(episodes_for_playlist)

                # enable updating of UI
                self.enable_download_list_update()

                if (self._config.device_sync.device_type == 'filesystem' and self._config.device_sync.playlists.create):
                    title = _('Update successful')
                    message = _('The playlist on your MP3 player has been updated.')
                    self.notification(message, title)

                # Finally start the synchronization process
                @util.run_in_background
                def sync_thread_func():
                    device.add_sync_tasks(episodes, force_played=force_played,
                                          done_callback=done_callback)

                return
Example #3
0
        def check_free_space():
            # "Will we add this episode to the device?"
            def will_add(episode):
                # If already on-device, it won't take up any space
                if device.episode_on_device(episode):
                    return False

                # Might not be synced if it's played already
                if (not force_played
                        and self._config.device_sync.skip_played_episodes):
                    return False

                # In all other cases, we expect the episode to be
                # synchronized to the device, so "answer" positive
                return True

            # "What is the file size of this episode?"
            def file_size(episode):
                filename = episode.local_filename(create=False)
                if filename is None:
                    return 0
                return util.calculate_size(str(filename))

            # Calculate total size of sync and free space on device
            total_size = sum(file_size(e) for e in episodes if will_add(e))
            free_space = max(device.get_free_space(), 0)

            if total_size > free_space:
                title = _('Not enough space left on device')
                message = (_(
                    'Additional free space required: %(required_space)s\nDo you want to continue?'
                ) % {
                    'required_space':
                    util.format_filesize(total_size - free_space)
                })
                if not self.show_confirmation(message, title):
                    device.cancel()
                    device.close()
                    return

            # enable updating of UI
            self.enable_download_list_update()
            """Update device playlists
            General approach is as follows:

            When a episode is downloaded and synched, it is added to the
            standard playlist for that podcast which is then written to
            the device.

            After the user has played that episode on their device, they
            can delete that episode from their device.

            At the next sync, gPodder will then compare the standard
            podcast-specific playlists on the device (as written by
            gPodder during the last sync), with the episodes on the
            device.If there is an episode referenced in the playlist
            that is no longer on the device, gPodder will assume that
            the episode has already been synced and subsequently deleted
            from the device, and will hence mark that episode as deleted
            in gPodder. If there are no playlists, nothing is deleted.

            At the next sync, the playlists will be refreshed based on
            the downloaded, undeleted episodes in gPodder, and the
            cycle begins again...
            """

            def resume_sync(episode_urls, channel_urls, progress):
                if progress is not None:
                    progress.on_finished()

                # rest of sync process should continue here
                self.commit_changes_to_database()
                for current_channel in self.channels:
                    # only sync those channels marked for syncing
                    if (self._config.device_sync.device_type == 'filesystem'
                            and current_channel.sync_to_mp3_player
                            and self._config.device_sync.playlists.create):

                        # get playlist object
                        playlist = gPodderDevicePlaylist(
                            self._config, current_channel.title)
                        # need to refresh episode list so that
                        # deleted episodes aren't included in playlists
                        episodes_for_playlist = sorted(
                            current_channel.get_episodes(
                                gpodder.STATE_DOWNLOADED),
                            key=lambda ep: ep.published)
                        # don't add played episodes to playlist if skip_played_episodes is True
                        if self._config.device_sync.skip_played_episodes:
                            episodes_for_playlist = [
                                ep for ep in episodes_for_playlist if ep.is_new
                            ]
                        playlist.write_m3u(episodes_for_playlist)

                # enable updating of UI
                self.enable_download_list_update()

                if (self._config.device_sync.device_type == 'filesystem'
                        and self._config.device_sync.playlists.create):
                    title = _('Update successful')
                    message = _(
                        'The playlist on your MP3 player has been updated.')
                    self.notification(message, title)

                # Finally start the synchronization process
                @util.run_in_background
                def sync_thread_func():
                    device.add_sync_tasks(episodes,
                                          force_played=force_played,
                                          done_callback=done_callback)

                return

            if self._config.device_sync.playlists.create:
                try:
                    episodes_to_delete = []
                    if self._config.device_sync.playlists.two_way_sync:
                        for current_channel in self.channels:
                            # only include channels that are included in the sync
                            if current_channel.sync_to_mp3_player:
                                # get playlist object
                                playlist = gPodderDevicePlaylist(
                                    self._config, current_channel.title)
                                # get episodes to be written to playlist
                                episodes_for_playlist = sorted(
                                    current_channel.get_episodes(
                                        gpodder.STATE_DOWNLOADED),
                                    key=lambda ep: ep.published)
                                episode_keys = list(
                                    map(
                                        playlist.
                                        get_absolute_filename_for_playlist,
                                        episodes_for_playlist))

                                episode_dict = dict(
                                    list(
                                        zip(episode_keys,
                                            episodes_for_playlist)))

                                # then get episodes in playlist (if it exists) already on device
                                episodes_in_playlists = playlist.read_m3u()
                                # if playlist doesn't exist (yet) episodes_in_playlist will be empty
                                if episodes_in_playlists:
                                    for episode_filename in episodes_in_playlists:

                                        if not (os.path.exists(
                                                os.path.join(
                                                    playlist.mountpoint,
                                                    episode_filename))):
                                            # episode was synced but no longer on device
                                            # i.e. must have been deleted by user, so delete from gpodder
                                            try:
                                                episodes_to_delete.append(
                                                    episode_dict[
                                                        episode_filename])
                                            except KeyError as ioe:
                                                logger.warn(
                                                    'Episode %s, removed from device has already been deleted from gpodder',
                                                    episode_filename)
                    # delete all episodes from gpodder (will prompt user)

                    # not using playlists to delete
                    def auto_delete_callback(episodes):

                        if not episodes:
                            # episodes were deleted on device
                            # but user decided not to delete them from gpodder
                            # so jump straight to sync
                            logger.info(
                                'Starting sync - no episodes selected for deletion'
                            )
                            resume_sync([], [], None)
                        else:
                            # episodes need to be deleted from gpodder
                            for episode_to_delete in episodes:
                                logger.info("Deleting episode %s",
                                            episode_to_delete.title)

                            logger.info(
                                'Will start sync - after deleting episodes')
                            self.delete_episode_list(episodes, False, True,
                                                     resume_sync)

                        return

                    if episodes_to_delete:
                        columns = (('markup_delete_episodes', None, None,
                                    _('Episode')), )

                        self.select_episodes_to_delete(
                            self.parent_window,
                            title=_('Episodes have been deleted on device'),
                            instructions=
                            'Select the episodes you want to delete:',
                            episodes=episodes_to_delete,
                            selected=[
                                True,
                            ] * len(episodes_to_delete),
                            columns=columns,
                            callback=auto_delete_callback,
                            _config=self._config)
                    else:
                        logger.warning("Starting sync - no episodes to delete")
                        resume_sync([], [], None)

                except IOError as ioe:
                    title = _('Error writing playlist files')
                    message = _(str(ioe))
                    self.notification(message, title)
            else:
                logger.info('Not creating playlists - starting sync')
                resume_sync([], [], None)
Example #4
0
        def check_free_space():
            # "Will we add this episode to the device?"
            def will_add(episode):
                # If already on-device, it won't take up any space
                if device.episode_on_device(episode):
                    return False

                # Might not be synced if it's played already
                if (not force_played and
                        self._config.device_sync.skip_played_episodes):
                    return False

                # In all other cases, we expect the episode to be
                # synchronized to the device, so "answer" positive
                return True

            # "What is the file size of this episode?"
            def file_size(episode):
                filename = episode.local_filename(create=False)
                if filename is None:
                    return 0
                return util.calculate_size(str(filename))

            # Calculate total size of sync and free space on device
            total_size = sum(file_size(e) for e in episodes if will_add(e))
            free_space = max(device.get_free_space(), 0)

            if total_size > free_space:
                title = _('Not enough space left on device')
                message = (_('Additional free space required: %(required_space)s\nDo you want to continue?') %
               {'required_space': util.format_filesize(total_size - free_space)})
                if not self.show_confirmation(message, title):
                    device.cancel()
                    device.close()
                    return

            # enable updating of UI
            self.enable_download_list_update()

            """Update device playlists
            General approach is as follows:

            When a episode is downloaded and synched, it is added to the
            standard playlist for that podcast which is then written to
            the device.

            After the user has played that episode on their device, they
            can delete that episode from their device.

            At the next sync, gPodder will then compare the standard
            podcast-specific playlists on the device (as written by
            gPodder during the last sync), with the episodes on the
            device.If there is an episode referenced in the playlist
            that is no longer on the device, gPodder will assume that
            the episode has already been synced and subsequently deleted
            from the device, and will hence mark that episode as deleted
            in gPodder. If there are no playlists, nothing is deleted.

            At the next sync, the playlists will be refreshed based on
            the downloaded, undeleted episodes in gPodder, and the
            cycle begins again...
            """

            def resume_sync(episode_urls, channel_urls, progress):
                if progress is not None:
                    progress.on_finished()

                # rest of sync process should continue here
                self.commit_changes_to_database()
                for current_channel in self.channels:
                    # only sync those channels marked for syncing
                    if (self._config.device_sync.device_type == 'filesystem'
                            and current_channel.sync_to_mp3_player
                            and self._config.device_sync.playlists.create):

                        # get playlist object
                        playlist = gPodderDevicePlaylist(self._config,
                                                         current_channel.title)
                        # need to refresh episode list so that
                        # deleted episodes aren't included in playlists
                        episodes_for_playlist = sorted(current_channel.get_episodes(gpodder.STATE_DOWNLOADED),
                                                       key=lambda ep: ep.published)
                        # don't add played episodes to playlist if skip_played_episodes is True
                        if self._config.device_sync.skip_played_episodes:
                            episodes_for_playlist = [ep for ep in episodes_for_playlist if ep.is_new]
                        playlist.write_m3u(episodes_for_playlist)

                # enable updating of UI
                self.enable_download_list_update()

                if (self._config.device_sync.device_type == 'filesystem' and self._config.device_sync.playlists.create):
                    title = _('Update successful')
                    message = _('The playlist on your MP3 player has been updated.')
                    self.notification(message, title)

                # Finally start the synchronization process
                @util.run_in_background
                def sync_thread_func():
                    device.add_sync_tasks(episodes, force_played=force_played,
                                          done_callback=done_callback)

                return

            if self._config.device_sync.playlists.create:
                try:
                    episodes_to_delete = []
                    if self._config.device_sync.playlists.two_way_sync:
                        for current_channel in self.channels:
                            # only include channels that are included in the sync
                            if current_channel.sync_to_mp3_player:
                                # get playlist object
                                playlist = gPodderDevicePlaylist(self._config, current_channel.title)
                                # get episodes to be written to playlist
                                episodes_for_playlist = sorted(current_channel.get_episodes(gpodder.STATE_DOWNLOADED),
                                                               key=lambda ep: ep.published)
                                episode_keys = list(map(playlist.get_absolute_filename_for_playlist,
                                                        episodes_for_playlist))

                                episode_dict = dict(list(zip(episode_keys, episodes_for_playlist)))

                                # then get episodes in playlist (if it exists) already on device
                                episodes_in_playlists = playlist.read_m3u()
                                # if playlist doesn't exist (yet) episodes_in_playlist will be empty
                                if episodes_in_playlists:
                                    for episode_filename in episodes_in_playlists:

                                        if not(os.path.exists(os.path.join(playlist.mountpoint,
                                                                           episode_filename))):
                                            # episode was synced but no longer on device
                                            # i.e. must have been deleted by user, so delete from gpodder
                                            try:
                                                episodes_to_delete.append(episode_dict[episode_filename])
                                            except KeyError as ioe:
                                                logger.warn('Episode %s, removed from device has already been deleted from gpodder',
                                                            episode_filename)
                    # delete all episodes from gpodder (will prompt user)

                    # not using playlists to delete
                    def auto_delete_callback(episodes):

                        if not episodes:
                            # episodes were deleted on device
                            # but user decided not to delete them from gpodder
                            # so jump straight to sync
                            logger.info('Starting sync - no episodes selected for deletion')
                            resume_sync([], [], None)
                        else:
                            # episodes need to be deleted from gpodder
                            for episode_to_delete in episodes:
                                logger.info("Deleting episode %s",
                                            episode_to_delete.title)

                            logger.info('Will start sync - after deleting episodes')
                            self.delete_episode_list(episodes, False,
                                                     True, resume_sync)

                        return

                    if episodes_to_delete:
                        columns = (
                            ('markup_delete_episodes', None, None, _('Episode')),
                        )

                        self.select_episodes_to_delete(
                            self.parent_window,
                            title=_('Episodes have been deleted on device'),
                            instructions='Select the episodes you want to delete:',
                            episodes=episodes_to_delete,
                            selected=[True, ] * len(episodes_to_delete),
                            columns=columns,
                            callback=auto_delete_callback,
                            _config=self._config)
                    else:
                        logger.warning("Starting sync - no episodes to delete")
                        resume_sync([], [], None)

                except IOError as ioe:
                    title = _('Error writing playlist files')
                    message = _(str(ioe))
                    self.notification(message, title)
            else:
                logger.info('Not creating playlists - starting sync')
                resume_sync([], [], None)