Example #1
0
    def cancel_all( self):
        for element in self.status_list:
	    self.status_list[element]['iter']=None
	    self.status_list[element]['thread'].cancel()
        # clear the tree model after cancelling
        util.idle_add(self.tree_model.clear)
        self.downloads_done_bytes=0
Example #2
0
    def cover_download_finished(self, channel, pixbuf):
        def set_cover(channel, pixbuf):
            if self.channel == channel:
                self.imgCover.set_from_pixbuf(self.scale_pixbuf(pixbuf))
                self.gPodderChannel.show()

        util.idle_add(set_cover, channel, pixbuf)
Example #3
0
    def on_ui_initialized(self, model, update_podcast_callback,
            download_episode_callback):
        """
        Connect to the woodchuck server and initialize any state.

        model is an instance of the podcast model.

        podcast_update is a function that is passed a single argument: the
        PodcastPodcast that should be updated.

        episode_download is a function that is passed a single argument:
        the PodcastEpisode that should be downloaded.

        If podcast_update and episode_download are None, then Woodchuck
        upcalls will be disabled.  In this case, you don't need to specify
        the list of podcasts.  Just specify None.
        """
        logger.info('Got on_ui_initialized. Setting up woodchuck..')

        if not woodchuck_imported:
            return

        global _main_thread
        _main_thread = threading.currentThread()

        global woodchuck_instance
        woodchuck_instance = mywoodchuck(model,
                update_podcast_callback,
                download_episode_callback)

        if not woodchuck_instance.available():
            logger.warn('Unable to contact Woodchuck server. Disabling.')

        logger.info('Connected to Woodchuck server.')
        idle_add(check_subscriptions)
Example #4
0
    def add_sync_tasks(self,
                       tracklist,
                       force_played=False,
                       done_callback=None):
        for track in list(tracklist):
            # Filter tracks that are not meant to be synchronized
            does_not_exist = not track.was_downloaded(and_exists=True)
            exclude_played = (not track.is_new and
                              self._config.device_sync.skip_played_episodes)
            wrong_type = track.file_type() not in self.allowed_types

            if does_not_exist or exclude_played or wrong_type:
                logger.info('Excluding %s from sync', track.title)
                tracklist.remove(track)

        if tracklist:
            for track in sorted(tracklist, key=lambda e: e.pubdate_prop):
                if self.cancelled:
                    return False

                # XXX: need to check if track is added properly?
                sync_task = SyncTask(track)

                sync_task.status = sync_task.QUEUED
                sync_task.device = self
                # New Task, we must wait on the GTK Loop
                self.download_status_model.register_task(sync_task)
                # Executes after task has been registered
                util.idle_add(self.download_queue_manager.queue_task,
                              sync_task)
        else:
            logger.warning("No episodes to sync")

        if done_callback:
            done_callback()
 def name_owner_changed(name, old_owner, new_owner):
     logger.debug('name_owner_changed "%s" "%s" "%s"',
                  name, old_owner, new_owner)
     if name == self.bus_name:
         logger.debug('MPRISResumer player %s is there', name)
         cancel.remove()
         util.idle_add(lambda: self.do_enqueue(filename, pos))
Example #6
0
    def on_ui_initialized(self, model, update_podcast_callback,
                          download_episode_callback):
        """
        Connect to the woodchuck server and initialize any state.

        model is an instance of the podcast model.

        podcast_update is a function that is passed a single argument: the
        PodcastPodcast that should be updated.

        episode_download is a function that is passed a single argument:
        the PodcastEpisode that should be downloaded.

        If podcast_update and episode_download are None, then Woodchuck
        upcalls will be disabled.  In this case, you don't need to specify
        the list of podcasts.  Just specify None.
        """
        logger.info('Got on_ui_initialized. Setting up woodchuck..')

        if not woodchuck_imported:
            return

        global _main_thread
        _main_thread = threading.currentThread()

        global woodchuck_instance
        woodchuck_instance = mywoodchuck(model, update_podcast_callback,
                                         download_episode_callback)

        if not woodchuck_instance.available():
            logger.warn('Unable to contact Woodchuck server. Disabling.')

        logger.info('Connected to Woodchuck server.')
        idle_add(check_subscriptions)
Example #7
0
    def cover_download_finished(self, channel, pixbuf):
        def set_cover(channel, pixbuf):
            if self.channel == channel:
                self.imgCover.set_from_pixbuf(self.scale_pixbuf(pixbuf))
                self.gPodderChannel.show()

        util.idle_add(set_cover, channel, pixbuf)
Example #8
0
    def add_sync_tasks(self, tracklist, force_played=False, done_callback=None):
        for track in list(tracklist):
            # Filter tracks that are not meant to be synchronized
            does_not_exist = not track.was_downloaded(and_exists=True)
            exclude_played = (not track.is_new and
                    self._config.device_sync.skip_played_episodes)
            wrong_type = track.file_type() not in self.allowed_types

            if does_not_exist or exclude_played or wrong_type:
                logger.info('Excluding %s from sync', track.title)
                tracklist.remove(track)

        if tracklist:
            for track in sorted(tracklist, key=lambda e: e.pubdate_prop):
                if self.cancelled:
                    return False

                # XXX: need to check if track is added properly?
                sync_task = SyncTask(track)

                sync_task.status = sync_task.QUEUED
                sync_task.device = self
                # New Task, we must wait on the GTK Loop
                self.download_status_model.register_task(sync_task)
                # Executes after task has been registered
                util.idle_add(self.download_queue_manager.queue_task, sync_task)
        else:
            logger.warning("No episodes to sync")

        if done_callback:
            done_callback()
 def name_owner_changed(name, old_owner, new_owner):
     logger.debug('name_owner_changed "%s" "%s" "%s"', name, old_owner,
                  new_owner)
     if name == self.bus_name:
         logger.debug('MPRISResumer player %s is there', name)
         cancel.remove()
         util.idle_add(lambda: self.do_enqueue(filename, pos))
Example #10
0
    def thread_func(self, tab=0):
        if tab == 1:
            model = OpmlListModel(opml.Importer(my.TOPLIST_OPML))
            if len(model) == 0:
                self.notification(
                    _('The specified URL does not provide any valid OPML podcast items.'
                      ), _('No feeds found'))
        elif tab == 2:
            model = OpmlListModel(
                youtube.find_youtube_channels(
                    self.entryYoutubeSearch.get_text()))
            if len(model) == 0:
                self.notification(
                    _('There are no YouTube channels that would match this query.'
                      ), _('No channels found'))
        else:
            url = self.entryURL.get_text()
            if self.is_search_term(url):
                url = 'http://gpodder.net/search.opml?q=' + urllib.quote(url)
            model = OpmlListModel(opml.Importer(url))
            if len(model) == 0:
                self.notification(
                    _('The specified URL does not provide any valid OPML podcast items.'
                      ), _('No feeds found'))

        util.idle_add(self.thread_finished, model, tab)
Example #11
0
    def wrapper(*args, **kwargs):
        if not woodchuck_instance.available():
            return

        def doit():
            @wraps(func)
            def it():
                # Execute the function.

                # Assert that we are running in the main thread.
                assert _main_thread is not None
                assert threading.currentThread() == _main_thread, \
                    ("idle function executed in %s, not %s"
                     % (threading.currentThread(), _main_thread))

                try:
                    func(*args, **kwargs)
                except KeyboardInterrupt:
                    raise
                except:
                    logger.error(
                        "execute_in_main_thread: Executing %s: %s"
                        % (func, traceback.format_exc()))
    
                return False
            return it
    
        if threading.currentThread() == _main_thread:
            logger.debug("Already in main thread. Executing %s" % (func,))
            doit()()
        else:
            logger.debug("Queuing execution of %s from %s"
                         % (func, threading.currentThread()))
            idle_add(doit())
        def download_thread_func():
            if url.startswith('youtube://'):
                importer = youtube.find_youtube_channels(\
                        url[len('youtube://'):])
            else:
                importer = opml.Importer(url)

            if importer.items:
                model = OpmlListModel(importer)
            else:
                model = None
            def download_thread_finished():
                self._is_updating = False
                self.treeview.queue_draw()
                hildon.hildon_gtk_window_set_progress_indicator(\
                        self.main_window, False)
                self.action_select_all.set_property('visible', \
                        model is not None)
                self.action_select_none.set_property('visible', \
                        model is not None)
                self.treeview.set_model(model)
                self.set_subscribe_button_sensitive()

                if model is None:
                    self.show_message(_('No podcasts found. Try another source.'), \
                            important=True)
                    self.main_window.destroy()

            util.idle_add(download_thread_finished)
Example #13
0
    def wrapper(*args, **kwargs):
        if not woodchuck_instance.available():
            return

        def doit():
            @wraps(func)
            def it():
                # Execute the function.

                # Assert that we are running in the main thread.
                assert _main_thread is not None
                assert threading.currentThread() == _main_thread, \
                    ("idle function executed in %s, not %s"
                     % (threading.currentThread(), _main_thread))

                try:
                    func(*args, **kwargs)
                except KeyboardInterrupt:
                    raise
                except:
                    logger.error("execute_in_main_thread: Executing %s: %s" %
                                 (func, traceback.format_exc()))

                return False

            return it

        if threading.currentThread() == _main_thread:
            logger.debug("Already in main thread. Executing %s" % (func, ))
            doit()()
        else:
            logger.debug("Queuing execution of %s from %s" %
                         (func, threading.currentThread()))
            idle_add(doit())
Example #14
0
        def download_thread_func():
            if url.startswith('youtube://'):
                importer = youtube.find_youtube_channels(\
                        url[len('youtube://'):])
            else:
                importer = opml.Importer(url)

            if importer.items:
                model = OpmlListModel(importer)
            else:
                model = None

            def download_thread_finished():
                self._is_updating = False
                self.treeview.queue_draw()
                hildon.hildon_gtk_window_set_progress_indicator(\
                        self.main_window, False)
                self.action_select_all.set_property('visible', \
                        model is not None)
                self.action_select_none.set_property('visible', \
                        model is not None)
                self.treeview.set_model(model)
                self.set_subscribe_button_sensitive()

                if model is None:
                    self.show_message(_('No podcasts found. Try another source.'), \
                            important=True)
                    self.main_window.destroy()

            util.idle_add(download_thread_finished)
Example #15
0
    def notify(self, signal_name, *args):
        if signal_name in self.observers:
            for observer in self.observers[signal_name]:
                util.idle_add(observer, *args)

            return True

        return False
Example #16
0
 def execute():
     try:
         generator.next()
         idle_add(execute)
     except StopIteration:
         return
     except Exception, e:
         logger.exception("Running %s: %s" % (str(func), str(e)))
Example #17
0
    def notify(self, signal_name, *args):
        if signal_name in self.observers:
            for observer in self.observers[signal_name]:
                util.idle_add(observer, *args)

            return True

        return False
Example #18
0
 def execute():
     try:
         generator.next()
         idle_add(execute)
     except StopIteration:
         return
     except Exception, e:
         logger.exception("Running %s: %s" % (str(func), str(e)))
Example #19
0
    def on_web_request(self, web_view, web_frame, web_resource, request, response):
        uri = request.get_uri()
        if uri.startswith(self.flattr.CALLBACK):
            if not self.flattr.process_retrieved_code(uri):
                self.show_message(query["error_description"][0], _("Error"), important=True)

            # Destroy the window later
            util.idle_add(self.main_window.destroy)
Example #20
0
    def replace_from_channel(self, channel, downloading=None, \
            include_description=False, generate_thumbnails=False, \
            treeview=None):
        """
        Add episode from the given channel to this model.
        Downloading should be a callback.
        include_description should be a boolean value (True if description
        is to be added to the episode row, or False if not)
        """

        # Remove old episodes in the list store
        self.clear()

        if treeview is not None:
            util.idle_add(treeview.queue_draw)

        self._all_episodes_view = getattr(channel, 'ALL_EPISODES_PROXY', False)

        # Avoid gPodder bug 1291
        if channel is None:
            episodes = []
        else:
            episodes = channel.get_all_episodes()

        if not isinstance(episodes, list):
            episodes = list(episodes)
        count = len(episodes)

        for position, episode in enumerate(episodes):
            iter = self.append((episode.url, \
                    episode.title, \
                    self._format_filesize(episode), \
                    episode, \
                    None, \
                    episode.cute_pubdate(), \
                    '', \
                    '', \
                    True, \
                    True, \
                    True, \
                    episode.length, \
                    episode.pubDate, \
                    episode.get_play_info_string(), \
                    episode.total_time and not episode.current_position, \
                    episode.total_time and episode.current_position, \
                    episode.is_locked))

            self.update_by_iter(iter, downloading, include_description, \
                    generate_thumbnails, reload_from_db=False)

        self._on_filter_changed(self.has_episodes())
        log("updated model")

        def hello():
            log("idle again")

        gtk.idle_add(hello)
Example #21
0
    def on_web_request(self, web_view, web_frame, web_resource, request, response):
        uri = request.get_uri()
        if uri.startswith(self.flattr.CALLBACK):
            if not self.flattr.process_retrieved_code(uri):
                self.show_message(query['error_description'][0], _('Error'),
                        important=True)

            # Destroy the window later
            util.idle_add(self.main_window.destroy)
Example #22
0
    def cover_download_finished(self, channel, pixbuf):
        def set_cover(channel, pixbuf):
            if self.channel == channel:
                self.imgCover.set_from_pixbuf(self.scale_pixbuf(pixbuf))
                if self.show_on_cover_load:
                    self.main_window.show()
                    self.show_on_cover_load = False

        util.idle_add(set_cover, channel, pixbuf)
Example #23
0
    def cover_download_finished(self, channel, pixbuf):
        def set_cover(channel, pixbuf):
            if self.channel == channel:
                self.imgCover.set_from_pixbuf(self.scale_pixbuf(pixbuf))
                if self.show_on_cover_load:
                    self.main_window.show()
                    self.show_on_cover_load = False

        util.idle_add(set_cover, channel, pixbuf)
 def convert():
     ffmpeg = subprocess.Popen(['ffmpeg', '-f', 'concat', '-nostdin', '-y',
         '-i', list_filename, '-c', 'copy', out_filename])
     result = ffmpeg.wait()
     util.delete_file(list_filename)
     util.idle_add(lambda: indicator.on_finished())
     util.idle_add(lambda: self.gpodder.show_message(
         _('Videos successfully converted') if result == 0 else
         _('Error converting videos'),
         _('Concatenation result'), important=True))
Example #25
0
 def connect_gtk_window( self, window, config_prefix='main_window'):
     ( x, y, width, height )=map( lambda x: config_prefix + '_' + x, [ 'x', 'y', 'width', 'height' ])
     if set( ( x, y, width, height )).issubset( set( self.Settings)):
         window.resize( getattr( self, width), getattr( self, height))
         window.move( getattr( self, x), getattr( self, y))
         self.disable_window_events()
         util.idle_add(self.enable_window_events)
         window.connect( 'configure-event', self.receive_configure_event, config_prefix)
     else:
         raise ValueError( 'Missing settings in set: %s' % ', '.join( ( x, y, width, height )))
Example #26
0
    def replace_from_channel(self, channel, downloading=None, \
            include_description=False, generate_thumbnails=False, \
            treeview=None):
        """
        Add episode from the given channel to this model.
        Downloading should be a callback.
        include_description should be a boolean value (True if description
        is to be added to the episode row, or False if not)
        """

        # Remove old episodes in the list store
        self.clear()

        if treeview is not None:
            util.idle_add(treeview.queue_draw)

        self._all_episodes_view = getattr(channel, 'ALL_EPISODES_PROXY', False)

        # Avoid gPodder bug 1291
        if channel is None:
            episodes = []
        else:
            episodes = channel.get_all_episodes()

        if not isinstance(episodes, list):
            episodes = list(episodes)
        count = len(episodes)

        for position, episode in enumerate(episodes):
            iter = self.append((episode.url, \
                    episode.title, \
                    self._format_filesize(episode), \
                    episode, \
                    None, \
                    episode.cute_pubdate(), \
                    '', \
                    '', \
                    True, \
                    True, \
                    True, \
                    episode.length, \
                    episode.pubDate, \
                    episode.get_play_info_string(), \
                    episode.total_time and not episode.current_position, \
                    episode.total_time and episode.current_position, \
                    episode.is_locked))

            self.update_by_iter(iter, downloading, include_description, \
                    generate_thumbnails, reload_from_db=False)

        self._on_filter_changed(self.has_episodes())
        log("updated model")
        def hello():
        	log("idle again")
        gtk.idle_add(hello)
Example #27
0
 def convert():
     ffmpeg = util.Popen(['ffmpeg', '-f', 'concat', '-nostdin', '-y',
                          '-i', list_filename, '-c', 'copy', out_filename],
                         close_fds=True)
     result = ffmpeg.wait()
     util.delete_file(list_filename)
     util.idle_add(lambda: indicator.on_finished())
     util.idle_add(lambda: self.gpodder.show_message(
         _('Videos successfully converted') if result == 0 else
         _('Error converting videos'),
         _('Concatenation result'), important=True))
Example #28
0
    def connect_gtk_window(self, window, config_prefix, show_window=False):
        cfg = getattr(self.ui.gtk.state, config_prefix)

        if gpodder.ui.win32:
            window.set_gravity(Gdk.Gravity.STATIC)

        if cfg.width != -1 and cfg.height != -1:
            window.resize(cfg.width, cfg.height)

        # Not all platforms can natively restore position, gPodder must handle it.
        # https://github.com/gpodder/gpodder/pull/933#issuecomment-818039693
        if cfg.x == -1 or cfg.y == -1:
            window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
        else:
            window.move(cfg.x, cfg.y)
            # From Gtk docs: most window managers ignore requests for initial window
            # positions (instead using a user-defined placement algorithm) and honor
            # requests after the window has already been shown.
            # Move it a second time after the window has been shown.
            # The first move reduces chance of window jumping.
            util.idle_add(window.move, cfg.x, cfg.y)

        # Ignore events while we're connecting to the window
        self.__ignore_window_events = True

        # Get window state, correct size comes from window.get_size(),
        # see https://developer.gnome.org/SaveWindowState/
        def _receive_configure_event(widget, event):
            x_pos, y_pos = widget.get_position()
            width_size, height_size = widget.get_size()
            maximized = bool(event.window.get_state() & Gdk.WindowState.MAXIMIZED)
            if not self.__ignore_window_events and not maximized:
                cfg.x = x_pos
                cfg.y = y_pos
                cfg.width = width_size
                cfg.height = height_size

        window.connect('configure-event', _receive_configure_event)

        def _receive_window_state(widget, event):
            new_value = bool(event.new_window_state & Gdk.WindowState.MAXIMIZED)
            cfg.maximized = new_value

        window.connect('window-state-event', _receive_window_state)

        # After the window has been set up, we enable events again
        def _enable_window_events():
            self.__ignore_window_events = False
        util.idle_add(_enable_window_events)

        if show_window:
            window.show()
        if cfg.maximized:
            window.maximize()
Example #29
0
        def subscribeEvent_reply_(self, event, reply):
            """ handles a 'Subscribe to...' event"""
            filelist = event.paramDescriptorForKeyword_(aeKeyword(keyDirectObject))
            fileURLData = filelist.data()
            url = buffer(fileURLData.bytes(),0,fileURLData.length())
            url = str(url)
            print >>sys.stderr,("Subscribe to :"+url)
            util.idle_add(self.gp.subscribe_to_url, url)

            result = NSAppleEventDescriptor.descriptorWithInt32_(42)
            reply.setParamDescriptor_forKeyword_(result, aeKeyword('----'))
Example #30
0
        def subscribeEvent_reply_(self, event, reply):
            """ handles a 'Subscribe to...' event"""
            filelist = event.paramDescriptorForKeyword_(aeKeyword(keyDirectObject))
            fileURLData = filelist.data()
            url = buffer(fileURLData.bytes(),0,fileURLData.length())
            url = str(url)
            print(("Subscribe to :" + url), file=sys.stderr)
            util.idle_add(self.gp.subscribe_to_url, url)

            result = NSAppleEventDescriptor.descriptorWithInt32_(42)
            reply.setParamDescriptor_forKeyword_(result, aeKeyword('----'))
Example #31
0
    def connect_gtk_window(self, window, config_prefix, show_window=False):
        cfg = getattr(self.ui.gtk.state, config_prefix)

        if gpodder.ui.win32:
            window.set_gravity(Gdk.Gravity.STATIC)

        if cfg.width != -1 and cfg.height != -1:
            window.resize(cfg.width, cfg.height)

        # Not all platforms can natively restore position, gPodder must handle it.
        # https://github.com/gpodder/gpodder/pull/933#issuecomment-818039693
        if cfg.x == -1 or cfg.y == -1:
            window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
        else:
            window.move(cfg.x, cfg.y)

        # Ignore events while we're connecting to the window
        self.__ignore_window_events = True

        # Get window state, correct size comes from window.get_size(),
        # see https://developer.gnome.org/SaveWindowState/
        def _receive_configure_event(widget, event):
            x_pos, y_pos = widget.get_position()
            width_size, height_size = widget.get_size()
            maximized = bool(event.window.get_state()
                             & Gdk.WindowState.MAXIMIZED)
            if not self.__ignore_window_events and not maximized:
                cfg.x = x_pos
                cfg.y = y_pos
                cfg.width = width_size
                cfg.height = height_size

        window.connect('configure-event', _receive_configure_event)

        def _receive_window_state(widget, event):
            # ELL: why is it commented out?
            # new_value = bool(event.new_window_state & Gdk.WindowState.MAXIMIZED)
            # cfg.maximized = new_value
            pass

        window.connect('window-state-event', _receive_window_state)

        # After the window has been set up, we enable events again
        def _enable_window_events():
            self.__ignore_window_events = False

        util.idle_add(_enable_window_events)

        if show_window:
            window.show()
        if cfg.maximized:
            window.maximize()
Example #32
0
    def replace_from_channel(self,
                             channel,
                             include_description=False,
                             treeview=None):
        """
        Add episode from the given channel to this model.
        Downloading should be a callback.
        include_description should be a boolean value (True if description
        is to be added to the episode row, or False if not)
        """

        # Remove old episodes in the list store
        self.clear()

        if treeview is not None:
            util.idle_add(treeview.queue_draw)

        self._all_episodes_view = getattr(channel, 'ALL_EPISODES_PROXY', False)

        # Avoid gPodder bug 1291
        if channel is None:
            episodes = []
        else:
            episodes = channel.get_all_episodes()

        if not isinstance(episodes, list):
            episodes = list(episodes)
        count = len(episodes)

        for position, episode in enumerate(episodes):
            iter = self.append((episode.url, \
                    episode.title, \
                    self._format_filesize(episode), \
                    episode, \
                    None, \
                    episode.cute_pubdate(), \
                    '', \
                    '', \
                    True, \
                    True, \
                    True, \
                    episode.file_size, \
                    episode.published, \
                    episode.get_play_info_string(), \
                    bool(episode.total_time), \
                    episode.total_time, \
                    episode.archive))

            self.update_by_iter(iter, include_description)

        self._on_filter_changed(self.has_episodes())
Example #33
0
    def replace_from_channel(self, channel, include_description=False,
            treeview=None):
        """
        Add episode from the given channel to this model.
        Downloading should be a callback.
        include_description should be a boolean value (True if description
        is to be added to the episode row, or False if not)
        """

        # Remove old episodes in the list store
        self.clear()

        if treeview is not None:
            util.idle_add(treeview.queue_draw)

        self._all_episodes_view = getattr(channel, 'ALL_EPISODES_PROXY', False)

        # Avoid gPodder bug 1291
        if channel is None:
            episodes = []
        else:
            episodes = channel.get_all_episodes()

        if not isinstance(episodes, list):
            episodes = list(episodes)
        count = len(episodes)

        for position, episode in enumerate(episodes):
            iter = self.append((episode.url, \
                    episode.title, \
                    self._format_filesize(episode), \
                    episode, \
                    None, \
                    episode.cute_pubdate(), \
                    '', \
                    '', \
                    True, \
                    True, \
                    True, \
                    episode.file_size, \
                    episode.published, \
                    episode.get_play_info_string(), \
                    bool(episode.total_time), \
                    episode.total_time, \
                    episode.archive))

            self.update_by_iter(iter, include_description)

        self._on_filter_changed(self.has_episodes())
Example #34
0
 def thread_proc():
     try:
         devices = self.mygpo_client.get_devices()
     except Exception, e:
         indicator.on_finished()
         def show_error(e):
             if str(e):
                 message = str(e)
             else:
                 message = e.__class__.__name__
             self.show_message(message,
                     _('Error getting list'),
                     important=True)
         util.idle_add(show_error, e)
         return
Example #35
0
    def on_web_request(self, web_view, web_frame, web_resource, request, response):
        uri = request.get_uri()
        if uri.startswith(self.flattr.CALLBACK):
            uri_parsed = urlparse.urlparse(uri)
            query = urlparse.parse_qs(uri_parsed.path[2:])
            if 'code' in query:
                code = query['code'][0]
                token = self.flattr.request_access_token(code)
                self._config.flattr.token = token
            else:
                self.show_message(query['error_description'][0], _('Error'),
                        important=True)

            # Destroy the window later
            util.idle_add(self.main_window.destroy)
Example #36
0
    def _run_and_log(self, cmd):
        """Utility: get cmd's output in real time and log it through logger"""
        p = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            universal_newlines=True,
        )

        for line in iter(p.stdout.readline, b''):
            util.idle_add(self.logger._log,"\t"+line.rstrip())
        p.stdout.close()
        status = p.wait()
        if status != 0:
            self.logger.error("%r exited with code %i" % (cmd, status))
        return (status == 0)
    def thread_func(self, tab=0):
        if tab == 1:
            model = OpmlListModel(opml.Importer(self._config.toplist_url))
            if len(model) == 0:
                self.notification(_('The specified URL does not provide any valid OPML podcast items.'), _('No feeds found'))
        elif tab == 2:
            model = OpmlListModel(youtube.find_youtube_channels(self.entryYoutubeSearch.get_text()))
            if len(model) == 0:
                self.notification(_('There are no YouTube channels that would match this query.'), _('No channels found'))
        else:
            url = self.entryURL.get_text()
            model = OpmlListModel(opml.Importer(url))
            if len(model) == 0:
                self.notification(_('The specified URL does not provide any valid OPML podcast items.'), _('No feeds found'))

        util.idle_add(self.thread_finished, model, tab)
Example #38
0
    def use_provider(self, provider):
        self.podcasts_model.clear()
        self.current_provider = provider

        if provider.kind == directory.Provider.PROVIDER_SEARCH:
            self.lb_search.set_text("Search:")
            self.bt_search.set_label("Search")
        elif provider.kind == directory.Provider.PROVIDER_URL:
            self.lb_search.set_text("URL:")
            self.bt_search.set_label("Download")
        elif provider.kind == directory.Provider.PROVIDER_FILE:
            self.lb_search.set_text("Filename:")
            self.bt_search.set_label("Open")
        elif provider.kind == directory.Provider.PROVIDER_TAGCLOUD:
            self.tag_cloud.clear_tags()

            @util.run_in_background
            def load_tags():
                try:
                    tags = [(t.tag, t.weight) for t in provider.get_tags()]
                except Exception as e:
                    logger.warn("Got exception while loading tags: %s", e)
                    tags = []

                @util.idle_add
                def update_ui():
                    self.tag_cloud.set_tags(tags)

        elif provider.kind == directory.Provider.PROVIDER_STATIC:
            self.obtain_podcasts_with(provider.on_static)

        if provider.kind in (
            directory.Provider.PROVIDER_SEARCH,
            directory.Provider.PROVIDER_URL,
            directory.Provider.PROVIDER_FILE,
        ):
            self.en_query.set_text("")
            self.hb_text_entry.show()
            util.idle_add(self.en_query.grab_focus)
        else:
            self.hb_text_entry.hide()

        if provider.kind == directory.Provider.PROVIDER_TAGCLOUD:
            self.sw_tagcloud.show()
        else:
            self.sw_tagcloud.hide()
Example #39
0
        def openFileEvent_reply_(self, event, reply):
            """ handles an 'Open With...' event"""
            urls = []
            filelist = event.paramDescriptorForKeyword_(aeKeyword(keyDirectObject))
            numberOfItems = filelist.numberOfItems()
            for i in range(1,numberOfItems+1):
                fileAliasDesc = filelist.descriptorAtIndex_(i)
                fileURLDesc = fileAliasDesc.coerceToDescriptorType_(aeKeyword(typeFileURL))
                fileURLData = fileURLDesc.data()
                url = buffer(fileURLData.bytes(),0,fileURLData.length())
                url = str(url)
                util.idle_add(self.gp.on_item_import_from_file_activate, None,url)
                urls.append(str(url))

            print >>sys.stderr,("open Files :",urls)
            result = NSAppleEventDescriptor.descriptorWithInt32_(42)
            reply.setParamDescriptor_forKeyword_(result, aeKeyword('----'))
Example #40
0
        def openFileEvent_reply_(self, event, reply):
            """ handles an 'Open With...' event"""
            urls = []
            filelist = event.paramDescriptorForKeyword_(aeKeyword(keyDirectObject))
            numberOfItems = filelist.numberOfItems()
            for i in range(1, numberOfItems + 1):
                fileAliasDesc = filelist.descriptorAtIndex_(i)
                fileURLDesc = fileAliasDesc.coerceToDescriptorType_(aeKeyword(typeFileURL))
                fileURLData = fileURLDesc.data()
                url = buffer(fileURLData.bytes(),0,fileURLData.length())
                url = str(url)
                util.idle_add(self.gp.on_item_import_from_file_activate, None,url)
                urls.append(str(url))

            print(("open Files :",urls), file=sys.stderr)
            result = NSAppleEventDescriptor.descriptorWithInt32_(42)
            reply.setParamDescriptor_forKeyword_(result, aeKeyword('----'))
Example #41
0
    def connect_gtk_window(self, window, config_prefix, show_window=False):
        cfg = getattr(self.ui.gtk.state, config_prefix)

        if gpodder.ui.win32:
            window.set_gravity(Gdk.GRAVITY_STATIC)

        window.resize(cfg.width, cfg.height)
        if cfg.x == -1 or cfg.y == -1:
            window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
        else:
            window.move(cfg.x, cfg.y)

        # Ignore events while we're connecting to the window
        self.__ignore_window_events = True

        def _receive_configure_event(widget, event):
            x_pos, y_pos = event.x, event.y
            width_size, height_size = event.width, event.height
            maximized = bool(event.window.get_state()
                             & Gdk.WindowState.MAXIMIZED)
            if not self.__ignore_window_events and not maximized:
                cfg.x = x_pos
                cfg.y = y_pos
                cfg.width = width_size
                cfg.height = height_size

        window.connect('configure-event', _receive_configure_event)

        def _receive_window_state(widget, event):
            # ELL: why is it commented out?
            #new_value = bool(event.new_window_state & Gdk.WindowState.MAXIMIZED)
            #cfg.maximized = new_value
            pass

        window.connect('window-state-event', _receive_window_state)

        # After the window has been set up, we enable events again
        def _enable_window_events():
            self.__ignore_window_events = False

        util.idle_add(_enable_window_events)

        if show_window:
            window.show()
        if cfg.maximized:
            window.maximize()
Example #42
0
    def update_status( self, id, **kwargs):
        if not id in self.status_list:
            return

        iter=self.status_list[id]['iter']
        if iter:
            self.tree_model_lock.acquire()
            for ( column, key ) in self.COLUMN_NAMES.items():
                if key in kwargs:
                    util.idle_add(self.tree_model.set, iter, column, kwargs[key])
                    self.status_list[id][key]=kwargs[key]
            self.tree_model_lock.release()

        if 'progress' in kwargs and 'speed' in kwargs and 'url' in self.status_list[id]:
            self.notify( 'progress-detail', self.status_list[id]['url'], kwargs['progress'], kwargs['speed'])

        self.notify_progress()
Example #43
0
    def connect_gtk_window(self, window, config_prefix, show_window=False):
        x, y, width, height, maximized = map(lambda x: config_prefix+'_'+x, \
                ('x', 'y', 'width', 'height', 'maximized'))

        if set((x, y, width, height)).issubset(set(self.Settings)):
            window.resize(getattr(self, width), getattr(self, height))
            if getattr(self, x) == -1 or getattr(self, y) == -1:
                window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
            else:
                window.move(getattr(self, x), getattr(self, y))

            # Ignore events while we're connecting to the window
            self.__ignore_window_events = True

            def _receive_configure_event(widget, event):
                x_pos, y_pos = widget.get_position()
                width_size, height_size = widget.get_size()
                if not self.__ignore_window_events and not \
                       (hasattr(self, maximized) and getattr(self, maximized)):
                    setattr(self, x, x_pos)
                    setattr(self, y, y_pos)
                    setattr(self, width, width_size)
                    setattr(self, height, height_size)

            window.connect('configure-event', _receive_configure_event)

            def _receive_window_state(widget, event):
                new_value = bool(event.new_window_state & \
                        gtk.gdk.WINDOW_STATE_MAXIMIZED)
                if hasattr(self, maximized):
                    setattr(self, maximized, new_value)

            window.connect('window-state-event', _receive_window_state)

            # After the window has been set up, we enable events again
            def _enable_window_events():
                self.__ignore_window_events = False
            util.idle_add(_enable_window_events)

            if show_window:
                window.show()
            if getattr(self, maximized, False):
                window.maximize()
        else:
            raise ValueError('Cannot connect %s', config_prefix, sender=self)
Example #44
0
    def connect_gtk_window(self, window, config_prefix, show_window=False):
        x, y, width, height, maximized = map(lambda x: config_prefix+'_'+x, \
                ('x', 'y', 'width', 'height', 'maximized'))

        if set((x, y, width, height)).issubset(set(self.Settings)):
            window.resize(getattr(self, width), getattr(self, height))
            if getattr(self, x) == -1 or getattr(self, y) == -1:
                window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
            else:
                window.move(getattr(self, x), getattr(self, y))

            # Ignore events while we're connecting to the window
            self.__ignore_window_events = True

            def _receive_configure_event(widget, event):
                x_pos, y_pos = widget.get_position()
                width_size, height_size = widget.get_size()
                if not self.__ignore_window_events and not \
                       (hasattr(self, maximized) and getattr(self, maximized)):
                    setattr(self, x, x_pos)
                    setattr(self, y, y_pos)
                    setattr(self, width, width_size)
                    setattr(self, height, height_size)

            window.connect('configure-event', _receive_configure_event)

            def _receive_window_state(widget, event):
                new_value = bool(event.new_window_state & \
                        gtk.gdk.WINDOW_STATE_MAXIMIZED)
                if hasattr(self, maximized):
                    setattr(self, maximized, new_value)

            window.connect('window-state-event', _receive_window_state)

            # After the window has been set up, we enable events again
            def _enable_window_events():
                self.__ignore_window_events = False
            util.idle_add(_enable_window_events)

            if show_window:
                window.show()
            if getattr(self, maximized, False):
                window.maximize()
        else:
            raise ValueError('Cannot connect %s', config_prefix, sender=self)
Example #45
0
    def do_startup(self):
        Gtk.Application.do_startup(self)

        self.create_actions()

        builder = Gtk.Builder()
        builder.set_translation_domain(gpodder.textdomain)

        for ui_folder in gpodder.ui_folders:
            filename = os.path.join(ui_folder, 'gtk/menus.ui')
            if os.path.exists(filename):
                builder.add_from_file(filename)
                break

        menubar = builder.get_object('menubar')
        if menubar is None:
            logger.error('Cannot find gtk/menus.ui in %r, exiting' %
                         gpodder.ui_folders)
            sys.exit(1)

        self.menu_view_columns = builder.get_object('menuViewColumns')
        self.set_menubar(menubar)

        self.set_app_menu(builder.get_object('app-menu'))

        Gtk.Window.set_default_icon_name('gpodder')

        try:
            dbus_main_loop = DBusGMainLoop(set_as_default=True)
            gpodder.dbus_session_bus = dbus.SessionBus(dbus_main_loop)

            self.bus_name = dbus.service.BusName(gpodder.dbus_bus_name,
                                                 bus=gpodder.dbus_session_bus)
        except dbus.exceptions.DBusException as dbe:
            logger.warn('Cannot get "on the bus".', exc_info=True)
            dlg = Gtk.MessageDialog(None, Gtk.DialogFlags.MODAL,
                                    Gtk.MessageType.ERROR,
                                    Gtk.ButtonsType.CLOSE,
                                    _('Cannot start gPodder'))
            dlg.format_secondary_markup(_('D-Bus error: %s') % (str(dbe), ))
            dlg.set_title('gPodder')
            dlg.run()
            dlg.destroy()
            sys.exit(0)
        util.idle_add(self.check_root_folder_path_gui)
Example #46
0
    def thread_func(self, tab=0):
        if tab == 1:
            model = OpmlListModel(opml.Importer(my.TOPLIST_OPML))
            if len(model) == 0:
                self.notification(_('The specified URL does not provide any valid OPML podcast items.'), _('No feeds found'))
        elif tab == 2:
            model = OpmlListModel(youtube.find_youtube_channels(self.entryYoutubeSearch.get_text()))
            if len(model) == 0:
                self.notification(_('There are no YouTube channels that would match this query.'), _('No channels found'))
        else:
            url = self.entryURL.get_text()
            if self.is_search_term(url):
                url = 'http://gpodder.net/search.opml?q=' + urllib.quote(url)
            model = OpmlListModel(opml.Importer(url))
            if len(model) == 0:
                self.notification(_('The specified URL does not provide any valid OPML podcast items.'), _('No feeds found'))

        util.idle_add(self.thread_finished, model, tab)
Example #47
0
    def connect_gtk_window(self, window, config_prefix, show_window=False):
        cfg = getattr(self.ui.gtk.state, config_prefix)

        if gpodder.ui.win32:
            window.set_gravity(Gdk.Gravity.STATIC)

        window.resize(cfg.width, cfg.height)
        if cfg.x == -1 or cfg.y == -1:
            window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
        else:
            window.move(cfg.x, cfg.y)

        # Ignore events while we're connecting to the window
        self.__ignore_window_events = True

        def _receive_configure_event(widget, event):
            x_pos, y_pos = event.x, event.y
            width_size, height_size = event.width, event.height
            maximized = bool(event.window.get_state() & Gdk.WindowState.MAXIMIZED)
            if not self.__ignore_window_events and not maximized:
                cfg.x = x_pos
                cfg.y = y_pos
                cfg.width = width_size
                cfg.height = height_size

        window.connect('configure-event', _receive_configure_event)

        def _receive_window_state(widget, event):
            # ELL: why is it commented out?
            # new_value = bool(event.new_window_state & Gdk.WindowState.MAXIMIZED)
            # cfg.maximized = new_value
            pass

        window.connect('window-state-event', _receive_window_state)

        # After the window has been set up, we enable events again
        def _enable_window_events():
            self.__ignore_window_events = False
        util.idle_add(_enable_window_events)

        if show_window:
            window.show()
        if cfg.maximized:
            window.maximize()
Example #48
0
    def use_provider(self, provider):
        self.podcasts_model.clear()
        self.current_provider = provider

        if provider.kind == directory.Provider.PROVIDER_SEARCH:
            self.lb_search.set_text(_('Search:'))
            self.bt_search.set_label(_('Search'))
        elif provider.kind == directory.Provider.PROVIDER_URL:
            self.lb_search.set_text(_('URL:'))
            self.bt_search.set_label(_('Download'))
        elif provider.kind == directory.Provider.PROVIDER_FILE:
            self.lb_search.set_text(_('Filename:'))
            self.bt_search.set_label(_('Open'))
        elif provider.kind == directory.Provider.PROVIDER_TAGCLOUD:
            self.tag_cloud.clear_tags()

            @util.run_in_background
            def load_tags():
                try:
                    tags = [(t.tag, t.weight) for t in provider.get_tags()]
                except Exception as e:
                    logger.warn('Got exception while loading tags: %s', e)
                    tags = []

                @util.idle_add
                def update_ui():
                    self.tag_cloud.set_tags(tags)
        elif provider.kind == directory.Provider.PROVIDER_STATIC:
            self.obtain_podcasts_with(provider.on_static)

        if provider.kind in (directory.Provider.PROVIDER_SEARCH,
                directory.Provider.PROVIDER_URL,
                directory.Provider.PROVIDER_FILE):
            self.en_query.set_text('')
            self.hb_text_entry.show()
            util.idle_add(self.en_query.grab_focus)
        else:
            self.hb_text_entry.hide()

        if provider.kind == directory.Provider.PROVIDER_TAGCLOUD:
            self.sw_tagcloud.show()
        else:
            self.sw_tagcloud.hide()
Example #49
0
        def cleanup_episodes():
            # 'skip_played_episodes' must be used or else all the
            # played tracks will be copied then immediately deleted
            if (self._config.device_sync.delete_played_episodes and
                    self._config.device_sync.skip_played_episodes):
                all_episodes = self._filter_sync_episodes(channels,
                        only_downloaded=False)
                for local_episode in all_episodes:
                    episode = device.episode_on_device(local_episode)
                    if episode is None:
                        continue

                    if local_episode.state == gpodder.STATE_DELETED:
                        logger.info('Removing episode from device: %s',
                                episode.title)
                        device.remove_track(episode)

            # When this is done, start the callback in the UI code
            util.idle_add(check_free_space)
Example #50
0
    def remove_download_id( self, id):
        if not id in self.status_list:
            return
        iter=self.status_list[id]['iter']
	if iter is not None:
            self.tree_model_lock.acquire()
            util.idle_add(self.remove_iter, iter)
            self.tree_model_lock.release()
            self.status_list[id]['iter']=None
            self.status_list[id]['thread'].cancel()
            del self.status_list[id]
            if not self.has_items():
                # Reset the counter now
                self.downloads_done_bytes=0
        if self.batch_mode_enabled:
            self.batch_mode_notify_flag=True
        else:
            self.notify('list-changed')
        self.notify_progress()
Example #51
0
        def cleanup_episodes():
            # 'skip_played_episodes' must be used or else all the
            # played tracks will be copied then immediately deleted
            if (self._config.device_sync.delete_played_episodes and
                    self._config.device_sync.skip_played_episodes):
                all_episodes = self._filter_sync_episodes(channels,
                        only_downloaded=False)
                for local_episode in all_episodes:
                    episode = device.episode_on_device(local_episode)
                    if episode is None:
                        continue

                    if local_episode.state == gpodder.STATE_DELETED:
                        logger.info('Removing episode from device: %s',
                                episode.title)
                        device.remove_track(episode)

            # When this is done, start the callback in the UI code
            util.idle_add(check_free_space)
Example #52
0
    def add_from_channel(self, channel, downloading=None, \
            include_description=False, generate_thumbnails=False, \
            treeview=None):
        """
        Add episode from the given channel to this model.
        Downloading should be a callback.
        include_description should be a boolean value (True if description
        is to be added to the episode row, or False if not)
        """

        self._update_progress = 0.
        self._last_redraw_progress = 0.
        if treeview is not None:
            util.idle_add(treeview.queue_draw)

        self._all_episodes_view = getattr(channel, 'ALL_EPISODES_PROXY', False)

        episodes = channel.get_all_episodes()
        if not isinstance(episodes, list):
            episodes = list(episodes)
        count = len(episodes)

        for position, episode in enumerate(episodes):
            iter = self.append()
            self.set(iter, \
                    self.C_URL, episode.url, \
                    self.C_TITLE, episode.title, \
                    self.C_FILESIZE_TEXT, self._format_filesize(episode), \
                    self.C_EPISODE, episode, \
                    self.C_PUBLISHED_TEXT, episode.cute_pubdate())
            self.update_by_iter(iter, downloading, include_description, \
                    generate_thumbnails, reload_from_db=False)

            self._update_progress = float(position+1)/count
            if treeview is not None and \
                    (self._update_progress > self._last_redraw_progress + self._UI_UPDATE_STEP or position+1 == count):
                def in_gtk_main_thread():
                    treeview.queue_draw()
                    while gtk.events_pending():
                        gtk.main_iteration(False)
                util.idle_add(in_gtk_main_thread)
                self._last_redraw_progress = self._update_progress
Example #53
0
        def download_thread_func():
            if use_youtube:
                importer = youtube.find_youtube_channels(url)
            else:
                importer = opml.Importer(url)

            if importer.items:
                model = OpmlListModel(importer)
            else:
                model = None
                self.show_message(_('Please pick another source.'), _('No podcasts found'))

            def download_thread_finished():
                if banner is not None:
                    banner.destroy()
                self.treeview.set_model(model)
                self.treeview.set_sensitive(True)
                self.button_cancel.set_sensitive(True)
                self.set_subscribe_button_sensitive()
            util.idle_add(download_thread_finished)
Example #54
0
    def connect_gtk_window(self, window, config_prefix, show_window=False):
        cfg = getattr(self.ui.gtk.state, config_prefix)

        window.resize(cfg.width, cfg.height)
        if cfg.x == -1 or cfg.y == -1:
            window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
        else:
            window.move(cfg.x, cfg.y)

        # Ignore events while we're connecting to the window
        self.__ignore_window_events = True

        def _receive_configure_event(widget, event):
            x_pos, y_pos = event.x, event.y
            width_size, height_size = event.width, event.height
            if not self.__ignore_window_events and not cfg.maximized:
                cfg.x = x_pos
                cfg.y = y_pos
                cfg.width = width_size
                cfg.height = height_size

        window.connect('configure-event', _receive_configure_event)

        def _receive_window_state(widget, event):
            new_value = bool(event.new_window_state
                             & gtk.gdk.WINDOW_STATE_MAXIMIZED)
            cfg.maximized = new_value

        window.connect('window-state-event', _receive_window_state)

        # After the window has been set up, we enable events again
        def _enable_window_events():
            self.__ignore_window_events = False

        util.idle_add(_enable_window_events)

        if show_window:
            window.show()
        if cfg.maximized:
            window.maximize()
Example #55
0
        def download_thread_func():
            if use_youtube:
                importer = youtube.find_youtube_channels(url)
            else:
                importer = opml.Importer(url)

            if importer.items:
                model = OpmlListModel(importer)
            else:
                model = None
                self.show_message(_('Please pick another source.'),
                                  _('No podcasts found'))

            def download_thread_finished():
                if banner is not None:
                    banner.destroy()
                self.treeview.set_model(model)
                self.treeview.set_sensitive(True)
                self.button_cancel.set_sensitive(True)
                self.set_subscribe_button_sensitive()

            util.idle_add(download_thread_finished)
Example #56
0
        def cleanup_episodes():
            # 'only_sync_not_played' must be used or else all the
            # played tracks will be copied then immediately deleted
            if self._config.mp3_player_delete_played and \
                    self._config.only_sync_not_played:
                all_episodes = self._filter_sync_episodes(channels, \
                        only_downloaded=False)
                episodes_on_device = device.get_all_tracks()
                for local_episode in all_episodes:
                    episode = device.episode_on_device(local_episode)
                    if episode is None:
                        continue

                    if local_episode.state == gpodder.STATE_DELETED \
                            or (local_episode.is_played and \
                                not local_episode.is_locked):
                        log('Removing episode from device: %s',
                            episode.title,
                            sender=self)
                        device.remove_track(episode)

            # When this is done, start the callback in the UI code
            util.idle_add(check_free_space)
Example #57
0
            def after_device_sync_callback(device, successful_sync):
                if device.cancelled:
                    log('Cancelled by user.', sender=self)
                elif successful_sync:
                    title = _('Device synchronized')
                    message = _('Your device has been synchronized.')
                    self.notification(message, title)
                else:
                    title = _('Error closing device')
                    message = _('Please check settings and permission.')
                    self.notification(message, title, important=True)

                # Update the UI to reflect changes from the sync process
                episode_urls = set()
                channel_urls = set()
                for episode in episodes:
                    episode_urls.add(episode.url)
                    channel_urls.add(episode.channel.url)
                util.idle_add(self.update_episode_list_icons, episode_urls)
                util.idle_add(self.update_podcast_list_model, channel_urls)
                util.idle_add(self.commit_changes_to_database)
Example #58
0
 def notification(self, message, title=None, important=False, widget=None):
     util.idle_add(self.show_message, message, title, important, widget)
Example #59
0
 def register_task(self, task):
     util.idle_add(self.__add_new_task, task)
Example #60
0
 def get_next(self):
     dqr = DequeueRequest()
     util.idle_add(self.__get_next, dqr)
     return dqr.dequeue()