def on_show_close_splash(self, subject, changetype, objectID, *args): gui_image_manager = GuiImageManager.getInstance() bm = gui_image_manager.getImage(u'closescreen.png') self.close_splash = GaugeSplash(bm, "Closing...", self.CLOSE_GAUGE_SPLASH_TICKS) if self.close_completed: self.destroy_close_splash(None, None, None, None)
def on_show_startup_splash(self, subject, changetype, objectID, *args): gui_image_manager = GuiImageManager.getInstance() bm = gui_image_manager.getImage(u'splash.png') self.startup_splash = GaugeSplash(bm, "Loading...", self.START_GAUGE_SPLASH_TICKS) # Check if the destroy message has already arrived. Loading the splash takes a while, # so the setup may have already been completed. if self.startup_completed: self.destroy_startup_splash(None, None, None, None)
def OnExit(self): bm = self.gui_image_manager.getImage(u'closescreen.png') self.closewindow = GaugeSplash(bm, "Closing...", 6) self.closewindow.Show() self._logger.info("main: ONEXIT") self.ready = False self.done = True # write all persistent data to disk self.closewindow.tick('Write all persistent data to disk') if self.torrentfeed: self.torrentfeed.shutdown() self.torrentfeed.delInstance() if self.webUI: self.webUI.stop() self.webUI.delInstance() if self.frame: self.frame.Destroy() self.frame = None # Don't checkpoint, interferes with current way of saving Preferences, # see Tribler/Main/Dialogs/abcoption.py if self.utility: # Niels: lets add a max waiting time for this session shutdown. session_shutdown_start = time() try: self._logger.info("ONEXIT cleaning database") self.closewindow.tick('Cleaning database') torrent_db = self.utility.session.open_dbhandler(NTFY_TORRENTS) torrent_db._db.clean_db(randint(0, 24) == 0, exiting=True) except: print_exc() self.closewindow.tick('Shutdown session') self.utility.session.shutdown(hacksessconfcheckpoint=False) # Arno, 2012-07-12: Shutdown should be quick # Niels, 2013-03-21: However, setting it too low will prevent checkpoints from being written to disk waittime = 60 while not self.utility.session.has_shutdown(): diff = time() - session_shutdown_start if diff > waittime: self._logger.info("main: ONEXIT NOT Waiting for Session to shutdown, took too long") break self._logger.info( "ONEXIT Waiting for Session to shutdown, will wait for an additional %d seconds", waittime - diff) sleep(3) self._logger.info("ONEXIT Session is shutdown") self.closewindow.tick('Deleting instances') self._logger.debug("ONEXIT deleting instances") Session.del_instance() GUIUtility.delInstance() GUIDBProducer.delInstance() DefaultDownloadStartupConfig.delInstance() GuiImageManager.delInstance() self.closewindow.tick('Exiting now') self.closewindow.Destroy() return 0
def __init__(self, params, installdir, autoload_discovery=True, use_torrent_search=True, use_channel_search=True): assert not isInIOThread(), "isInIOThread() seems to not be working correctly" self._logger = logging.getLogger(self.__class__.__name__) self.params = params self.installdir = installdir self.state_dir = None self.error = None self.last_update = 0 self.ready = False self.done = False self.frame = None self.upgrader = None self.said_start_playback = False self.decodeprogress = 0 self.old_reputation = 0 # DISPERSY will be set when available self.dispersy = None # BARTER_COMMUNITY will be set when both Dispersy and the EffortCommunity are available self.barter_community = None self.tunnel_community = None self.torrentfeed = None self.webUI = None self.utility = None # Stage 1 start session = self.InitStage1(installdir, autoload_discovery=autoload_discovery, use_torrent_search=use_torrent_search, use_channel_search=use_channel_search) self.splash = None try: bm = self.gui_image_manager.getImage(u'splash.png') self.splash = GaugeSplash(bm, "Loading...", 13) self.splash.Show() self._logger.info('Client Starting Up.') self._logger.info("Tribler is using %s as working directory", self.installdir) # Stage 2: show the splash window and start the session self.splash.tick('Starting API') s = self.startAPI(session, self.splash.tick) self.utility = Utility(self.installdir, s.get_state_dir()) if self.utility.read_config(u'saveas', u'downloadconfig'): DefaultDownloadStartupConfig.getInstance().set_dest_dir(self.utility.read_config(u'saveas', u'downloadconfig')) self.utility.set_app(self) self.utility.set_session(s) self.guiUtility = GUIUtility.getInstance(self.utility, self.params, self) GUIDBProducer.getInstance() self._logger.info('Tribler Version: %s Build: %s', version_id, commit_id) version_info = self.utility.read_config('version_info') if version_info.get('version_id', None) != version_id: # First run of a different version version_info['first_run'] = int(time()) version_info['version_id'] = version_id self.utility.write_config('version_info', version_info) self.splash.tick('Starting session and upgrading database (it may take a while)') s.start() self.dispersy = s.lm.dispersy self.splash.tick('Loading userdownloadchoice') from Tribler.Main.vwxGUI.UserDownloadChoice import UserDownloadChoice UserDownloadChoice.get_singleton().set_utility(self.utility) self.splash.tick('Initializing Family Filter') cat = Category.getInstance(session) state = self.utility.read_config('family_filter') if state in (1, 0): cat.set_family_filter(state == 1) else: self.utility.write_config('family_filter', 1) self.utility.flush_config() cat.set_family_filter(True) # Create global speed limits self.splash.tick('Setting up speed limits') # Counter to suppress some event from occurring self.ratestatecallbackcount = 0 maxup = self.utility.read_config('maxuploadrate') maxdown = self.utility.read_config('maxdownloadrate') # set speed limits using LibtorrentMgr s.set_max_upload_speed(maxup) s.set_max_download_speed(maxdown) # Only allow updates to come in after we defined ratelimiter self.prevActiveDownloads = [] s.set_download_states_callback(self.sesscb_states_callback) # Schedule task for checkpointing Session, to avoid hash checks after # crashes. startWorker(consumer=None, workerFn=self.guiservthread_checkpoint_timer, delay=SESSION_CHECKPOINT_INTERVAL) if not ALLOW_MULTIPLE: # Put it here so an error is shown in the startup-error popup # Start server for instance2instance communication Instance2InstanceServer(self.utility.read_config('i2ilistenport'), self.i2ithread_readlinecallback) self.splash.tick('GUIUtility register') self.guiUtility.register() self.frame = MainFrame(self, None, PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(), self.splash.tick) self.frame.SetIcon(wx.Icon(os.path.join(self.installdir, 'Tribler', 'Main', 'vwxGUI', 'images', 'tribler.ico'), wx.BITMAP_TYPE_ICO)) # Arno, 2011-06-15: VLC 1.1.10 pops up separate win, don't have two. self.frame.videoframe = None if PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(): vlcwrap = s.lm.videoplayer.get_vlcwrap() wx.CallLater(3000, vlcwrap._init_vlc) self.frame.videoframe = VideoDummyFrame(self.frame.videoparentpanel, self.utility, vlcwrap) if sys.platform == 'win32': wx.CallAfter(self.frame.top_bg.Refresh) wx.CallAfter(self.frame.top_bg.Layout) else: self.frame.top_bg.Layout() # Arno, 2007-05-03: wxWidgets 2.8.3.0 and earlier have the MIME-type for .bmp # files set to 'image/x-bmp' whereas 'image/bmp' is the official one. try: bmphand = None hands = wx.Image.GetHandlers() for hand in hands: # print "Handler",hand.GetExtension(),hand.GetType(),hand.GetMimeType() if hand.GetMimeType() == 'image/x-bmp': bmphand = hand break # wx.Image.AddHandler() if bmphand is not None: bmphand.SetMimeType('image/bmp') except: # wx < 2.7 don't like wx.Image.GetHandlers() print_exc() self.splash.Destroy() self.frame.Show(True) session.lm.threadpool.call_in_thread(0, self.guiservthread_free_space_check) self.torrentfeed = RssParser.getInstance() self.webUI = None if self.utility.read_config('use_webui'): try: from Tribler.Main.webUI.webUI import WebUI self.webUI = WebUI.getInstance(self.guiUtility.library_manager, self.guiUtility.torrentsearch_manager, self.utility.read_config('webui_port')) self.webUI.start() except Exception: print_exc() self.emercoin_mgr = None try: from Tribler.Main.Emercoin.EmercoinMgr import EmercoinMgr self.emercoin_mgr = EmercoinMgr(self.utility) except Exception: print_exc() wx.CallAfter(self.PostInit2) # 08/02/10 Boudewijn: Working from home though console # doesn't allow me to press close. The statement below # gracefully closes Tribler after 120 seconds. # wx.CallLater(120*1000, wx.GetApp().Exit) self.ready = True except Exception as e: if self.splash: self.splash.Destroy() self.onError(e)
class ABCApp(object): def __init__(self, params, installdir, autoload_discovery=True, use_torrent_search=True, use_channel_search=True): assert not isInIOThread(), "isInIOThread() seems to not be working correctly" self._logger = logging.getLogger(self.__class__.__name__) self.params = params self.installdir = installdir self.state_dir = None self.error = None self.last_update = 0 self.ready = False self.done = False self.frame = None self.upgrader = None self.said_start_playback = False self.decodeprogress = 0 self.old_reputation = 0 # DISPERSY will be set when available self.dispersy = None # BARTER_COMMUNITY will be set when both Dispersy and the EffortCommunity are available self.barter_community = None self.tunnel_community = None self.torrentfeed = None self.webUI = None self.utility = None # Stage 1 start session = self.InitStage1(installdir, autoload_discovery=autoload_discovery, use_torrent_search=use_torrent_search, use_channel_search=use_channel_search) self.splash = None try: bm = self.gui_image_manager.getImage(u'splash.png') self.splash = GaugeSplash(bm, "Loading...", 13) self.splash.Show() self._logger.info('Client Starting Up.') self._logger.info("Tribler is using %s as working directory", self.installdir) # Stage 2: show the splash window and start the session self.splash.tick('Starting API') s = self.startAPI(session, self.splash.tick) self.utility = Utility(self.installdir, s.get_state_dir()) if self.utility.read_config(u'saveas', u'downloadconfig'): DefaultDownloadStartupConfig.getInstance().set_dest_dir(self.utility.read_config(u'saveas', u'downloadconfig')) self.utility.set_app(self) self.utility.set_session(s) self.guiUtility = GUIUtility.getInstance(self.utility, self.params, self) GUIDBProducer.getInstance() self._logger.info('Tribler Version: %s Build: %s', version_id, commit_id) version_info = self.utility.read_config('version_info') if version_info.get('version_id', None) != version_id: # First run of a different version version_info['first_run'] = int(time()) version_info['version_id'] = version_id self.utility.write_config('version_info', version_info) self.splash.tick('Starting session and upgrading database (it may take a while)') s.start() self.dispersy = s.lm.dispersy self.splash.tick('Loading userdownloadchoice') from Tribler.Main.vwxGUI.UserDownloadChoice import UserDownloadChoice UserDownloadChoice.get_singleton().set_utility(self.utility) self.splash.tick('Initializing Family Filter') cat = Category.getInstance(session) state = self.utility.read_config('family_filter') if state in (1, 0): cat.set_family_filter(state == 1) else: self.utility.write_config('family_filter', 1) self.utility.flush_config() cat.set_family_filter(True) # Create global speed limits self.splash.tick('Setting up speed limits') # Counter to suppress some event from occurring self.ratestatecallbackcount = 0 maxup = self.utility.read_config('maxuploadrate') maxdown = self.utility.read_config('maxdownloadrate') # set speed limits using LibtorrentMgr s.set_max_upload_speed(maxup) s.set_max_download_speed(maxdown) # Only allow updates to come in after we defined ratelimiter self.prevActiveDownloads = [] s.set_download_states_callback(self.sesscb_states_callback) # Schedule task for checkpointing Session, to avoid hash checks after # crashes. startWorker(consumer=None, workerFn=self.guiservthread_checkpoint_timer, delay=SESSION_CHECKPOINT_INTERVAL) if not ALLOW_MULTIPLE: # Put it here so an error is shown in the startup-error popup # Start server for instance2instance communication Instance2InstanceServer(self.utility.read_config('i2ilistenport'), self.i2ithread_readlinecallback) self.splash.tick('GUIUtility register') self.guiUtility.register() self.frame = MainFrame(self, None, PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(), self.splash.tick) self.frame.SetIcon(wx.Icon(os.path.join(self.installdir, 'Tribler', 'Main', 'vwxGUI', 'images', 'tribler.ico'), wx.BITMAP_TYPE_ICO)) # Arno, 2011-06-15: VLC 1.1.10 pops up separate win, don't have two. self.frame.videoframe = None if PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(): vlcwrap = s.lm.videoplayer.get_vlcwrap() wx.CallLater(3000, vlcwrap._init_vlc) self.frame.videoframe = VideoDummyFrame(self.frame.videoparentpanel, self.utility, vlcwrap) if sys.platform == 'win32': wx.CallAfter(self.frame.top_bg.Refresh) wx.CallAfter(self.frame.top_bg.Layout) else: self.frame.top_bg.Layout() # Arno, 2007-05-03: wxWidgets 2.8.3.0 and earlier have the MIME-type for .bmp # files set to 'image/x-bmp' whereas 'image/bmp' is the official one. try: bmphand = None hands = wx.Image.GetHandlers() for hand in hands: # print "Handler",hand.GetExtension(),hand.GetType(),hand.GetMimeType() if hand.GetMimeType() == 'image/x-bmp': bmphand = hand break # wx.Image.AddHandler() if bmphand is not None: bmphand.SetMimeType('image/bmp') except: # wx < 2.7 don't like wx.Image.GetHandlers() print_exc() self.splash.Destroy() self.frame.Show(True) session.lm.threadpool.call_in_thread(0, self.guiservthread_free_space_check) self.torrentfeed = RssParser.getInstance() self.webUI = None if self.utility.read_config('use_webui'): try: from Tribler.Main.webUI.webUI import WebUI self.webUI = WebUI.getInstance(self.guiUtility.library_manager, self.guiUtility.torrentsearch_manager, self.utility.read_config('webui_port')) self.webUI.start() except Exception: print_exc() self.emercoin_mgr = None try: from Tribler.Main.Emercoin.EmercoinMgr import EmercoinMgr self.emercoin_mgr = EmercoinMgr(self.utility) except Exception: print_exc() wx.CallAfter(self.PostInit2) # 08/02/10 Boudewijn: Working from home though console # doesn't allow me to press close. The statement below # gracefully closes Tribler after 120 seconds. # wx.CallLater(120*1000, wx.GetApp().Exit) self.ready = True except Exception as e: if self.splash: self.splash.Destroy() self.onError(e) def InitStage1(self, installdir, autoload_discovery=True, use_torrent_search=True, use_channel_search=True): """ Stage 1 start: pre-start the session to handle upgrade. """ # Make sure the installation dir is on the PATH os.environ['PATH'] += os.pathsep + os.path.abspath(installdir) self.gui_image_manager = GuiImageManager.getInstance(installdir) # Start Tribler Session defaultConfig = SessionStartupConfig() state_dir = defaultConfig.get_state_dir() # Switch to the state dir so relative paths can be used (IE, in LevelDB store paths) if not os.path.exists(state_dir): os.makedirs(state_dir) os.chdir(state_dir) cfgfilename = Session.get_default_config_filename(state_dir) self._logger.debug(u"Session config %s", cfgfilename) try: self.sconfig = SessionStartupConfig.load(cfgfilename) except: try: self.sconfig = convertSessionConfig(os.path.join(state_dir, 'sessconfig.pickle'), cfgfilename) convertMainConfig(state_dir, os.path.join(state_dir, 'abc.conf'), os.path.join(state_dir, STATEDIR_GUICONFIG)) except: self.sconfig = SessionStartupConfig() self.sconfig.set_state_dir(state_dir) self.sconfig.set_install_dir(self.installdir) # TODO(emilon): Do we still want to force limit this? With the new # torrent store it should be pretty fast even with more that that. # Arno, 2010-03-31: Hard upgrade to 50000 torrents collected self.sconfig.set_torrent_collecting_max_torrents(50000) dlcfgfilename = get_default_dscfg_filename(self.sconfig.get_state_dir()) self._logger.debug("main: Download config %s", dlcfgfilename) try: defaultDLConfig = DefaultDownloadStartupConfig.load(dlcfgfilename) except: try: defaultDLConfig = convertDefaultDownloadConfig( os.path.join(state_dir, 'dlconfig.pickle'), dlcfgfilename) except: defaultDLConfig = DefaultDownloadStartupConfig.getInstance() if not defaultDLConfig.get_dest_dir(): defaultDLConfig.set_dest_dir(get_default_dest_dir()) if not os.path.isdir(defaultDLConfig.get_dest_dir()): try: os.makedirs(defaultDLConfig.get_dest_dir()) except: # Could not create directory, ask user to select a different location dlg = wx.DirDialog(None, "Could not find download directory, please select a new location to store your downloads", style=wx.DEFAULT_DIALOG_STYLE) dlg.SetPath(get_default_dest_dir()) if dlg.ShowModal() == wx.ID_OK: new_dest_dir = dlg.GetPath() defaultDLConfig.set_dest_dir(new_dest_dir) defaultDLConfig.save(dlcfgfilename) self.sconfig.save(cfgfilename) else: # Quit self.onError = lambda e: self._logger.error( "tribler: quitting due to non-existing destination directory") raise Exception() if not use_torrent_search: self.sconfig.set_enable_torrent_search(False) if not use_channel_search: self.sconfig.set_enable_channel_search(False) session = Session(self.sconfig, autoload_discovery=autoload_discovery) session.add_observer(self.show_upgrade_dialog, NTFY_UPGRADER, [NTFY_STARTED]) self.upgrader = session.prestart() while not self.upgrader.is_done: wx.SafeYield() sleep(0.1) return session @forceWxThread def show_upgrade_dialog(self, subject, changetype, objectID, *args): assert wx.Thread_IsMain() upgrade_dialog = TriblerUpgradeDialog(self.gui_image_manager, self.upgrader) failed = upgrade_dialog.ShowModal() upgrade_dialog.Destroy() if failed: wx.MessageDialog(None, "Failed to upgrade the on disk data.\n\n" "Tribler has backed up the old data and will now start from scratch.\n\n" "Get in contact with the Tribler team if you want to help debugging this issue.\n\n" "Error was: %s" % self.upgrader.current_status, "Data format upgrade failed", wx.OK | wx.CENTRE | wx.ICON_EXCLAMATION).ShowModal() def _frame_and_ready(self): return self.ready and self.frame and self.frame.ready def PostInit2(self): self.frame.Raise() self.startWithRightView() self.set_reputation() s = self.utility.session s.add_observer(self.sesscb_ntfy_reachable, NTFY_REACHABLE, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_activities, NTFY_ACTIVITIES, [NTFY_INSERT], cache=10) s.add_observer(self.sesscb_ntfy_channelupdates, NTFY_CHANNELCAST, [NTFY_INSERT, NTFY_UPDATE, NTFY_CREATE, NTFY_STATE, NTFY_MODIFIED], cache=10) s.add_observer(self.sesscb_ntfy_channelupdates, NTFY_VOTECAST, [NTFY_UPDATE], cache=10) s.add_observer(self.sesscb_ntfy_myprefupdates, NTFY_MYPREFERENCES, [NTFY_INSERT, NTFY_UPDATE, NTFY_DELETE]) s.add_observer(self.sesscb_ntfy_torrentupdates, NTFY_TORRENTS, [NTFY_UPDATE, NTFY_INSERT], cache=10) s.add_observer(self.sesscb_ntfy_playlistupdates, NTFY_PLAYLISTS, [NTFY_INSERT, NTFY_UPDATE]) s.add_observer(self.sesscb_ntfy_commentupdates, NTFY_COMMENTS, [NTFY_INSERT, NTFY_DELETE]) s.add_observer(self.sesscb_ntfy_modificationupdates, NTFY_MODIFICATIONS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_moderationupdats, NTFY_MODERATIONS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_markingupdates, NTFY_MARKINGS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_torrentfinished, NTFY_TORRENTS, [NTFY_FINISHED]) s.add_observer(self.sesscb_ntfy_magnet, NTFY_TORRENTS, [NTFY_MAGNET_GOT_PEERS, NTFY_MAGNET_STARTED, NTFY_MAGNET_CLOSE]) # TODO(emilon): Use the LogObserver I already implemented # self.dispersy.callback.attach_exception_handler(self.frame.exceptionHandler) startWorker(None, self.loadSessionCheckpoint, delay=5.0, workerType="ThreadPool") # initialize the torrent feed thread channelcast = s.open_dbhandler(NTFY_CHANNELCAST) def db_thread(): return channelcast.getMyChannelId() def wx_thread(delayedResult): my_channel = delayedResult.get() if my_channel: self.torrentfeed.register(self.utility.session, my_channel) self.torrentfeed.addCallback(my_channel, self.guiUtility.channelsearch_manager.createTorrentFromDef) startWorker(wx_thread, db_thread, delay=5.0) def startAPI(self, session, progress): @call_on_reactor_thread def define_communities(*args): assert isInIOThread() from Tribler.community.channel.community import ChannelCommunity from Tribler.community.channel.preview import PreviewChannelCommunity from Tribler.community.tunnel.tunnel_community import TunnelSettings from Tribler.community.tunnel.hidden_community import HiddenTunnelCommunity # make sure this is only called once session.remove_observer(define_communities) dispersy = session.get_dispersy_instance() self._logger.info("tribler: Preparing communities...") now = time() dispersy.attach_progress_handler(self.progressHandler) default_kwargs = {'tribler_session': session} # must be called on the Dispersy thread if session.get_barter_community_enabled(): from Tribler.community.bartercast4.community import BarterCommunity dispersy.define_auto_load(BarterCommunity, session.dispersy_member, load=True) # load metadata community dispersy.define_auto_load(ChannelCommunity, session.dispersy_member, load=True, kargs=default_kwargs) dispersy.define_auto_load(PreviewChannelCommunity, session.dispersy_member, kargs=default_kwargs) keypair = dispersy.crypto.generate_key(u"curve25519") dispersy_member = dispersy.get_member(private_key=dispersy.crypto.key_to_bin(keypair),) settings = TunnelSettings(session.get_install_dir(), tribler_session=session) tunnel_kwargs = {'tribler_session': session, 'settings': settings} self.tunnel_community = dispersy.define_auto_load(HiddenTunnelCommunity, dispersy_member, load=True, kargs=tunnel_kwargs)[0] session.set_anon_proxy_settings(2, ("127.0.0.1", session.get_tunnel_community_socks5_listen_ports())) diff = time() - now self._logger.info("tribler: communities are ready in %.2f seconds", diff) session.add_observer(define_communities, NTFY_DISPERSY, [NTFY_STARTED]) return session @forceWxThread def sesscb_ntfy_myprefupdates(self, subject, changeType, objectID, *args): if self._frame_and_ready(): if changeType in [NTFY_INSERT, NTFY_UPDATE]: if changeType == NTFY_INSERT: if self.frame.searchlist: manager = self.frame.searchlist.GetManager() manager.downloadStarted(objectID) manager = self.frame.selectedchannellist.GetManager() manager.downloadStarted(objectID) manager = self.frame.librarylist.GetManager() manager.downloadStarted(objectID) elif changeType == NTFY_DELETE: self.guiUtility.frame.librarylist.RemoveItem(objectID) if self.guiUtility.frame.librarylist.IsShownOnScreen() and \ self.guiUtility.frame.librarydetailspanel.torrent and \ self.guiUtility.frame.librarydetailspanel.torrent.infohash == objectID: self.guiUtility.frame.librarylist.ResetBottomWindow() self.guiUtility.frame.top_bg.ClearButtonHandlers() if self.guiUtility.frame.librarylist.list.IsEmpty(): self.guiUtility.frame.librarylist.SetData([]) def progressHandler(self, title, message, maximum): from Tribler.Main.Dialogs.ThreadSafeProgressDialog import ThreadSafeProgressDialog return ThreadSafeProgressDialog(title, message, maximum, None, wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME | wx.PD_ESTIMATED_TIME | wx.PD_REMAINING_TIME | wx.PD_AUTO_HIDE) def set_reputation(self): def do_db(): nr_connections = 0 nr_channel_connections = 0 if self.dispersy: for community in self.dispersy.get_communities(): from Tribler.community.search.community import SearchCommunity from Tribler.community.allchannel.community import AllChannelCommunity if isinstance(community, SearchCommunity): nr_connections = community.get_nr_connections() elif isinstance(community, AllChannelCommunity): nr_channel_connections = community.get_nr_connections() return nr_connections, nr_channel_connections def do_wx(delayedResult): if not self.frame: return nr_connections, nr_channel_connections = delayedResult.get() # self.frame.SRstatusbar.set_reputation(myRep, total_down, total_up) # bitmap is 16px wide, -> but first and last pixel do not add anything. percentage = min(1.0, (nr_connections + 1) / 16.0) self.frame.SRstatusbar.SetConnections(percentage, nr_connections, nr_channel_connections) """ set the reputation in the GUI""" if self._frame_and_ready(): startWorker(do_wx, do_db, uId=u"tribler.set_reputation") startWorker(None, self.set_reputation, delay=5.0, workerType="ThreadPool") def sesscb_states_callback(self, dslist): if not self.ready: return 5.0, [] wantpeers = [] self.ratestatecallbackcount += 1 try: # Print stats on Console if self.ratestatecallbackcount % 5 == 0: for ds in dslist: safename = repr(ds.get_download().get_def().get_name()) self._logger.debug( "%s %s %.1f%% dl %.1f ul %.1f n %d", safename, dlstatus_strings[ds.get_status()], 100.0 * ds.get_progress(), ds.get_current_speed(DOWNLOAD), ds.get_current_speed(UPLOAD), ds.get_num_peers()) if ds.get_status() == DLSTATUS_STOPPED_ON_ERROR: self._logger.error("main: Error: %s", repr(ds.get_error())) download = self.utility.session.lm.downloads.get(ds.get_infohash()) if download: download.stop() # show error dialog dlg = wx.MessageDialog(self.frame, "Download stopped on error: %s" % repr(ds.get_error()), "Download Error", wx.OK | wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() # Pass DownloadStates to libaryView no_collected_list = [ds for ds in dslist] try: # Arno, 2012-07-17: Retrieving peerlist for the DownloadStates takes CPU # so only do it when needed for display. wantpeers.extend(self.guiUtility.library_manager.download_state_callback(no_collected_list)) except: print_exc() # Check to see if a download has finished newActiveDownloads = [] doCheckpoint = False seeding_download_list = [] for ds in dslist: state = ds.get_status() download = ds.get_download() tdef = download.get_def() safename = tdef.get_name_as_unicode() if state == DLSTATUS_DOWNLOADING: newActiveDownloads.append(safename) elif state == DLSTATUS_SEEDING: seeding_download_list.append({u'infohash': tdef.get_infohash(), u'download': download, }) if safename in self.prevActiveDownloads: infohash = tdef.get_infohash() self.utility.session.notifier.notify(NTFY_TORRENTS, NTFY_FINISHED, infohash, safename) doCheckpoint = True elif download.get_hops() == 0 and download.get_safe_seeding(): self._logger.info("Re-add torrent with default nr of hops to prevent naked seeding") self.utility.session.remove_download(download) # copy the old download_config and change the hop count dscfg = download.copy() dscfg.set_hops(self.utility.read_config('default_number_hops')) # TODO(emilon): That's a hack to work around the fact # that removing a torrent is racy. self.utility.session.lm.threadpool.call(0.5, reactor.callInThread, self.utility.session.start_download, tdef, dscfg) self.prevActiveDownloads = newActiveDownloads if doCheckpoint: self.utility.session.checkpoint() if self.utility.read_config(u'seeding_mode') == 'never': for data in seeding_download_list: data[u'download'].stop() from Tribler.Main.vwxGUI.UserDownloadChoice import UserDownloadChoice UserDownloadChoice.get_singleton().set_download_state(data[u'infohash'], "stop") # Adjust speeds and call TunnelCommunity.monitor_downloads once every 4 seconds adjustspeeds = False if self.ratestatecallbackcount % 4 == 0: adjustspeeds = True if adjustspeeds and self.tunnel_community: self.tunnel_community.monitor_downloads(dslist) except: print_exc() return 1.0, wantpeers def loadSessionCheckpoint(self): pstate_dir = self.utility.session.get_downloads_pstate_dir() filelist = os.listdir(pstate_dir) if any([filename.endswith('.pickle') for filename in filelist]): convertDownloadCheckpoints(pstate_dir) from Tribler.Main.vwxGUI.UserDownloadChoice import UserDownloadChoice user_download_choice = UserDownloadChoice.get_singleton() initialdlstatus_dict = {} for infohash, state in user_download_choice.get_download_states().iteritems(): if state == 'stop': initialdlstatus_dict[infohash] = DLSTATUS_STOPPED self.utility.session.load_checkpoint(initialdlstatus_dict=initialdlstatus_dict) def guiservthread_free_space_check(self): if not (self and self.frame and self.frame.SRstatusbar): return free_space = get_free_space(DefaultDownloadStartupConfig.getInstance().get_dest_dir()) self.frame.SRstatusbar.RefreshFreeSpace(free_space) storage_locations = defaultdict(list) for download in self.utility.session.get_downloads(): if download.get_status() == DLSTATUS_DOWNLOADING: storage_locations[download.get_dest_dir()].append(download) show_message = False low_on_space = [ path for path in storage_locations.keys( ) if 0 < get_free_space( path) < self.utility.read_config( 'free_space_threshold')] for path in low_on_space: for download in storage_locations[path]: download.stop() show_message = True if show_message: wx.CallAfter(wx.MessageBox, "Tribler has detected low disk space. Related downloads have been stopped.", "Error") self.utility.session.lm.threadpool.call_in_thread(FREE_SPACE_CHECK_INTERVAL, self.guiservthread_free_space_check) def guiservthread_checkpoint_timer(self): """ Periodically checkpoint Session """ if self.done: return try: self._logger.info("main: Checkpointing Session") self.utility.session.checkpoint() self.utility.session.lm.threadpool.call_in_thread(SESSION_CHECKPOINT_INTERVAL, self.guiservthread_checkpoint_timer) except: print_exc() @forceWxThread def sesscb_ntfy_activities(self, events): if self._frame_and_ready(): for args in events: objectID = args[2] args = args[3:] self.frame.setActivity(objectID, *args) @forceWxThread def sesscb_ntfy_reachable(self, subject, changeType, objectID, msg): if self._frame_and_ready(): self.frame.SRstatusbar.onReachable() @forceWxThread def sesscb_ntfy_channelupdates(self, events): if self._frame_and_ready(): for args in events: subject = args[0] changeType = args[1] objectID = args[2] if self.frame.channellist: if len(args) > 3: myvote = args[3] else: myvote = False manager = self.frame.channellist.GetManager() manager.channelUpdated(objectID, subject == NTFY_VOTECAST, myvote=myvote) manager = self.frame.selectedchannellist.GetManager() manager.channelUpdated( objectID, stateChanged=changeType == NTFY_STATE, modified=changeType == NTFY_MODIFIED) if changeType == NTFY_CREATE: if self.frame.channellist: self.frame.channellist.SetMyChannelId(objectID) self.torrentfeed.register(self.utility.session, objectID) self.torrentfeed.addCallback(objectID, self.guiUtility.channelsearch_manager.createTorrentFromDef) self.frame.managechannel.channelUpdated( objectID, created=changeType == NTFY_CREATE, modified=changeType == NTFY_MODIFIED) @forceWxThread def sesscb_ntfy_torrentupdates(self, events): if self._frame_and_ready(): infohashes = [args[2] for args in events] if self.frame.searchlist: manager = self.frame.searchlist.GetManager() manager.torrentsUpdated(infohashes) manager = self.frame.selectedchannellist.GetManager() manager.torrentsUpdated(infohashes) manager = self.frame.playlist.GetManager() manager.torrentsUpdated(infohashes) manager = self.frame.librarylist.GetManager() manager.torrentsUpdated(infohashes) from Tribler.Main.Utility.GuiDBTuples import CollectedTorrent if self.frame.torrentdetailspanel.torrent and self.frame.torrentdetailspanel.torrent.infohash in infohashes: # If an updated torrent is being shown in the detailspanel, make sure the information gets refreshed. t = self.frame.torrentdetailspanel.torrent torrent = t.torrent if isinstance(t, CollectedTorrent) else t self.frame.torrentdetailspanel.setTorrent(torrent) if self.frame.librarydetailspanel.torrent and self.frame.librarydetailspanel.torrent.infohash in infohashes: t = self.frame.librarydetailspanel.torrent torrent = t.torrent if isinstance(t, CollectedTorrent) else t self.frame.librarydetailspanel.setTorrent(torrent) def sesscb_ntfy_torrentfinished(self, subject, changeType, objectID, *args): self.guiUtility.Notify( "Download Completed", "Torrent '%s' has finished downloading. Now seeding." % args[0], icon='seed') if self._frame_and_ready(): infohash = objectID torrent = self.guiUtility.torrentsearch_manager.getTorrentByInfohash(infohash) self.guiUtility.library_manager.addDownloadState(torrent) def sesscb_ntfy_magnet(self, subject, changetype, objectID, *args): if changetype == NTFY_MAGNET_STARTED: self.guiUtility.library_manager.magnet_started(objectID) elif changetype == NTFY_MAGNET_GOT_PEERS: self.guiUtility.library_manager.magnet_got_peers(objectID, args[0]) elif changetype == NTFY_MAGNET_CLOSE: self.guiUtility.library_manager.magnet_close(objectID) @forceWxThread def sesscb_ntfy_playlistupdates(self, subject, changeType, objectID, *args): if self._frame_and_ready(): if changeType == NTFY_INSERT: self.frame.managechannel.playlistCreated(objectID) manager = self.frame.selectedchannellist.GetManager() manager.playlistCreated(objectID) else: self.frame.managechannel.playlistUpdated(objectID, modified=changeType == NTFY_MODIFIED) if len(args) > 0: infohash = args[0] else: infohash = False manager = self.frame.selectedchannellist.GetManager() manager.playlistUpdated(objectID, infohash, modified=changeType == NTFY_MODIFIED) manager = self.frame.playlist.GetManager() manager.playlistUpdated(objectID, modified=changeType == NTFY_MODIFIED) @forceWxThread def sesscb_ntfy_commentupdates(self, subject, changeType, objectID, *args): if self._frame_and_ready(): self.frame.selectedchannellist.OnCommentCreated(objectID) self.frame.playlist.OnCommentCreated(objectID) @forceWxThread def sesscb_ntfy_modificationupdates(self, subject, changeType, objectID, *args): if self._frame_and_ready(): self.frame.selectedchannellist.OnModificationCreated(objectID) self.frame.playlist.OnModificationCreated(objectID) @forceWxThread def sesscb_ntfy_moderationupdats(self, subject, changeType, objectID, *args): if self._frame_and_ready(): self.frame.selectedchannellist.OnModerationCreated(objectID) self.frame.playlist.OnModerationCreated(objectID) @forceWxThread def sesscb_ntfy_markingupdates(self, subject, changeType, objectID, *args): if self._frame_and_ready(): self.frame.selectedchannellist.OnMarkingCreated(objectID) self.frame.playlist.OnModerationCreated(objectID) @forceWxThread def onError(self, e): print_exc() _, value, stack = sys.exc_info() backtrace = traceback.format_exception(type, value, stack) win = FeedbackWindow("Unfortunately, Tribler ran into an internal error") win.CreateOutputWindow('') for line in backtrace: win.write(line) win.ShowModal() @forceWxThread def OnExit(self): bm = self.gui_image_manager.getImage(u'closescreen.png') self.closewindow = GaugeSplash(bm, "Closing...", 6) self.closewindow.Show() self._logger.info("main: ONEXIT") self.ready = False self.done = True # write all persistent data to disk self.closewindow.tick('Write all persistent data to disk') if self.torrentfeed: self.torrentfeed.shutdown() self.torrentfeed.delInstance() if self.webUI: self.webUI.stop() self.webUI.delInstance() if self.frame: self.frame.Destroy() self.frame = None # Don't checkpoint, interferes with current way of saving Preferences, # see Tribler/Main/Dialogs/abcoption.py if self.utility: # Niels: lets add a max waiting time for this session shutdown. session_shutdown_start = time() try: self._logger.info("ONEXIT cleaning database") self.closewindow.tick('Cleaning database') torrent_db = self.utility.session.open_dbhandler(NTFY_TORRENTS) torrent_db._db.clean_db(randint(0, 24) == 0, exiting=True) except: print_exc() self.closewindow.tick('Shutdown session') self.utility.session.shutdown(hacksessconfcheckpoint=False) # Arno, 2012-07-12: Shutdown should be quick # Niels, 2013-03-21: However, setting it too low will prevent checkpoints from being written to disk waittime = 60 while not self.utility.session.has_shutdown(): diff = time() - session_shutdown_start if diff > waittime: self._logger.info("main: ONEXIT NOT Waiting for Session to shutdown, took too long") break self._logger.info( "ONEXIT Waiting for Session to shutdown, will wait for an additional %d seconds", waittime - diff) sleep(3) self._logger.info("ONEXIT Session is shutdown") self.closewindow.tick('Deleting instances') self._logger.debug("ONEXIT deleting instances") Session.del_instance() GUIUtility.delInstance() GUIDBProducer.delInstance() DefaultDownloadStartupConfig.delInstance() GuiImageManager.delInstance() self.closewindow.tick('Exiting now') self.closewindow.Destroy() return 0 def db_exception_handler(self, e): self._logger.debug("Database Exception handler called %s value %s #", e, e.args) try: if e.args[1] == "DB object has been closed": return # We caused this non-fatal error, don't show. if self.error is not None and self.error.args[1] == e.args[1]: return # don't repeat same error except: self._logger.error("db_exception_handler error %s %s", e, type(e)) print_exc() # print_stack() self.onError(e) def getConfigPath(self): return self.utility.getConfigPath() def startWithRightView(self): if self.params[0] != "": self.guiUtility.ShowPage('my_files') def i2ithread_readlinecallback(self, ic, cmd): """ Called by Instance2Instance thread """ self._logger.info("main: Another instance called us with cmd %s", cmd) ic.close() if cmd.startswith('START '): param = cmd[len('START '):].strip().decode("utf-8") torrentfilename = None if param.startswith('http:'): # Retrieve from web f = tempfile.NamedTemporaryFile() n = urllib2.urlopen(param) data = n.read() f.write(data) f.close() n.close() torrentfilename = f.name else: torrentfilename = param # Switch to GUI thread # New for 5.0: Start in VOD mode def start_asked_download(): if torrentfilename.startswith("magnet:"): self.frame.startDownloadFromMagnet(torrentfilename) else: self.frame.startDownload(torrentfilename) self.guiUtility.ShowPage('my_files') wx.CallAfter(start_asked_download)
def OnExit(self): bm = self.gui_image_manager.getImage(u'closescreen.png') self.closewindow = GaugeSplash(bm, "Closing...", 6) self.closewindow.Show() self._logger.info("main: ONEXIT") self.ready = False self.done = True # write all persistent data to disk self.closewindow.tick('Write all persistent data to disk') if self.torrentfeed: self.torrentfeed.shutdown() self.torrentfeed.delInstance() if self.webUI: self.webUI.stop() self.webUI.delInstance() if self.frame: self.frame.Destroy() self.frame = None # Don't checkpoint, interferes with current way of saving Preferences, # see Tribler/Main/Dialogs/abcoption.py if self.utility: # Niels: lets add a max waiting time for this session shutdown. session_shutdown_start = time() try: self._logger.info("ONEXIT cleaning database") self.closewindow.tick('Cleaning database') torrent_db = self.utility.session.open_dbhandler(NTFY_TORRENTS) torrent_db._db.clean_db(randint(0, 24) == 0, exiting=True) except: print_exc() self.closewindow.tick('Shutdown session') self.utility.session.shutdown(hacksessconfcheckpoint=False) # Arno, 2012-07-12: Shutdown should be quick # Niels, 2013-03-21: However, setting it too low will prevent checkpoints from being written to disk waittime = 60 while not self.utility.session.has_shutdown(): diff = time() - session_shutdown_start if diff > waittime: self._logger.info( "main: ONEXIT NOT Waiting for Session to shutdown, took too long" ) break self._logger.info( "ONEXIT Waiting for Session to shutdown, will wait for an additional %d seconds", waittime - diff) sleep(3) self._logger.info("ONEXIT Session is shutdown") self.closewindow.tick('Deleting instances') self._logger.debug("ONEXIT deleting instances") Session.del_instance() GUIUtility.delInstance() GUIDBProducer.delInstance() DefaultDownloadStartupConfig.delInstance() GuiImageManager.delInstance() self.closewindow.tick('Exiting now') self.closewindow.Destroy() return 0
def __init__(self, params, installdir, autoload_discovery=True, use_torrent_search=True, use_channel_search=True): assert not isInIOThread( ), "isInIOThread() seems to not be working correctly" self._logger = logging.getLogger(self.__class__.__name__) self.params = params self.installdir = installdir self.state_dir = None self.error = None self.last_update = 0 self.ready = False self.done = False self.frame = None self.upgrader = None self.said_start_playback = False self.decodeprogress = 0 self.old_reputation = 0 # DISPERSY will be set when available self.dispersy = None # BARTER_COMMUNITY will be set when both Dispersy and the EffortCommunity are available self.barter_community = None self.tunnel_community = None self.torrentfeed = None self.webUI = None self.utility = None # Stage 1 start session = self.InitStage1(installdir, autoload_discovery=autoload_discovery, use_torrent_search=use_torrent_search, use_channel_search=use_channel_search) self.splash = None try: bm = self.gui_image_manager.getImage(u'splash.png') self.splash = GaugeSplash(bm, "Loading...", 13) self.splash.Show() self._logger.info('Client Starting Up.') self._logger.info("Tribler is using %s as working directory", self.installdir) # Stage 2: show the splash window and start the session self.splash.tick('Starting API') s = self.startAPI(session, self.splash.tick) self.utility = Utility(self.installdir, s.get_state_dir()) if self.utility.read_config(u'saveas', u'downloadconfig'): DefaultDownloadStartupConfig.getInstance().set_dest_dir( self.utility.read_config(u'saveas', u'downloadconfig')) self.utility.set_app(self) self.utility.set_session(s) self.guiUtility = GUIUtility.getInstance(self.utility, self.params, self) GUIDBProducer.getInstance() self._logger.info('Tribler Version: %s Build: %s', version_id, commit_id) version_info = self.utility.read_config('version_info') if version_info.get('version_id', None) != version_id: # First run of a different version version_info['first_run'] = int(time()) version_info['version_id'] = version_id self.utility.write_config('version_info', version_info) self.splash.tick( 'Starting session and upgrading database (it may take a while)' ) s.start() self.dispersy = s.lm.dispersy self.splash.tick('Loading userdownloadchoice') from Tribler.Main.vwxGUI.UserDownloadChoice import UserDownloadChoice UserDownloadChoice.get_singleton().set_utility(self.utility) self.splash.tick('Initializing Family Filter') cat = Category.getInstance(session) state = self.utility.read_config('family_filter') if state in (1, 0): cat.set_family_filter(state == 1) else: self.utility.write_config('family_filter', 1) self.utility.flush_config() cat.set_family_filter(True) # Create global speed limits self.splash.tick('Setting up speed limits') # Counter to suppress some event from occurring self.ratestatecallbackcount = 0 maxup = self.utility.read_config('maxuploadrate') maxdown = self.utility.read_config('maxdownloadrate') # set speed limits using LibtorrentMgr s.set_max_upload_speed(maxup) s.set_max_download_speed(maxdown) # Only allow updates to come in after we defined ratelimiter self.prevActiveDownloads = [] s.set_download_states_callback(self.sesscb_states_callback) # Schedule task for checkpointing Session, to avoid hash checks after # crashes. startWorker(consumer=None, workerFn=self.guiservthread_checkpoint_timer, delay=SESSION_CHECKPOINT_INTERVAL) if not ALLOW_MULTIPLE: # Put it here so an error is shown in the startup-error popup # Start server for instance2instance communication Instance2InstanceServer( self.utility.read_config('i2ilistenport'), self.i2ithread_readlinecallback) self.splash.tick('GUIUtility register') self.guiUtility.register() self.frame = MainFrame( self, None, PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(), self.splash.tick) self.frame.SetIcon( wx.Icon( os.path.join(self.installdir, 'Tribler', 'Main', 'vwxGUI', 'images', 'tribler.ico'), wx.BITMAP_TYPE_ICO)) # Arno, 2011-06-15: VLC 1.1.10 pops up separate win, don't have two. self.frame.videoframe = None if PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(): vlcwrap = s.lm.videoplayer.get_vlcwrap() wx.CallLater(3000, vlcwrap._init_vlc) self.frame.videoframe = VideoDummyFrame( self.frame.videoparentpanel, self.utility, vlcwrap) if sys.platform == 'win32': wx.CallAfter(self.frame.top_bg.Refresh) wx.CallAfter(self.frame.top_bg.Layout) else: self.frame.top_bg.Layout() # Arno, 2007-05-03: wxWidgets 2.8.3.0 and earlier have the MIME-type for .bmp # files set to 'image/x-bmp' whereas 'image/bmp' is the official one. try: bmphand = None hands = wx.Image.GetHandlers() for hand in hands: # print "Handler",hand.GetExtension(),hand.GetType(),hand.GetMimeType() if hand.GetMimeType() == 'image/x-bmp': bmphand = hand break # wx.Image.AddHandler() if bmphand is not None: bmphand.SetMimeType('image/bmp') except: # wx < 2.7 don't like wx.Image.GetHandlers() print_exc() self.splash.Destroy() self.frame.Show(True) session.lm.threadpool.call_in_thread( 0, self.guiservthread_free_space_check) self.torrentfeed = RssParser.getInstance() self.webUI = None if self.utility.read_config('use_webui'): try: from Tribler.Main.webUI.webUI import WebUI self.webUI = WebUI.getInstance( self.guiUtility.library_manager, self.guiUtility.torrentsearch_manager, self.utility.read_config('webui_port')) self.webUI.start() except Exception: print_exc() self.emercoin_mgr = None try: from Tribler.Main.Emercoin.EmercoinMgr import EmercoinMgr self.emercoin_mgr = EmercoinMgr(self.utility) except Exception: print_exc() wx.CallAfter(self.PostInit2) # 08/02/10 Boudewijn: Working from home though console # doesn't allow me to press close. The statement below # gracefully closes Tribler after 120 seconds. # wx.CallLater(120*1000, wx.GetApp().Exit) self.ready = True except Exception as e: if self.splash: self.splash.Destroy() self.onError(e)
class ABCApp(object): def __init__(self, params, installdir, autoload_discovery=True, use_torrent_search=True, use_channel_search=True): assert not isInIOThread( ), "isInIOThread() seems to not be working correctly" self._logger = logging.getLogger(self.__class__.__name__) self.params = params self.installdir = installdir self.state_dir = None self.error = None self.last_update = 0 self.ready = False self.done = False self.frame = None self.upgrader = None self.said_start_playback = False self.decodeprogress = 0 self.old_reputation = 0 # DISPERSY will be set when available self.dispersy = None # BARTER_COMMUNITY will be set when both Dispersy and the EffortCommunity are available self.barter_community = None self.tunnel_community = None self.torrentfeed = None self.webUI = None self.utility = None # Stage 1 start session = self.InitStage1(installdir, autoload_discovery=autoload_discovery, use_torrent_search=use_torrent_search, use_channel_search=use_channel_search) self.splash = None try: bm = self.gui_image_manager.getImage(u'splash.png') self.splash = GaugeSplash(bm, "Loading...", 13) self.splash.Show() self._logger.info('Client Starting Up.') self._logger.info("Tribler is using %s as working directory", self.installdir) # Stage 2: show the splash window and start the session self.splash.tick('Starting API') s = self.startAPI(session, self.splash.tick) self.utility = Utility(self.installdir, s.get_state_dir()) if self.utility.read_config(u'saveas', u'downloadconfig'): DefaultDownloadStartupConfig.getInstance().set_dest_dir( self.utility.read_config(u'saveas', u'downloadconfig')) self.utility.set_app(self) self.utility.set_session(s) self.guiUtility = GUIUtility.getInstance(self.utility, self.params, self) GUIDBProducer.getInstance() self._logger.info('Tribler Version: %s Build: %s', version_id, commit_id) version_info = self.utility.read_config('version_info') if version_info.get('version_id', None) != version_id: # First run of a different version version_info['first_run'] = int(time()) version_info['version_id'] = version_id self.utility.write_config('version_info', version_info) self.splash.tick( 'Starting session and upgrading database (it may take a while)' ) s.start() self.dispersy = s.lm.dispersy self.splash.tick('Loading userdownloadchoice') from Tribler.Main.vwxGUI.UserDownloadChoice import UserDownloadChoice UserDownloadChoice.get_singleton().set_utility(self.utility) self.splash.tick('Initializing Family Filter') cat = Category.getInstance(session) state = self.utility.read_config('family_filter') if state in (1, 0): cat.set_family_filter(state == 1) else: self.utility.write_config('family_filter', 1) self.utility.flush_config() cat.set_family_filter(True) # Create global speed limits self.splash.tick('Setting up speed limits') # Counter to suppress some event from occurring self.ratestatecallbackcount = 0 maxup = self.utility.read_config('maxuploadrate') maxdown = self.utility.read_config('maxdownloadrate') # set speed limits using LibtorrentMgr s.set_max_upload_speed(maxup) s.set_max_download_speed(maxdown) # Only allow updates to come in after we defined ratelimiter self.prevActiveDownloads = [] s.set_download_states_callback(self.sesscb_states_callback) # Schedule task for checkpointing Session, to avoid hash checks after # crashes. startWorker(consumer=None, workerFn=self.guiservthread_checkpoint_timer, delay=SESSION_CHECKPOINT_INTERVAL) if not ALLOW_MULTIPLE: # Put it here so an error is shown in the startup-error popup # Start server for instance2instance communication Instance2InstanceServer( self.utility.read_config('i2ilistenport'), self.i2ithread_readlinecallback) self.splash.tick('GUIUtility register') self.guiUtility.register() self.frame = MainFrame( self, None, PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(), self.splash.tick) self.frame.SetIcon( wx.Icon( os.path.join(self.installdir, 'Tribler', 'Main', 'vwxGUI', 'images', 'tribler.ico'), wx.BITMAP_TYPE_ICO)) # Arno, 2011-06-15: VLC 1.1.10 pops up separate win, don't have two. self.frame.videoframe = None if PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(): vlcwrap = s.lm.videoplayer.get_vlcwrap() wx.CallLater(3000, vlcwrap._init_vlc) self.frame.videoframe = VideoDummyFrame( self.frame.videoparentpanel, self.utility, vlcwrap) if sys.platform == 'win32': wx.CallAfter(self.frame.top_bg.Refresh) wx.CallAfter(self.frame.top_bg.Layout) else: self.frame.top_bg.Layout() # Arno, 2007-05-03: wxWidgets 2.8.3.0 and earlier have the MIME-type for .bmp # files set to 'image/x-bmp' whereas 'image/bmp' is the official one. try: bmphand = None hands = wx.Image.GetHandlers() for hand in hands: # print "Handler",hand.GetExtension(),hand.GetType(),hand.GetMimeType() if hand.GetMimeType() == 'image/x-bmp': bmphand = hand break # wx.Image.AddHandler() if bmphand is not None: bmphand.SetMimeType('image/bmp') except: # wx < 2.7 don't like wx.Image.GetHandlers() print_exc() self.splash.Destroy() self.frame.Show(True) session.lm.threadpool.call_in_thread( 0, self.guiservthread_free_space_check) self.torrentfeed = RssParser.getInstance() self.webUI = None if self.utility.read_config('use_webui'): try: from Tribler.Main.webUI.webUI import WebUI self.webUI = WebUI.getInstance( self.guiUtility.library_manager, self.guiUtility.torrentsearch_manager, self.utility.read_config('webui_port')) self.webUI.start() except Exception: print_exc() self.emercoin_mgr = None try: from Tribler.Main.Emercoin.EmercoinMgr import EmercoinMgr self.emercoin_mgr = EmercoinMgr(self.utility) except Exception: print_exc() wx.CallAfter(self.PostInit2) # 08/02/10 Boudewijn: Working from home though console # doesn't allow me to press close. The statement below # gracefully closes Tribler after 120 seconds. # wx.CallLater(120*1000, wx.GetApp().Exit) self.ready = True except Exception as e: if self.splash: self.splash.Destroy() self.onError(e) def InitStage1(self, installdir, autoload_discovery=True, use_torrent_search=True, use_channel_search=True): """ Stage 1 start: pre-start the session to handle upgrade. """ self.gui_image_manager = GuiImageManager.getInstance(installdir) # Start Tribler Session defaultConfig = SessionStartupConfig() state_dir = defaultConfig.get_state_dir() # Switch to the state dir so relative paths can be used (IE, in LevelDB store paths) if not os.path.exists(state_dir): os.makedirs(state_dir) os.chdir(state_dir) cfgfilename = Session.get_default_config_filename(state_dir) self._logger.debug(u"Session config %s", cfgfilename) try: self.sconfig = SessionStartupConfig.load(cfgfilename) except: try: self.sconfig = convertSessionConfig( os.path.join(state_dir, 'sessconfig.pickle'), cfgfilename) convertMainConfig(state_dir, os.path.join(state_dir, 'abc.conf'), os.path.join(state_dir, STATEDIR_GUICONFIG)) except: self.sconfig = SessionStartupConfig() self.sconfig.set_state_dir(state_dir) self.sconfig.set_install_dir(self.installdir) # TODO(emilon): Do we still want to force limit this? With the new # torrent store it should be pretty fast even with more that that. # Arno, 2010-03-31: Hard upgrade to 50000 torrents collected self.sconfig.set_torrent_collecting_max_torrents(50000) dlcfgfilename = get_default_dscfg_filename( self.sconfig.get_state_dir()) self._logger.debug("main: Download config %s", dlcfgfilename) try: defaultDLConfig = DefaultDownloadStartupConfig.load(dlcfgfilename) except: try: defaultDLConfig = convertDefaultDownloadConfig( os.path.join(state_dir, 'dlconfig.pickle'), dlcfgfilename) except: defaultDLConfig = DefaultDownloadStartupConfig.getInstance() if not defaultDLConfig.get_dest_dir(): defaultDLConfig.set_dest_dir(get_default_dest_dir()) if not os.path.isdir(defaultDLConfig.get_dest_dir()): try: os.makedirs(defaultDLConfig.get_dest_dir()) except: # Could not create directory, ask user to select a different location dlg = wx.DirDialog( None, "Could not find download directory, please select a new location to store your downloads", style=wx.DEFAULT_DIALOG_STYLE) dlg.SetPath(get_default_dest_dir()) if dlg.ShowModal() == wx.ID_OK: new_dest_dir = dlg.GetPath() defaultDLConfig.set_dest_dir(new_dest_dir) defaultDLConfig.save(dlcfgfilename) self.sconfig.save(cfgfilename) else: # Quit self.onError = lambda e: self._logger.error( "tribler: quitting due to non-existing destination directory" ) raise Exception() if not use_torrent_search: self.sconfig.set_enable_torrent_search(False) if not use_channel_search: self.sconfig.set_enable_channel_search(False) session = Session(self.sconfig, autoload_discovery=autoload_discovery) session.add_observer(self.show_upgrade_dialog, NTFY_UPGRADER, [NTFY_STARTED]) self.upgrader = session.prestart() while not self.upgrader.is_done: wx.SafeYield() sleep(0.1) return session @forceWxThread def show_upgrade_dialog(self, subject, changetype, objectID, *args): assert wx.Thread_IsMain() upgrade_dialog = TriblerUpgradeDialog(self.gui_image_manager, self.upgrader) failed = upgrade_dialog.ShowModal() upgrade_dialog.Destroy() if failed: wx.MessageDialog( None, "Failed to upgrade the on disk data.\n\n" "Tribler has backed up the old data and will now start from scratch.\n\n" "Get in contact with the Tribler team if you want to help debugging this issue.\n\n" "Error was: %s" % self.upgrader.current_status, "Data format upgrade failed", wx.OK | wx.CENTRE | wx.ICON_EXCLAMATION).ShowModal() def _frame_and_ready(self): return self.ready and self.frame and self.frame.ready def PostInit2(self): self.frame.Raise() self.startWithRightView() self.set_reputation() s = self.utility.session s.add_observer(self.sesscb_ntfy_reachable, NTFY_REACHABLE, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_activities, NTFY_ACTIVITIES, [NTFY_INSERT], cache=10) s.add_observer( self.sesscb_ntfy_channelupdates, NTFY_CHANNELCAST, [NTFY_INSERT, NTFY_UPDATE, NTFY_CREATE, NTFY_STATE, NTFY_MODIFIED], cache=10) s.add_observer(self.sesscb_ntfy_channelupdates, NTFY_VOTECAST, [NTFY_UPDATE], cache=10) s.add_observer(self.sesscb_ntfy_myprefupdates, NTFY_MYPREFERENCES, [NTFY_INSERT, NTFY_UPDATE, NTFY_DELETE]) s.add_observer(self.sesscb_ntfy_torrentupdates, NTFY_TORRENTS, [NTFY_UPDATE, NTFY_INSERT], cache=10) s.add_observer(self.sesscb_ntfy_playlistupdates, NTFY_PLAYLISTS, [NTFY_INSERT, NTFY_UPDATE]) s.add_observer(self.sesscb_ntfy_commentupdates, NTFY_COMMENTS, [NTFY_INSERT, NTFY_DELETE]) s.add_observer(self.sesscb_ntfy_modificationupdates, NTFY_MODIFICATIONS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_moderationupdats, NTFY_MODERATIONS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_markingupdates, NTFY_MARKINGS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_torrentfinished, NTFY_TORRENTS, [NTFY_FINISHED]) s.add_observer( self.sesscb_ntfy_magnet, NTFY_TORRENTS, [NTFY_MAGNET_GOT_PEERS, NTFY_MAGNET_STARTED, NTFY_MAGNET_CLOSE]) # TODO(emilon): Use the LogObserver I already implemented # self.dispersy.callback.attach_exception_handler(self.frame.exceptionHandler) startWorker(None, self.loadSessionCheckpoint, delay=5.0, workerType="ThreadPool") # initialize the torrent feed thread channelcast = s.open_dbhandler(NTFY_CHANNELCAST) def db_thread(): return channelcast.getMyChannelId() def wx_thread(delayedResult): my_channel = delayedResult.get() if my_channel: self.torrentfeed.register(self.utility.session, my_channel) self.torrentfeed.addCallback( my_channel, self.guiUtility.channelsearch_manager.createTorrentFromDef) startWorker(wx_thread, db_thread, delay=5.0) def startAPI(self, session, progress): @call_on_reactor_thread def define_communities(*args): assert isInIOThread() from Tribler.community.channel.community import ChannelCommunity from Tribler.community.channel.preview import PreviewChannelCommunity from Tribler.community.tunnel.tunnel_community import TunnelSettings from Tribler.community.tunnel.hidden_community import HiddenTunnelCommunity # make sure this is only called once session.remove_observer(define_communities) dispersy = session.get_dispersy_instance() self._logger.info("tribler: Preparing communities...") now = time() dispersy.attach_progress_handler(self.progressHandler) default_kwargs = {'tribler_session': session} # must be called on the Dispersy thread if session.get_barter_community_enabled(): from Tribler.community.bartercast4.community import BarterCommunity dispersy.define_auto_load(BarterCommunity, session.dispersy_member, load=True) # load metadata community dispersy.define_auto_load(ChannelCommunity, session.dispersy_member, load=True, kargs=default_kwargs) dispersy.define_auto_load(PreviewChannelCommunity, session.dispersy_member, kargs=default_kwargs) keypair = dispersy.crypto.generate_key(u"curve25519") dispersy_member = dispersy.get_member( private_key=dispersy.crypto.key_to_bin(keypair), ) settings = TunnelSettings(session.get_install_dir(), tribler_session=session) tunnel_kwargs = {'tribler_session': session, 'settings': settings} self.tunnel_community = dispersy.define_auto_load( HiddenTunnelCommunity, dispersy_member, load=True, kargs=tunnel_kwargs)[0] session.set_anon_proxy_settings( 2, ("127.0.0.1", session.get_tunnel_community_socks5_listen_ports())) diff = time() - now self._logger.info("tribler: communities are ready in %.2f seconds", diff) session.add_observer(define_communities, NTFY_DISPERSY, [NTFY_STARTED]) return session @forceWxThread def sesscb_ntfy_myprefupdates(self, subject, changeType, objectID, *args): if self._frame_and_ready(): if changeType in [NTFY_INSERT, NTFY_UPDATE]: if changeType == NTFY_INSERT: if self.frame.searchlist: manager = self.frame.searchlist.GetManager() manager.downloadStarted(objectID) manager = self.frame.selectedchannellist.GetManager() manager.downloadStarted(objectID) manager = self.frame.librarylist.GetManager() manager.downloadStarted(objectID) elif changeType == NTFY_DELETE: self.guiUtility.frame.librarylist.RemoveItem(objectID) if self.guiUtility.frame.librarylist.IsShownOnScreen() and \ self.guiUtility.frame.librarydetailspanel.torrent and \ self.guiUtility.frame.librarydetailspanel.torrent.infohash == objectID: self.guiUtility.frame.librarylist.ResetBottomWindow() self.guiUtility.frame.top_bg.ClearButtonHandlers() if self.guiUtility.frame.librarylist.list.IsEmpty(): self.guiUtility.frame.librarylist.SetData([]) def progressHandler(self, title, message, maximum): from Tribler.Main.Dialogs.ThreadSafeProgressDialog import ThreadSafeProgressDialog return ThreadSafeProgressDialog( title, message, maximum, None, wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME | wx.PD_ESTIMATED_TIME | wx.PD_REMAINING_TIME | wx.PD_AUTO_HIDE) def set_reputation(self): def do_db(): nr_connections = 0 nr_channel_connections = 0 if self.dispersy: for community in self.dispersy.get_communities(): from Tribler.community.search.community import SearchCommunity from Tribler.community.allchannel.community import AllChannelCommunity if isinstance(community, SearchCommunity): nr_connections = community.get_nr_connections() elif isinstance(community, AllChannelCommunity): nr_channel_connections = community.get_nr_connections() return nr_connections, nr_channel_connections def do_wx(delayedResult): if not self.frame: return nr_connections, nr_channel_connections = delayedResult.get() # self.frame.SRstatusbar.set_reputation(myRep, total_down, total_up) # bitmap is 16px wide, -> but first and last pixel do not add anything. percentage = min(1.0, (nr_connections + 1) / 16.0) self.frame.SRstatusbar.SetConnections(percentage, nr_connections, nr_channel_connections) """ set the reputation in the GUI""" if self._frame_and_ready(): startWorker(do_wx, do_db, uId=u"tribler.set_reputation") startWorker(None, self.set_reputation, delay=5.0, workerType="ThreadPool") def sesscb_states_callback(self, dslist): if not self.ready: return 5.0, [] wantpeers = [] self.ratestatecallbackcount += 1 try: # Print stats on Console if self.ratestatecallbackcount % 5 == 0: for ds in dslist: safename = repr(ds.get_download().get_def().get_name()) self._logger.debug("%s %s %.1f%% dl %.1f ul %.1f n %d", safename, dlstatus_strings[ds.get_status()], 100.0 * ds.get_progress(), ds.get_current_speed(DOWNLOAD), ds.get_current_speed(UPLOAD), ds.get_num_peers()) if ds.get_status() == DLSTATUS_STOPPED_ON_ERROR: self._logger.error("main: Error: %s", repr(ds.get_error())) download = self.utility.session.lm.downloads.get( ds.get_infohash()) if download: download.stop() # show error dialog dlg = wx.MessageDialog( self.frame, "Download stopped on error: %s" % repr(ds.get_error()), "Download Error", wx.OK | wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() # Pass DownloadStates to libaryView no_collected_list = [ds for ds in dslist] try: # Arno, 2012-07-17: Retrieving peerlist for the DownloadStates takes CPU # so only do it when needed for display. wantpeers.extend( self.guiUtility.library_manager.download_state_callback( no_collected_list)) except: print_exc() # Check to see if a download has finished newActiveDownloads = [] doCheckpoint = False seeding_download_list = [] for ds in dslist: state = ds.get_status() download = ds.get_download() tdef = download.get_def() safename = tdef.get_name_as_unicode() if state == DLSTATUS_DOWNLOADING: newActiveDownloads.append(safename) elif state == DLSTATUS_SEEDING: seeding_download_list.append({ u'infohash': tdef.get_infohash(), u'download': download, }) if safename in self.prevActiveDownloads: infohash = tdef.get_infohash() self.utility.session.notifier.notify( NTFY_TORRENTS, NTFY_FINISHED, infohash, safename) doCheckpoint = True elif download.get_hops( ) == 0 and download.get_safe_seeding(): self._logger.info( "Re-add torrent with default nr of hops to prevent naked seeding" ) self.utility.session.remove_download(download) # copy the old download_config and change the hop count dscfg = download.copy() dscfg.set_hops( self.utility.read_config('default_number_hops')) # TODO(emilon): That's a hack to work around the fact # that removing a torrent is racy. self.utility.session.lm.threadpool.call( 0.5, reactor.callInThread, self.utility.session.start_download, tdef, dscfg) self.prevActiveDownloads = newActiveDownloads if doCheckpoint: self.utility.session.checkpoint() if self.utility.read_config(u'seeding_mode') == 'never': for data in seeding_download_list: data[u'download'].stop() from Tribler.Main.vwxGUI.UserDownloadChoice import UserDownloadChoice UserDownloadChoice.get_singleton().set_download_state( data[u'infohash'], "stop") # Adjust speeds and call TunnelCommunity.monitor_downloads once every 4 seconds adjustspeeds = False if self.ratestatecallbackcount % 4 == 0: adjustspeeds = True if adjustspeeds and self.tunnel_community: self.tunnel_community.monitor_downloads(dslist) except: print_exc() return 1.0, wantpeers def loadSessionCheckpoint(self): pstate_dir = self.utility.session.get_downloads_pstate_dir() filelist = os.listdir(pstate_dir) if any([filename.endswith('.pickle') for filename in filelist]): convertDownloadCheckpoints(pstate_dir) from Tribler.Main.vwxGUI.UserDownloadChoice import UserDownloadChoice user_download_choice = UserDownloadChoice.get_singleton() initialdlstatus_dict = {} for infohash, state in user_download_choice.get_download_states( ).iteritems(): if state == 'stop': initialdlstatus_dict[infohash] = DLSTATUS_STOPPED self.utility.session.load_checkpoint( initialdlstatus_dict=initialdlstatus_dict) def guiservthread_free_space_check(self): if not (self and self.frame and self.frame.SRstatusbar): return free_space = get_free_space( DefaultDownloadStartupConfig.getInstance().get_dest_dir()) self.frame.SRstatusbar.RefreshFreeSpace(free_space) storage_locations = defaultdict(list) for download in self.utility.session.get_downloads(): if download.get_status() == DLSTATUS_DOWNLOADING: storage_locations[download.get_dest_dir()].append(download) show_message = False low_on_space = [ path for path in storage_locations.keys() if 0 < get_free_space( path) < self.utility.read_config('free_space_threshold') ] for path in low_on_space: for download in storage_locations[path]: download.stop() show_message = True if show_message: wx.CallAfter( wx.MessageBox, "Tribler has detected low disk space. Related downloads have been stopped.", "Error") self.utility.session.lm.threadpool.call_in_thread( FREE_SPACE_CHECK_INTERVAL, self.guiservthread_free_space_check) def guiservthread_checkpoint_timer(self): """ Periodically checkpoint Session """ if self.done: return try: self._logger.info("main: Checkpointing Session") self.utility.session.checkpoint() self.utility.session.lm.threadpool.call_in_thread( SESSION_CHECKPOINT_INTERVAL, self.guiservthread_checkpoint_timer) except: print_exc() @forceWxThread def sesscb_ntfy_activities(self, events): if self._frame_and_ready(): for args in events: objectID = args[2] args = args[3:] self.frame.setActivity(objectID, *args) @forceWxThread def sesscb_ntfy_reachable(self, subject, changeType, objectID, msg): if self._frame_and_ready(): self.frame.SRstatusbar.onReachable() @forceWxThread def sesscb_ntfy_channelupdates(self, events): if self._frame_and_ready(): for args in events: subject = args[0] changeType = args[1] objectID = args[2] if self.frame.channellist: if len(args) > 3: myvote = args[3] else: myvote = False manager = self.frame.channellist.GetManager() manager.channelUpdated(objectID, subject == NTFY_VOTECAST, myvote=myvote) manager = self.frame.selectedchannellist.GetManager() manager.channelUpdated(objectID, stateChanged=changeType == NTFY_STATE, modified=changeType == NTFY_MODIFIED) if changeType == NTFY_CREATE: if self.frame.channellist: self.frame.channellist.SetMyChannelId(objectID) self.torrentfeed.register(self.utility.session, objectID) self.torrentfeed.addCallback( objectID, self.guiUtility.channelsearch_manager. createTorrentFromDef) self.frame.managechannel.channelUpdated( objectID, created=changeType == NTFY_CREATE, modified=changeType == NTFY_MODIFIED) @forceWxThread def sesscb_ntfy_torrentupdates(self, events): if self._frame_and_ready(): infohashes = [args[2] for args in events] if self.frame.searchlist: manager = self.frame.searchlist.GetManager() manager.torrentsUpdated(infohashes) manager = self.frame.selectedchannellist.GetManager() manager.torrentsUpdated(infohashes) manager = self.frame.playlist.GetManager() manager.torrentsUpdated(infohashes) manager = self.frame.librarylist.GetManager() manager.torrentsUpdated(infohashes) from Tribler.Main.Utility.GuiDBTuples import CollectedTorrent if self.frame.torrentdetailspanel.torrent and self.frame.torrentdetailspanel.torrent.infohash in infohashes: # If an updated torrent is being shown in the detailspanel, make sure the information gets refreshed. t = self.frame.torrentdetailspanel.torrent torrent = t.torrent if isinstance(t, CollectedTorrent) else t self.frame.torrentdetailspanel.setTorrent(torrent) if self.frame.librarydetailspanel.torrent and self.frame.librarydetailspanel.torrent.infohash in infohashes: t = self.frame.librarydetailspanel.torrent torrent = t.torrent if isinstance(t, CollectedTorrent) else t self.frame.librarydetailspanel.setTorrent(torrent) def sesscb_ntfy_torrentfinished(self, subject, changeType, objectID, *args): self.guiUtility.Notify( "Download Completed", "Torrent '%s' has finished downloading. Now seeding." % args[0], icon='seed') if self._frame_and_ready(): infohash = objectID torrent = self.guiUtility.torrentsearch_manager.getTorrentByInfohash( infohash) self.guiUtility.library_manager.addDownloadState(torrent) def sesscb_ntfy_magnet(self, subject, changetype, objectID, *args): if changetype == NTFY_MAGNET_STARTED: self.guiUtility.library_manager.magnet_started(objectID) elif changetype == NTFY_MAGNET_GOT_PEERS: self.guiUtility.library_manager.magnet_got_peers(objectID, args[0]) elif changetype == NTFY_MAGNET_CLOSE: self.guiUtility.library_manager.magnet_close(objectID) @forceWxThread def sesscb_ntfy_playlistupdates(self, subject, changeType, objectID, *args): if self._frame_and_ready(): if changeType == NTFY_INSERT: self.frame.managechannel.playlistCreated(objectID) manager = self.frame.selectedchannellist.GetManager() manager.playlistCreated(objectID) else: self.frame.managechannel.playlistUpdated( objectID, modified=changeType == NTFY_MODIFIED) if len(args) > 0: infohash = args[0] else: infohash = False manager = self.frame.selectedchannellist.GetManager() manager.playlistUpdated(objectID, infohash, modified=changeType == NTFY_MODIFIED) manager = self.frame.playlist.GetManager() manager.playlistUpdated(objectID, modified=changeType == NTFY_MODIFIED) @forceWxThread def sesscb_ntfy_commentupdates(self, subject, changeType, objectID, *args): if self._frame_and_ready(): self.frame.selectedchannellist.OnCommentCreated(objectID) self.frame.playlist.OnCommentCreated(objectID) @forceWxThread def sesscb_ntfy_modificationupdates(self, subject, changeType, objectID, *args): if self._frame_and_ready(): self.frame.selectedchannellist.OnModificationCreated(objectID) self.frame.playlist.OnModificationCreated(objectID) @forceWxThread def sesscb_ntfy_moderationupdats(self, subject, changeType, objectID, *args): if self._frame_and_ready(): self.frame.selectedchannellist.OnModerationCreated(objectID) self.frame.playlist.OnModerationCreated(objectID) @forceWxThread def sesscb_ntfy_markingupdates(self, subject, changeType, objectID, *args): if self._frame_and_ready(): self.frame.selectedchannellist.OnMarkingCreated(objectID) self.frame.playlist.OnModerationCreated(objectID) @forceWxThread def onError(self, e): print_exc() _, value, stack = sys.exc_info() backtrace = traceback.format_exception(type, value, stack) win = FeedbackWindow( "Unfortunately, Tribler ran into an internal error") win.CreateOutputWindow('') for line in backtrace: win.write(line) win.ShowModal() @forceWxThread def OnExit(self): bm = self.gui_image_manager.getImage(u'closescreen.png') self.closewindow = GaugeSplash(bm, "Closing...", 6) self.closewindow.Show() self._logger.info("main: ONEXIT") self.ready = False self.done = True # write all persistent data to disk self.closewindow.tick('Write all persistent data to disk') if self.torrentfeed: self.torrentfeed.shutdown() self.torrentfeed.delInstance() if self.webUI: self.webUI.stop() self.webUI.delInstance() if self.frame: self.frame.Destroy() self.frame = None # Don't checkpoint, interferes with current way of saving Preferences, # see Tribler/Main/Dialogs/abcoption.py if self.utility: # Niels: lets add a max waiting time for this session shutdown. session_shutdown_start = time() try: self._logger.info("ONEXIT cleaning database") self.closewindow.tick('Cleaning database') torrent_db = self.utility.session.open_dbhandler(NTFY_TORRENTS) torrent_db._db.clean_db(randint(0, 24) == 0, exiting=True) except: print_exc() self.closewindow.tick('Shutdown session') self.utility.session.shutdown(hacksessconfcheckpoint=False) # Arno, 2012-07-12: Shutdown should be quick # Niels, 2013-03-21: However, setting it too low will prevent checkpoints from being written to disk waittime = 60 while not self.utility.session.has_shutdown(): diff = time() - session_shutdown_start if diff > waittime: self._logger.info( "main: ONEXIT NOT Waiting for Session to shutdown, took too long" ) break self._logger.info( "ONEXIT Waiting for Session to shutdown, will wait for an additional %d seconds", waittime - diff) sleep(3) self._logger.info("ONEXIT Session is shutdown") self.closewindow.tick('Deleting instances') self._logger.debug("ONEXIT deleting instances") Session.del_instance() GUIUtility.delInstance() GUIDBProducer.delInstance() DefaultDownloadStartupConfig.delInstance() GuiImageManager.delInstance() self.closewindow.tick('Exiting now') self.closewindow.Destroy() return 0 def db_exception_handler(self, e): self._logger.debug("Database Exception handler called %s value %s #", e, e.args) try: if e.args[1] == "DB object has been closed": return # We caused this non-fatal error, don't show. if self.error is not None and self.error.args[1] == e.args[1]: return # don't repeat same error except: self._logger.error("db_exception_handler error %s %s", e, type(e)) print_exc() # print_stack() self.onError(e) def getConfigPath(self): return self.utility.getConfigPath() def startWithRightView(self): if self.params[0] != "": self.guiUtility.ShowPage('my_files') def i2ithread_readlinecallback(self, ic, cmd): """ Called by Instance2Instance thread """ self._logger.info("main: Another instance called us with cmd %s", cmd) ic.close() if cmd.startswith('START '): param = cmd[len('START '):].strip().decode("utf-8") torrentfilename = None if param.startswith('http:'): # Retrieve from web f = tempfile.NamedTemporaryFile() n = urllib2.urlopen(param) data = n.read() f.write(data) f.close() n.close() torrentfilename = f.name else: torrentfilename = param # Switch to GUI thread # New for 5.0: Start in VOD mode def start_asked_download(): if torrentfilename.startswith("magnet:"): self.frame.startDownloadFromMagnet(torrentfilename) else: self.frame.startDownload(torrentfilename) self.guiUtility.ShowPage('my_files') wx.CallAfter(start_asked_download)
class GUIUtility(object): __single = None __single_lock = Lock() START_GAUGE_SPLASH_TICKS = 10 CLOSE_GAUGE_SPLASH_TICKS = 6 def __init__(self, utility=None, params=None, app=None): if GUIUtility.__single: raise RuntimeError("GUIUtility is singleton") GUIUtility.__single = self self.registered = False self._logger = logging.getLogger(self.__class__.__name__) # do other init self.utility = utility self.vwxGUI_path = os.path.join(self.utility.getPath(), LIBRARYNAME, 'Main', 'vwxGUI') self.utility.guiUtility = self self.params = params self.frame = None self.startup_splash = None self.close_splash = None self.app = app self.close_splash = None self.startup_splash = None self.startup_completed = False self.close_completed = False # videoplayer self.videoplayer = None # current GUI page self.guiPage = 'home' # previous pages self.oldpage = [] # firewall self.firewall_restart = False # ie Tribler needs to restart for the port number to be updated # Recall improves by 20-25% by increasing the number of peers to query to 20 from 10 ! self.max_remote_queries = 20 # max number of remote peers to query self.current_search_query = '' self.lists = [] from Tribler.Main.vwxGUI.list_header import ListHeaderIcon self.listicon = ListHeaderIcon.getInstance() # Add listeners to listen if tribler is starting the initialisation and closing procedures. self.utility.session.add_observer(self.on_show_startup_splash, NTFY_STARTUP_TICK, [NTFY_CREATE]) self.utility.session.add_observer(self.on_show_close_splash, NTFY_CLOSE_TICK, [NTFY_CREATE]) # Add listeners to update ticks self.utility.session.add_observer(self.on_startup_tick, NTFY_STARTUP_TICK, [NTFY_INSERT]) self.utility.session.add_observer(self.on_close_tick, NTFY_CLOSE_TICK, [NTFY_INSERT]) # Add listeners to listen when to destroy the gauge splash self.utility.session.add_observer(self.destroy_startup_splash, NTFY_STARTUP_TICK, [NTFY_DELETE]) self.utility.session.add_observer(self.destroy_close_splash, NTFY_CLOSE_TICK, [NTFY_DELETE]) def getInstance(*args, **kw): if GUIUtility.__single is None: GUIUtility(*args, **kw) return GUIUtility.__single getInstance = staticmethod(getInstance) def hasInstance(): return GUIUtility.__single is not None hasInstance = staticmethod(hasInstance) def delInstance(): with GUIUtility.__single_lock: if GUIUtility.__single and GUIUtility.__single.registered: GUIUtility.__single.listicon.delInstance() GUIUtility.__single.library_manager = None GUIUtility.__single.channelsearch_manager.delInstance() GUIUtility.__single.torrentsearch_manager = None GUIUtility.__single = None delInstance = staticmethod(delInstance) def register(self): if not self.registered: self.registered = True self.torrentsearch_manager = TorrentManager(self) self.channelsearch_manager = ChannelManager.getInstance() self.library_manager = LibraryManager(self) self.torrentsearch_manager.connect(self.utility.session, self.library_manager, self.channelsearch_manager) self.channelsearch_manager.connect(self.utility.session, self.library_manager, self.torrentsearch_manager) self.library_manager.connect(self.utility.session, self.torrentsearch_manager, self.channelsearch_manager) else: raise RuntimeError('GuiUtility is already registered') def ShowPlayer(self): # TODO(emilon): Hack to work around video player tab not been properly # drawn when clicking on the stream button of a search result which # hasn't had it's torrent fetched. wx.SafeYield() self.showLibrary() wx.SafeYield() #EO Hack if self.frame.videoparentpanel: self.ShowPage('videoplayer') @forceWxThread def ShowPage(self, page, *args): if page == 'settings': from Tribler.Main.vwxGUI.settingsDialog import SettingsDialog dialog = SettingsDialog() dialog.Centre() dialog.ShowModal() dialog.Destroy() elif page != self.guiPage: self.frame.actlist.selectTab(page) self.frame.top_bg.ClearButtonHandlers() self.oldpage.append(self.guiPage) if len(self.oldpage) > 3: self.oldpage.pop(0) #self.frame.Freeze() if page not in [ 'search_results', 'my_files', 'selectedchannel', 'playlist', 'channels' ]: self.frame.splitter.Show(False) if page == 'search_results': # Show list self.SetTopSplitterWindow(self.frame.searchlist) items = self.frame.searchlist.GetExpandedItems() if items: self.frame.searchlist.Select(items[0][0], force=True) else: self.frame.searchlist.ResetBottomWindow() elif self.guiPage == 'search_results': # Hide list self.frame.searchlist.Show(False) if page == 'channels': self.SetTopSplitterWindow(self.frame.channellist) items = self.frame.channellist.GetExpandedItems() if items: self.frame.channellist.Select(items[0][0], force=True) else: self.frame.channellist.ResetBottomWindow() elif self.guiPage == 'channels': self.frame.channellist.Show(False) if page == 'mychannel': # Show list self.frame.managechannel.SetChannelId( self.channelsearch_manager.channelcast_db._channel_id) self.frame.managechannel.Show() elif self.guiPage == 'mychannel': self.frame.managechannel.Show(False) if page == 'managechannel': self.frame.managechannel.Show() elif self.guiPage == 'managechannel': self.frame.managechannel.Show(False) if page == 'selectedchannel': self.SetTopSplitterWindow(self.frame.selectedchannellist) items = self.frame.selectedchannellist.GetExpandedItems() if items: self.frame.selectedchannellist.Select(items[0][0], force=True) else: self.frame.selectedchannellist.ResetBottomWindow() channelmenu = self.frame.actlist.GetItem(3) if channelmenu and channelmenu.expandedPanel: channelmenu.expandedPanel.AddCurrentChannelLink() elif self.guiPage == 'selectedchannel': self.frame.selectedchannellist.Show(False) if not self.frame.splitter.IsSplit(): sashpos = getattr(self.frame.splitter_top_window, 'sashpos', -185) self.frame.splitter.SplitHorizontally( self.frame.splitter_top_window, self.frame.splitter_bottom_window, sashpos) if page == 'playlist': self.SetTopSplitterWindow(self.frame.playlist) items = self.frame.playlist.GetExpandedItems() if items: self.frame.playlist.Select(items[0][0]) else: self.frame.playlist.ResetBottomWindow() channelmenu = self.frame.actlist.GetItem(3) if channelmenu and channelmenu.expandedPanel: channelmenu.expandedPanel.AddCurrentPlaylistLink() elif self.guiPage == 'playlist': self.frame.playlist.Show(False) if page == 'my_files': # Show list self.SetTopSplitterWindow(self.frame.librarylist) # Open infohash if args: self.frame.librarylist.GetManager().refresh_or_expand( args[0]) else: items = self.frame.librarylist.GetExpandedItems() if items: self.frame.librarylist.Select(items[0][0], force=True) else: self.frame.librarylist.ResetBottomWindow() elif self.guiPage == 'my_files': # Hide list self.frame.librarylist.Show(False) if page == 'creditmining': self.frame.creditminingpanel.Show(True) elif self.guiPage == 'creditmining': self.frame.creditminingpanel.Show(False) if page == 'home': self.frame.home.ResetSearchBox() self.frame.home.Show() elif self.guiPage == 'home': self.frame.home.Show(False) if page == 'stats': self.frame.stats.Show() elif self.guiPage == 'stats': self.frame.stats.Show(False) if page == 'networkgraph': self.frame.networkgraph.Show() elif self.guiPage == 'networkgraph': self.frame.networkgraph.Show(False) if self.frame.videoparentpanel: if page == 'videoplayer': self.frame.videoparentpanel.Show(True) elif self.guiPage == 'videoplayer': self.frame.videoparentpanel.Show(False) self.guiPage = page self.frame.Layout() #self.frame.Thaw() # Set focus to page if page == 'search_results': self.frame.searchlist.Focus() if args: self.frame.searchlist.total_results = None self.frame.searchlist.SetKeywords(args[0]) elif page == 'channels': self.frame.channellist.Focus() elif page == 'selectedchannel': self.frame.selectedchannellist.Focus() elif page == 'my_files': self.frame.librarylist.Focus() @forceWxThread def on_show_startup_splash(self, subject, changetype, objectID, *args): gui_image_manager = GuiImageManager.getInstance() bm = gui_image_manager.getImage(u'splash.png') self.startup_splash = GaugeSplash(bm, "Loading...", self.START_GAUGE_SPLASH_TICKS) # Check if the destroy message has already arrived. Loading the splash takes a while, # so the setup may have already been completed. if self.startup_completed: self.destroy_startup_splash(None, None, None, None) @forceWxThread def on_startup_tick(self, subject, changetype, objectID, *args): if self.startup_splash: self.startup_splash.tick(args[0]) @forceWxThread def destroy_startup_splash(self, subject, changetype, objectID, *args): self.startup_completed = True if self.startup_splash: self.startup_splash.Destroy() @forceWxThread def on_show_close_splash(self, subject, changetype, objectID, *args): gui_image_manager = GuiImageManager.getInstance() bm = gui_image_manager.getImage(u'closescreen.png') self.close_splash = GaugeSplash(bm, "Closing...", self.CLOSE_GAUGE_SPLASH_TICKS) if self.close_completed: self.destroy_close_splash(None, None, None, None) @forceWxThread def on_close_tick(self, subject, changetype, objectID, *args): if self.close_splash: self.close_splash.tick(args[0]) @forceWxThread def destroy_close_splash(self, subject, changetype, objectID, *args): if self.close_splash: self.close_splash.Destroy() def GetSelectedPage(self): if self.guiPage == 'home': return self.frame.home if self.guiPage == 'search_results': return self.frame.searchlist if self.guiPage == 'channels': return self.frame.channellist if self.guiPage == 'selectedchannel': return self.frame.selectedchannellist if self.guiPage == 'mychannel': return self.frame.managechannel if self.guiPage == 'managechannel': return self.frame.managechannel if self.guiPage == 'playlist': return self.frame.playlist if self.guiPage == 'my_files': return self.frame.librarylist if self.guiPage == 'creditmining': return self.frame.creditminingpanel def SetTopSplitterWindow(self, window=None, show=True): while self.frame.splitter_top.GetChildren(): self.frame.splitter_top.Detach(0) if window: self.frame.splitter_top.Add(window, 1, wx.EXPAND) window.Show(show) self.frame.splitter.Show(show) self.frame.splitter_top.Layout() self.frame.splitter_top_window.Refresh() def SetBottomSplitterWindow(self, panel_type): #self.frame.splitter_bottom_window.Freeze() from Tribler.Main.vwxGUI.list_details import TorrentDetails, ChannelInfoPanel, LibraryDetails, ChannelDetails, PlaylistDetails, SearchInfoPanel, LibraryInfoPanel, SelectedchannelInfoPanel, PlaylistInfoPanel type_to_panel = { TorrentDetails.__name__: self.frame.torrentdetailspanel, LibraryDetails.__name__: self.frame.librarydetailspanel, ChannelDetails.__name__: self.frame.channeldetailspanel, PlaylistDetails.__name__: self.frame.playlistdetailspanel, SearchInfoPanel.__name__: self.frame.searchinfopanel, ChannelInfoPanel.__name__: self.frame.channelinfopanel, LibraryInfoPanel.__name__: self.frame.libraryinfopanel, PlaylistInfoPanel.__name__: self.frame.playlistinfopanel, SelectedchannelInfoPanel.__name__: self.frame.selectedchannelinfopanel } result = None for pt, pl in type_to_panel.iteritems(): pl.Show(pt == panel_type.__name__) if pt == panel_type.__name__: result = pl if self.guiPage not in ['mychannel', 'home']: self.frame.splitter.Show(True) self.frame.splitter_bottom.Layout() #self.frame.splitter_bottom_window.Thaw() self.frame.splitter_bottom_window.Refresh() return result def SetColumnInfo(self, itemtype, columns, hide_defaults=[]): # Load hidden column info hide_columns = self.ReadGuiSetting("hide_columns", default={}) hide_columns = hide_columns.get(itemtype.__name__, {}) for index, column in enumerate(columns): if column['name'] in hide_columns: column['show'] = hide_columns[column['name']] else: column['show'] = not (index in hide_defaults) # Load column width info column_sizes = self.ReadGuiSetting("column_sizes", default={}) column_sizes = column_sizes.get(itemtype.__name__, {}) for index, column in enumerate(columns): if column['name'] in column_sizes: column['width'] = column_sizes[column['name']] return columns def ReadGuiSetting(self, setting_name, default=None, do_json=True): setting_value = self.utility.read_config(setting_name, literal_eval=False) if do_json and setting_value: setting_value = json.loads(setting_value) elif not setting_value: setting_value = default return setting_value def WriteGuiSetting(self, setting_name, setting_value, do_json=True): self.utility.write_config( setting_name, json.dumps(setting_value) if do_json else setting_value) self.utility.flush_config() @forceWxThread def GoBack(self, scrollTo=None, topage=None): if topage: self.oldpage.pop() else: if len(self.oldpage) > 0: topage = self.oldpage.pop() else: return if topage == 'search_results': self.frame.actlist.selectTab('results') elif topage in ['channels', 'selectedchannel', 'mychannel']: self.frame.actlist.selectTab('channels') else: self.frame.actlist.selectTab(topage) self.ShowPage(topage) self.oldpage.pop() # remove curpage from history if scrollTo: self.ScrollTo(scrollTo) def dosearch(self, input=None): if input is None: sf = self.frame.top_bg.searchField if sf is None: return input = sf.GetValue() if input: input = input.strip() if input == '': return else: return self.frame.top_bg.searchField.SetValue(input) if self.frame.startDownloadFromArg(input): self.frame.top_bg.searchField.Clear() self.ShowPage('my_files') else: keywords = split_into_keywords(input) keywords = [keyword for keyword in keywords if len(keyword) > 1] if len(keywords) == 0: self.Notify( 'Please enter a search term', "Your search term '%s' was either to small or to general." % input, icon=wx.ART_INFORMATION) else: self.frame.top_bg.StartSearch() self.current_search_query = keywords self._logger.debug("GUIUtil: searchFiles: %s %s", keywords, time()) #self.frame.searchlist.Freeze() self.torrentsearch_manager.setSearchKeywords(keywords) self.channelsearch_manager.setSearchKeywords(keywords) # We set oldkeywords to '', which will trigger a reset in SetKeywords (called from ShowPage). # This avoids calling reset twice. # Niels: 17-09-2012, unfortunately showpage calls show(true) # which results in the dirty items being refreshed. # We need to call Reset in order to prevent this from happening self.frame.searchlist.Reset() self.ShowPage('search_results', keywords) # We now have to call thaw, otherwise loading message will not be shown. #self.frame.searchlist.Thaw() # Peform local search self.torrentsearch_manager.set_gridmgr( self.frame.searchlist.GetManager()) self.channelsearch_manager.set_gridmgr( self.frame.searchlist.GetManager()) def db_thread(): self.torrentsearch_manager.refreshGrid() nr_peers_connected = self.torrentsearch_manager.searchDispersy( ) self.channelsearch_manager.searchDispersy() return nr_peers_connected def wx_thread(delayedResult): nr_peers_connected = delayedResult.get() if self and self.frame and self.frame.searchlist: self.frame.searchlist.SetMaxResults( nr_peers_connected + 1, keywords) self.frame.searchlist.NewResult() startWorker(wx_thread, db_thread, priority=1024) @forceWxThread def NewResult(self): self.frame.searchlist.NewResult() @forceWxThread def showChannelCategory(self, category, show=True): manager = self.frame.channellist.GetManager() manager.SetCategory(category, True) if show: self.ShowPage('channels') @forceWxThread def showLibrary(self, show=True): manager = self.frame.librarylist.GetManager() manager.do_or_schedule_refresh(True) if show: self.ShowPage('my_files') def showChannelFromId(self, channel_id): def db_callback(): channel = self.channelsearch_manager.getChannel(channel_id) self.showChannel(channel) startWorker(None, db_callback, priority=GUI_PRI_DISPERSY) @forceWxThread def showChannel(self, channel): if channel: manager = self.frame.selectedchannellist.GetManager() manager.refresh_if_required(channel) self.ShowPage('selectedchannel') if isinstance(channel, RemoteChannel): self.showChannelFromId(channel.id) def showChannels(self): self.frame.actlist.selectTab('channels') self.ShowPage('channels') @forceWxThread def showChannelResults(self, data_channel): self.frame.actlist.selectTab('channels') def subscribe_latestupdate_sort(a, b): val = cmp(a.modified, b.modified) if val == 0: return cmp(a.name, b.name) return val data = data_channel.values() data.sort(subscribe_latestupdate_sort, reverse=True) manager = self.frame.channellist.GetManager() manager.SetCategory('searchresults') manager.refresh(data) self.ShowPage('channels') @forceWxThread def showManageChannel(self, channel): self.frame.managechannel.SetChannel(channel) self.ShowPage('managechannel') @forceWxThread def showPlaylist(self, data): self.frame.playlist.Set(data) self.ShowPage('playlist') def OnList(self, goto_end, event=None): lists = { 'channels': self.frame.channellist, 'selectedchannel': self.frame.selectedchannellist, 'mychannel': self.frame.managechannel, 'search_results': self.frame.searchlist, 'my_files': self.frame.librarylist, 'creditmining': self.frame.creditminingpanel } if self.guiPage in lists and lists[self.guiPage].HasFocus(): lists[self.guiPage].ScrollToEnd(goto_end) elif event: event.Skip() def ScrollTo(self, id): lists = { 'channels': self.frame.channellist, 'selectedchannel': self.frame.selectedchannellist, 'mychannel': self.frame.managechannel, 'search_results': self.frame.searchlist, 'my_files': self.frame.librarylist, 'creditmining': self.frame.creditminingpanel } if self.guiPage in lists: lists[self.guiPage].ScrollToId(id) @forceWxThread def Notify(self, title, msg='', icon=wx.ART_INFORMATION): if not self or not self.frame or not self.frame.actlist: return if sys.platform == 'win32' and not self.frame.IsShownOnScreen(): self.frame.tbicon.Notify(title, msg, icon) else: if isinstance(icon, basestring): icon = wx.ArtProvider.GetBitmap(icon, wx.ART_FRAME_ICON) or \ GuiImageManager.getInstance().getImage(u"notify_%s.png" % icon) self.frame.actlist.Notify(msg or title, icon) def ShouldGuiUpdate(self): # Avoid WxPyDeadObject exception if self.frame and self.frame.ready: return self.frame.GUIupdate return True def addList(self, l): if l not in self.lists: self.lists.append(l) def toggleFamilyFilter(self, newState=None, setCheck=False): if newState is None: newState = not self.getFamilyFilter() self.utility.session.lm.category.set_family_filter(newState) for l in self.lists: if getattr(l, 'GotFilter', False): l.GotFilter(None) if setCheck: self.frame.SRstatusbar.ff_checkbox.SetValue(newState) self.frame.home.aw_panel.refreshNow() if newState: self.utility.write_config('family_filter', 1) else: self.utility.write_config('family_filter', 0) self.utility.flush_config() def getFamilyFilter(self): catobj = self.utility.session.lm.category return catobj.family_filter_enabled() def set_firewall_restart(self, b): self.firewall_restart = b @forceWxThread def MarkAsFavorite(self, event, channel): if channel: if event: button = event.GetEventObject() button.Enable(False) if hasattr(button, 'selected'): button.selected = False dlgname = 'MFdialog' if not self.ReadGuiSetting('show_%s' % dlgname, default=True): response = wx.ID_OK else: from Tribler.Main.Dialogs.ConfirmationDialog import ConfirmationDialog dlg = ConfirmationDialog( None, dlgname, "You are about to add \'%s\' to your list of favourite channels." % channel.name, "If you mark this channel as your favourite, you will be able to access its full content." ) response = dlg.ShowModal() if response == wx.ID_OK: @forceDBThread def add_vote(): self.channelsearch_manager.favorite(channel.id) wx.CallAfter(self.Notify, "Channel marked as favourite", "Marked channel '%s' as favourite" % channel.name, icon='favourite') if event: button.Enable(True) self.RefreshChannel(channel.id) add_vote() elif event: button.Enable(True) @forceWxThread def RemoveFavorite(self, event, channel): if channel: if event: button = event.GetEventObject() button.Enable(False) if hasattr(button, 'selected'): button.selected = False dlgname = 'RFdialog' if not self.ReadGuiSetting('show_%s' % dlgname, default=True): response = wx.ID_OK else: from Tribler.Main.Dialogs.ConfirmationDialog import ConfirmationDialog dlg = ConfirmationDialog( None, dlgname, "You are about to remove \'%s\' from your list of favourite channels." % channel.name, "If you remove this channel from your favourites, " "you will no longer be able to access its full content.") response = dlg.ShowModal() if response == wx.ID_OK: @forceDBThread def remove_vote(): self.channelsearch_manager.remove_vote(channel.id) wx.CallAfter(self.Notify, "Channel removed from favourites", "Removed channel '%s' from your favourites" % channel.name, icon='favourite') if event: button.Enable(True) self.RefreshChannel(channel.id) remove_vote() elif event: button.Enable(True) @forceWxThread def MarkAsSpam(self, event, channel): if channel: if event: button = event.GetEventObject() button.Enable(False) if hasattr(button, 'selected'): button.selected = False dlgname = 'MSdialog' if not self.ReadGuiSetting('show_%s' % dlgname, default=True): response = wx.ID_OK else: from Tribler.Main.Dialogs.ConfirmationDialog import ConfirmationDialog dlg = ConfirmationDialog( None, dlgname, "You are about to report channel \'%s\' as spam." % channel.name, "") response = dlg.ShowModal() if response == wx.ID_OK: @forceDBThread def remove_vote(): self.channelsearch_manager.spam(channel.id) wx.CallAfter(self.Notify, "Channel marked as spam", "Channel '%s' marked as spam" % channel.name) if event: button.Enable(True) self.RefreshChannel(channel.id) remove_vote() elif event: button.Enable(True) @forceWxThread def RemoveSpam(self, event, channel): if channel: if event: button = event.GetEventObject() button.Enable(False) if hasattr(button, 'selected'): button.selected = False dlgname = 'RSdialog' if not self.ReadGuiSetting('show_%s' % dlgname, default=True): response = wx.ID_OK else: from Tribler.Main.Dialogs.ConfirmationDialog import ConfirmationDialog dlg = ConfirmationDialog( None, dlgname, "You are about unmark channel \'%s\' as spam." % channel.name, "") response = dlg.ShowModal() if response == wx.ID_OK: @forceDBThread def remove_vote(): self.channelsearch_manager.remove_vote(channel.id) wx.CallAfter( self.Notify, "Channel unmarked as spam", "Channel '%s' unmarked as spam" % channel.name) if event: button.Enable(True) self.RefreshChannel(channel.id) remove_vote() elif event: button.Enable(True) def RefreshChannel(self, channelid): if self.guiPage in ['search_results', 'selectedchannel', 'channels']: list = self.GetSelectedPage() if self.guiPage == 'search_results': list.GetManager().refresh_partial(channelids=[channelid]) else: list.GetManager().refresh_partial((channelid, )) if self.guiPage == 'selectedchannel': wx.CallAfter(list.GetManager().reload, channelid) def SelectVideo(self, videofiles, selected_file=None): if len(videofiles) > 1: videofiles.sort() dialog = wx.SingleChoiceDialog( None, 'Tribler currently only supports playing one file at a time.\nSelect the file you want to play.', 'Which file do you want to play?', videofiles) if selected_file in videofiles: dialog.SetSelection(videofiles.index(selected_file)) selected_file = dialog.GetStringSelection() if dialog.ShowModal( ) == wx.ID_OK else None dialog.Destroy() return selected_file elif len(videofiles) == 1: return videofiles[0]
def __init__(self, params, single_instance_checker, installdir): self.params = params self.single_instance_checker = single_instance_checker self.installdir = self.configure_install_dir(installdir) self.state_dir = None self.error = None self.last_update = 0 self.ready = False self.done = False self.frame = None self.guiserver = GUITaskQueue.getInstance() self.said_start_playback = False self.decodeprogress = 0 self.old_reputation = 0 # DISPERSY will be set when available self.dispersy = None # BARTER_COMMUNITY will be set when both Dispersy and the EffortCommunity are available self.barter_community = None self.seedingmanager = None self.i2is = None self.torrentfeed = None self.webUI = None self.utility = None self.videoplayer = None try: bm = wx.Bitmap(os.path.join(self.installdir, 'Tribler', 'Main', 'vwxGUI', 'images', 'splash.png'), wx.BITMAP_TYPE_ANY) self.splash = GaugeSplash(bm) self.splash.setTicks(10) self.splash.Show() print >> sys.stderr, 'Client Starting Up.' print >> sys.stderr, "Tribler is using", self.installdir, "as working directory" self.splash.tick('Starting API') s = self.startAPI(self.splash.tick) print >> sys.stderr, "Tribler is expecting swift in", self.sconfig.get_swift_path() self.dispersy = s.lm.dispersy self.utility = Utility(self.installdir, s.get_state_dir()) self.utility.app = self self.utility.session = s self.guiUtility = GUIUtility.getInstance(self.utility, self.params, self) GUIDBProducer.getInstance(self.dispersy.callback) print >> sys.stderr, 'Tribler Version:', self.utility.lang.get('version'), ' Build:', self.utility.lang.get('build') self.splash.tick('Loading userdownloadchoice') from Tribler.Main.vwxGUI.UserDownloadChoice import UserDownloadChoice UserDownloadChoice.get_singleton().set_session_dir(s.get_state_dir()) self.splash.tick('Initializing Family Filter') cat = Category.getInstance() state = self.utility.config.Read('family_filter') if state in ('1', '0'): cat.set_family_filter(state == '1') else: self.utility.config.Write('family_filter', '1') self.utility.config.Flush() cat.set_family_filter(True) # Create global rate limiter self.splash.tick('Setting up ratelimiters') self.ratelimiter = UserDefinedMaxAlwaysOtherwiseDividedOverActiveSwarmsRateManager() # Counter to suppress some event from occurring self.ratestatecallbackcount = 0 # So we know if we asked for peer details last cycle self.lastwantpeers = [] # boudewijn 01/04/2010: hack to fix the seedupload speed that # was never used and defaulted to 0 (unlimited upload) maxup = self.utility.config.Read('maxuploadrate', "int") if maxup == -1: # no upload self.ratelimiter.set_global_max_speed(UPLOAD, 0.00001) self.ratelimiter.set_global_max_seedupload_speed(0.00001) else: self.ratelimiter.set_global_max_speed(UPLOAD, maxup) self.ratelimiter.set_global_max_seedupload_speed(maxup) maxdown = self.utility.config.Read('maxdownloadrate', "int") self.ratelimiter.set_global_max_speed(DOWNLOAD, maxdown) self.seedingmanager = GlobalSeedingManager(self.utility.config.Read) # Only allow updates to come in after we defined ratelimiter self.prevActiveDownloads = [] s.set_download_states_callback(self.sesscb_states_callback) # Schedule task for checkpointing Session, to avoid hash checks after # crashes. self.guiserver.add_task(self.guiservthread_checkpoint_timer, SESSION_CHECKPOINT_INTERVAL) self.utility.postAppInit(os.path.join(self.installdir, 'Tribler', 'Main', 'vwxGUI', 'images', 'tribler.ico')) # Put it here so an error is shown in the startup-error popup # Start server for instance2instance communication self.i2iconnhandler = InstanceConnectionHandler(self.i2ithread_readlinecallback) self.i2is = Instance2InstanceServer(I2I_LISTENPORT, self.i2iconnhandler) self.i2is.start() # Arno, 2010-01-15: VLC's reading behaviour of doing open-ended # Range: GETs causes performance problems in our code. Disable for now. # Arno, 2010-01-22: With the addition of a CachingStream the problem # is less severe (see VideoPlayer), so keep GET Range enabled. # # SimpleServer.RANGE_REQUESTS_ENABLED = False # Fire up the VideoPlayer, it abstracts away whether we're using # an internal or external video player. playbackmode = self.utility.config.Read('videoplaybackmode', "int") self.videoplayer = VideoPlayer.getInstance(httpport=VIDEOHTTP_LISTENPORT) self.videoplayer.register(self.utility, preferredplaybackmode=playbackmode) notification_init(self.utility) self.guiUtility.register() channel_only = os.path.exists(os.path.join(self.installdir, 'joinchannel')) if channel_only: f = open(os.path.join(self.installdir, 'joinchannel'), 'rb') channel_only = f.readline() f.close() self.frame = MainFrame(None, channel_only, PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(self.utility.getPath()), self.splash.tick) # Arno, 2011-06-15: VLC 1.1.10 pops up separate win, don't have two. self.frame.videoframe = None if PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(self.utility.getPath()): vlcwrap = self.videoplayer.get_vlcwrap() self.frame.videoframe = VideoDummyFrame(self.frame.videoparentpanel, self.utility, vlcwrap) self.videoplayer.set_videoframe(self.frame.videoframe) if sys.platform == 'win32': wx.CallAfter(self.frame.top_bg.Refresh) wx.CallAfter(self.frame.top_bg.Layout) else: self.frame.top_bg.Layout() # Arno, 2007-05-03: wxWidgets 2.8.3.0 and earlier have the MIME-type for .bmp # files set to 'image/x-bmp' whereas 'image/bmp' is the official one. try: bmphand = None hands = wx.Image.GetHandlers() for hand in hands: # print "Handler",hand.GetExtension(),hand.GetType(),hand.GetMimeType() if hand.GetMimeType() == 'image/x-bmp': bmphand = hand break # wx.Image.AddHandler() if bmphand is not None: bmphand.SetMimeType('image/bmp') except: # wx < 2.7 don't like wx.Image.GetHandlers() print_exc() self.splash.Destroy() self.frame.Show(True) self.torrentfeed = RssParser.getInstance() self.webUI = None if self.utility.config.Read('use_webui', "boolean"): try: from Tribler.Main.webUI.webUI import WebUI self.webUI = WebUI.getInstance(self.guiUtility.library_manager, self.guiUtility.torrentsearch_manager, self.utility.config.Read('webui_port', "int")) self.webUI.start() except Exception: print_exc() wx.CallAfter(self.PostInit2) # 08/02/10 Boudewijn: Working from home though console # doesn't allow me to press close. The statement below # gracefully closes Tribler after 120 seconds. # wx.CallLater(120*1000, wx.GetApp().Exit) status = get_status_holder("LivingLab") status.add_reporter(NullReporter("Periodically remove all events", 0)) # status.add_reporter(LivingLabPeriodicReporter("Living lab CS reporter", 300, "Tribler client")) # Report every 5 minutes # status.add_reporter(LivingLabPeriodicReporter("Living lab CS reporter", 30, "Tribler client")) # Report every 30 seconds - ONLY FOR TESTING # report client version status.create_and_add_event("client-startup-version", [self.utility.lang.get("version")]) status.create_and_add_event("client-startup-build", [self.utility.lang.get("build")]) status.create_and_add_event("client-startup-build-date", [self.utility.lang.get("build_date")]) self.ready = True except Exception as e: self.onError(e) return False
class ABCApp(): def __init__(self, params, single_instance_checker, installdir): self.params = params self.single_instance_checker = single_instance_checker self.installdir = self.configure_install_dir(installdir) self.state_dir = None self.error = None self.last_update = 0 self.ready = False self.done = False self.frame = None self.guiserver = GUITaskQueue.getInstance() self.said_start_playback = False self.decodeprogress = 0 self.old_reputation = 0 # DISPERSY will be set when available self.dispersy = None # BARTER_COMMUNITY will be set when both Dispersy and the EffortCommunity are available self.barter_community = None self.seedingmanager = None self.i2is = None self.torrentfeed = None self.webUI = None self.utility = None self.videoplayer = None try: bm = wx.Bitmap(os.path.join(self.installdir, 'Tribler', 'Main', 'vwxGUI', 'images', 'splash.png'), wx.BITMAP_TYPE_ANY) self.splash = GaugeSplash(bm) self.splash.setTicks(10) self.splash.Show() print >> sys.stderr, 'Client Starting Up.' print >> sys.stderr, "Tribler is using", self.installdir, "as working directory" self.splash.tick('Starting API') s = self.startAPI(self.splash.tick) print >> sys.stderr, "Tribler is expecting swift in", self.sconfig.get_swift_path() self.dispersy = s.lm.dispersy self.utility = Utility(self.installdir, s.get_state_dir()) self.utility.app = self self.utility.session = s self.guiUtility = GUIUtility.getInstance(self.utility, self.params, self) GUIDBProducer.getInstance(self.dispersy.callback) print >> sys.stderr, 'Tribler Version:', self.utility.lang.get('version'), ' Build:', self.utility.lang.get('build') self.splash.tick('Loading userdownloadchoice') from Tribler.Main.vwxGUI.UserDownloadChoice import UserDownloadChoice UserDownloadChoice.get_singleton().set_session_dir(s.get_state_dir()) self.splash.tick('Initializing Family Filter') cat = Category.getInstance() state = self.utility.config.Read('family_filter') if state in ('1', '0'): cat.set_family_filter(state == '1') else: self.utility.config.Write('family_filter', '1') self.utility.config.Flush() cat.set_family_filter(True) # Create global rate limiter self.splash.tick('Setting up ratelimiters') self.ratelimiter = UserDefinedMaxAlwaysOtherwiseDividedOverActiveSwarmsRateManager() # Counter to suppress some event from occurring self.ratestatecallbackcount = 0 # So we know if we asked for peer details last cycle self.lastwantpeers = [] # boudewijn 01/04/2010: hack to fix the seedupload speed that # was never used and defaulted to 0 (unlimited upload) maxup = self.utility.config.Read('maxuploadrate', "int") if maxup == -1: # no upload self.ratelimiter.set_global_max_speed(UPLOAD, 0.00001) self.ratelimiter.set_global_max_seedupload_speed(0.00001) else: self.ratelimiter.set_global_max_speed(UPLOAD, maxup) self.ratelimiter.set_global_max_seedupload_speed(maxup) maxdown = self.utility.config.Read('maxdownloadrate', "int") self.ratelimiter.set_global_max_speed(DOWNLOAD, maxdown) self.seedingmanager = GlobalSeedingManager(self.utility.config.Read) # Only allow updates to come in after we defined ratelimiter self.prevActiveDownloads = [] s.set_download_states_callback(self.sesscb_states_callback) # Schedule task for checkpointing Session, to avoid hash checks after # crashes. self.guiserver.add_task(self.guiservthread_checkpoint_timer, SESSION_CHECKPOINT_INTERVAL) self.utility.postAppInit(os.path.join(self.installdir, 'Tribler', 'Main', 'vwxGUI', 'images', 'tribler.ico')) # Put it here so an error is shown in the startup-error popup # Start server for instance2instance communication self.i2iconnhandler = InstanceConnectionHandler(self.i2ithread_readlinecallback) self.i2is = Instance2InstanceServer(I2I_LISTENPORT, self.i2iconnhandler) self.i2is.start() # Arno, 2010-01-15: VLC's reading behaviour of doing open-ended # Range: GETs causes performance problems in our code. Disable for now. # Arno, 2010-01-22: With the addition of a CachingStream the problem # is less severe (see VideoPlayer), so keep GET Range enabled. # # SimpleServer.RANGE_REQUESTS_ENABLED = False # Fire up the VideoPlayer, it abstracts away whether we're using # an internal or external video player. playbackmode = self.utility.config.Read('videoplaybackmode', "int") self.videoplayer = VideoPlayer.getInstance(httpport=VIDEOHTTP_LISTENPORT) self.videoplayer.register(self.utility, preferredplaybackmode=playbackmode) notification_init(self.utility) self.guiUtility.register() channel_only = os.path.exists(os.path.join(self.installdir, 'joinchannel')) if channel_only: f = open(os.path.join(self.installdir, 'joinchannel'), 'rb') channel_only = f.readline() f.close() self.frame = MainFrame(None, channel_only, PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(self.utility.getPath()), self.splash.tick) # Arno, 2011-06-15: VLC 1.1.10 pops up separate win, don't have two. self.frame.videoframe = None if PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(self.utility.getPath()): vlcwrap = self.videoplayer.get_vlcwrap() self.frame.videoframe = VideoDummyFrame(self.frame.videoparentpanel, self.utility, vlcwrap) self.videoplayer.set_videoframe(self.frame.videoframe) if sys.platform == 'win32': wx.CallAfter(self.frame.top_bg.Refresh) wx.CallAfter(self.frame.top_bg.Layout) else: self.frame.top_bg.Layout() # Arno, 2007-05-03: wxWidgets 2.8.3.0 and earlier have the MIME-type for .bmp # files set to 'image/x-bmp' whereas 'image/bmp' is the official one. try: bmphand = None hands = wx.Image.GetHandlers() for hand in hands: # print "Handler",hand.GetExtension(),hand.GetType(),hand.GetMimeType() if hand.GetMimeType() == 'image/x-bmp': bmphand = hand break # wx.Image.AddHandler() if bmphand is not None: bmphand.SetMimeType('image/bmp') except: # wx < 2.7 don't like wx.Image.GetHandlers() print_exc() self.splash.Destroy() self.frame.Show(True) self.torrentfeed = RssParser.getInstance() self.webUI = None if self.utility.config.Read('use_webui', "boolean"): try: from Tribler.Main.webUI.webUI import WebUI self.webUI = WebUI.getInstance(self.guiUtility.library_manager, self.guiUtility.torrentsearch_manager, self.utility.config.Read('webui_port', "int")) self.webUI.start() except Exception: print_exc() wx.CallAfter(self.PostInit2) # 08/02/10 Boudewijn: Working from home though console # doesn't allow me to press close. The statement below # gracefully closes Tribler after 120 seconds. # wx.CallLater(120*1000, wx.GetApp().Exit) status = get_status_holder("LivingLab") status.add_reporter(NullReporter("Periodically remove all events", 0)) # status.add_reporter(LivingLabPeriodicReporter("Living lab CS reporter", 300, "Tribler client")) # Report every 5 minutes # status.add_reporter(LivingLabPeriodicReporter("Living lab CS reporter", 30, "Tribler client")) # Report every 30 seconds - ONLY FOR TESTING # report client version status.create_and_add_event("client-startup-version", [self.utility.lang.get("version")]) status.create_and_add_event("client-startup-build", [self.utility.lang.get("build")]) status.create_and_add_event("client-startup-build-date", [self.utility.lang.get("build_date")]) self.ready = True except Exception as e: self.onError(e) return False def PostInit2(self): self.frame.Raise() self.startWithRightView() self.set_reputation() s = self.utility.session s.add_observer(self.sesscb_ntfy_reachable, NTFY_REACHABLE, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_activities, NTFY_ACTIVITIES, [NTFY_INSERT], cache=10) s.add_observer(self.sesscb_ntfy_channelupdates, NTFY_CHANNELCAST, [NTFY_INSERT, NTFY_UPDATE, NTFY_CREATE, NTFY_STATE, NTFY_MODIFIED], cache=10) s.add_observer(self.sesscb_ntfy_channelupdates, NTFY_VOTECAST, [NTFY_UPDATE], cache=10) s.add_observer(self.sesscb_ntfy_myprefupdates, NTFY_MYPREFERENCES, [NTFY_INSERT, NTFY_UPDATE]) s.add_observer(self.sesscb_ntfy_torrentupdates, NTFY_TORRENTS, [NTFY_UPDATE, NTFY_INSERT], cache=10) s.add_observer(self.sesscb_ntfy_playlistupdates, NTFY_PLAYLISTS, [NTFY_INSERT, NTFY_UPDATE]) s.add_observer(self.sesscb_ntfy_commentupdates, NTFY_COMMENTS, [NTFY_INSERT, NTFY_DELETE]) s.add_observer(self.sesscb_ntfy_modificationupdates, NTFY_MODIFICATIONS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_moderationupdats, NTFY_MODERATIONS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_markingupdates, NTFY_MARKINGS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_torrentfinished, NTFY_TORRENTS, [NTFY_FINISHED]) s.add_observer(self.sesscb_ntfy_magnet, NTFY_TORRENTS, [NTFY_MAGNET_GOT_PEERS, NTFY_MAGNET_PROGRESS, NTFY_MAGNET_STARTED, NTFY_MAGNET_CLOSE]) self.dispersy.attach_progress_handler(self.frame.progressHandler) self.dispersy.callback.attach_exception_handler(self.frame.exceptionHandler) startWorker(None, self.loadSessionCheckpoint, delay=5.0, workerType="guiTaskQueue") # initialize the torrent feed thread channelcast = ChannelCastDBHandler.getInstance() def db_thread(): return channelcast.getMyChannelId() def wx_thread(delayedResult): my_channel = delayedResult.get() if my_channel: self.torrentfeed.register(self.utility.session, my_channel) self.torrentfeed.addCallback(my_channel, self.guiUtility.channelsearch_manager.createTorrentFromDef) startWorker(wx_thread, db_thread, delay=5.0) def startAPI(self, progress): # Start Tribler Session defaultConfig = SessionStartupConfig() state_dir = defaultConfig.get_state_dir() if not state_dir: state_dir = Session.get_default_state_dir() cfgfilename = Session.get_default_config_filename(state_dir) progress('Loading sessionconfig') if DEBUG: print >> sys.stderr, "main: Session config", cfgfilename try: self.sconfig = SessionStartupConfig.load(cfgfilename) except: self.sconfig = SessionStartupConfig() self.sconfig.set_state_dir(state_dir) self.sconfig.set_install_dir(self.installdir) # Boudewijn, 2013-06-17: Enable Dispersy tunnel (hard-coded) # self.sconfig.set_dispersy_tunnel_over_swift(True) # Boudewijn, 2013-07-17: Disabling Dispersy tunnel (hard-coded) self.sconfig.set_dispersy_tunnel_over_swift(False) # Arno, 2010-03-31: Hard upgrade to 50000 torrents collected self.sconfig.set_torrent_collecting_max_torrents(50000) # Arno, 2012-05-21: Swift part II swiftbinpath = os.path.join(self.sconfig.get_install_dir(), "swift") if sys.platform == "darwin": if not os.path.exists(swiftbinpath): swiftbinpath = os.path.join(os.getcwdu(), "..", "MacOS", "swift") self.sconfig.set_swift_path(swiftbinpath) progress('Loading downloadconfig') dlcfgfilename = get_default_dscfg_filename(self.sconfig.get_state_dir()) if DEBUG: print >> sys.stderr, "main: Download config", dlcfgfilename try: defaultDLConfig = DefaultDownloadStartupConfig.load(dlcfgfilename) except: defaultDLConfig = DefaultDownloadStartupConfig.getInstance() if not defaultDLConfig.get_dest_dir(): defaultDLConfig.set_dest_dir(get_default_dest_dir()) if not os.path.isdir(defaultDLConfig.get_dest_dir()): os.makedirs(defaultDLConfig.get_dest_dir()) # Setting torrent collection dir based on default download dir if not self.sconfig.get_torrent_collecting_dir(): self.sconfig.set_torrent_collecting_dir(os.path.join(defaultDLConfig.get_dest_dir(), STATEDIR_TORRENTCOLL_DIR)) if not self.sconfig.get_swift_meta_dir(): self.sconfig.set_swift_meta_dir(os.path.join(defaultDLConfig.get_dest_dir(), STATEDIR_SWIFTRESEED_DIR)) # 15/05/12 niels: fixing swift port defaultDLConfig.set_swift_listen_port(7758) progress('Creating session/Checking database (may take a minute)') s = Session(self.sconfig) s.start() def define_communities(): from Tribler.community.search.community import SearchCommunity from Tribler.community.allchannel.community import AllChannelCommunity from Tribler.community.bartercast3.community import BarterCommunity from Tribler.community.channel.community import ChannelCommunity from Tribler.community.channel.preview import PreviewChannelCommunity # must be called on the Dispersy thread dispersy.define_auto_load(SearchCommunity, (s.dispersy_member,), load=True) dispersy.define_auto_load(AllChannelCommunity, (s.dispersy_member,), {"auto_join_channel": True} if sys.argv[0].endswith("dispersy-channel-booster.py") else {}, load=True) # 17/07/13 Boudewijn: the missing-member message send by the BarterCommunity on the swift port is crashing # 6.1 clients. We will disable the BarterCommunity for version 6.2, giving people some time to upgrade # their version before enabling it again. # if swift_process: # dispersy.define_auto_load(BarterCommunity, # (swift_process,), # load=True) dispersy.define_auto_load(ChannelCommunity, load=True) dispersy.define_auto_load(PreviewChannelCommunity) print >> sys.stderr, "tribler: Dispersy communities are ready" swift_process = s.get_swift_proc() and s.get_swift_process() dispersy = s.get_dispersy_instance() dispersy.callback.call(define_communities) return s def configure_install_dir(self, installdir): # Niels, 2011-03-03: Working dir sometimes set to a browsers working dir # only seen on windows # apply trick to obtain the executable location # see http://www.py2exe.org/index.cgi/WhereAmI # Niels, 2012-01-31: py2exe should only apply to windows if sys.platform == 'win32': def we_are_frozen(): """Returns whether we are frozen via py2exe. This will affect how we find out where we are located.""" return hasattr(sys, "frozen") def module_path(): """ This will get us the program's directory, even if we are frozen using py2exe""" if we_are_frozen(): return os.path.dirname(unicode(sys.executable, sys.getfilesystemencoding())) filedir = os.path.dirname(unicode(__file__, sys.getfilesystemencoding())) return os.path.abspath(os.path.join(filedir, '..', '..')) return module_path() return installdir @forceWxThread def sesscb_ntfy_myprefupdates(self, subject, changeType, objectID, *args): if self.ready and self.frame.ready: if changeType == NTFY_INSERT: if self.frame.searchlist: manager = self.frame.searchlist.GetManager() manager.downloadStarted(objectID) manager = self.frame.selectedchannellist.GetManager() manager.downloadStarted(objectID) manager = self.frame.librarylist.GetManager() manager.downloadStarted(objectID) def set_reputation(self): def do_db(): nr_connections = 0 nr_channel_connections = 0 if self.dispersy: for community in self.dispersy.get_communities(): from Tribler.community.search.community import SearchCommunity from Tribler.community.allchannel.community import AllChannelCommunity if isinstance(community, SearchCommunity): nr_connections = community.get_nr_connections() elif isinstance(community, AllChannelCommunity): nr_channel_connections = community.get_nr_connections() return nr_connections, nr_channel_connections def do_wx(delayedResult): nr_connections, nr_channel_connections = delayedResult.get() # self.frame.SRstatusbar.set_reputation(myRep, total_down, total_up) # bitmap is 16px wide, -> but first and last pixel do not add anything. percentage = min(1.0, (nr_connections + 1) / 16.0) self.frame.SRstatusbar.SetConnections(percentage, nr_connections, nr_channel_connections) """ set the reputation in the GUI""" if self.ready and self.frame.ready: startWorker(do_wx, do_db, uId=u"tribler.set_reputation") startWorker(None, self.set_reputation, delay=5.0, workerType="guiTaskQueue") def _dispersy_get_barter_community(self): try: return self.dispersy.get_community(BARTER_MASTER_MEMBER_PUBLIC_KEY_DIGEST, load=False, auto_load=False) except KeyError: return None def sesscb_states_callback(self, dslist): if not self.ready: return (5.0, []) wantpeers = [] self.ratestatecallbackcount += 1 if DEBUG: torrentdb = self.utility.session.open_dbhandler(NTFY_TORRENTS) peerdb = self.utility.session.open_dbhandler(NTFY_PEERS) print >> sys.stderr, "main: Stats: Total torrents found", torrentdb.size(), "peers", peerdb.size() try: # Print stats on Console if DEBUG: if self.ratestatecallbackcount % 5 == 0: for ds in dslist: safename = repr(ds.get_download().get_def().get_name()) if DEBUG: print >> sys.stderr, "%s %s %.1f%% dl %.1f ul %.1f n %d" % (safename, dlstatus_strings[ds.get_status()], 100.0 * ds.get_progress(), ds.get_current_speed(DOWNLOAD), ds.get_current_speed(UPLOAD), ds.get_num_peers()) # print >>sys.stderr,"main: Infohash:",`ds.get_download().get_def().get_infohash()` if ds.get_status() == DLSTATUS_STOPPED_ON_ERROR: print >> sys.stderr, "main: Error:", repr(ds.get_error()) # Pass DownloadStates to libaryView no_collected_list = [] try: coldir = os.path.basename(os.path.abspath(self.utility.session.get_torrent_collecting_dir())) for ds in dslist: destdir = os.path.basename(ds.get_download().get_dest_dir()) if destdir != coldir: no_collected_list.append(ds) # Arno, 2012-07-17: Retrieving peerlist for the DownloadStates takes CPU # so only do it when needed for display. wantpeers.extend(self.guiUtility.library_manager.download_state_callback(no_collected_list)) except: print_exc() # Update bandwidth statistics in the Barter Community if not self.barter_community: self.barter_community = self.dispersy.callback.call(self._dispersy_get_barter_community) if self.barter_community and not isinstance(self.barter_community, HardKilledCommunity): if self.barter_community.has_been_killed: # set BARTER_COMMUNITY to None. next state callback we will again get the # community resulting in the HardKilledCommunity instead self.barter_community = None else: if True in self.lastwantpeers: self.dispersy.callback.register(self.barter_community.download_state_callback, (dslist, True)) # only request peer info every 120 intervals if self.ratestatecallbackcount % 120 == 0: wantpeers.append(True) # Find State of currently playing video playds = None d = self.videoplayer.get_vod_download() for ds in dslist: if ds.get_download() == d: playds = ds # Apply status displaying from SwarmPlayer if playds: def do_video(): if playds.get_status() == DLSTATUS_HASHCHECKING: progress = progress_consec = playds.get_progress() else: progress = playds.get_vod_prebuffering_progress() progress_consec = playds.get_vod_prebuffering_progress_consec() self.videoplayer.set_player_status_and_progress(progress, progress_consec, \ playds.get_pieces_complete() if playds.get_progress() < 1.0 else [True]) wx.CallAfter(do_video) # Check to see if a download has finished newActiveDownloads = [] doCheckpoint = False for ds in dslist: state = ds.get_status() safename = ds.get_download().get_def().get_name() if state == DLSTATUS_DOWNLOADING: newActiveDownloads.append(safename) elif state == DLSTATUS_SEEDING: if safename in self.prevActiveDownloads: download = ds.get_download() cdef = download.get_def() coldir = os.path.basename(os.path.abspath(self.utility.session.get_torrent_collecting_dir())) destdir = os.path.basename(download.get_dest_dir()) if destdir != coldir: hash = cdef.get_id() notifier = Notifier.getInstance() notifier.notify(NTFY_TORRENTS, NTFY_FINISHED, hash, safename) # Arno, 2012-05-04: Swift reseeding if self.utility.config.Read('swiftreseed') == 1 and cdef.get_def_type() == 'torrent' and not download.get_selected_files(): self.sesscb_reseed_via_swift(download) doCheckpoint = True self.prevActiveDownloads = newActiveDownloads if doCheckpoint: self.utility.session.checkpoint() self.seedingmanager.apply_seeding_policy(no_collected_list) # Adjust speeds once every 4 seconds adjustspeeds = False if self.ratestatecallbackcount % 4 == 0: adjustspeeds = True if adjustspeeds: swift_dslist = [ds for ds in no_collected_list if ds.get_download().get_def().get_def_type() == 'swift'] self.ratelimiter.add_downloadstatelist(swift_dslist) self.ratelimiter.adjust_speeds() if DEBUG_DOWNLOADS: for ds in dslist: cdef = ds.get_download().get_def() state = ds.get_status() if cdef.get_def_type() == 'swift': safename = cdef.get_name() print >> sys.stderr, "tribler: SW", dlstatus_strings[state], safename, ds.get_current_speed(UPLOAD) else: print >> sys.stderr, "tribler: BT", dlstatus_strings[state], cdef.get_name(), ds.get_current_speed(UPLOAD) except: print_exc() self.lastwantpeers = wantpeers return (1.0, wantpeers) def loadSessionCheckpoint(self): # Niels: first remove all "swift" torrent collect checkpoints dir = self.utility.session.get_downloads_pstate_dir() coldir = os.path.basename(os.path.abspath(self.utility.session.get_torrent_collecting_dir())) filelist = os.listdir(dir) filelist = [os.path.join(dir, filename) for filename in filelist if filename.endswith('.pickle')] for file in filelist: try: pstate = self.utility.session.lm.load_download_pstate(file) dlconfig = pstate['dlconfig'] if dlconfig.get('saveas', ''): destdir = os.path.basename(dlconfig['saveas']) if destdir == coldir: os.remove(file) except: pass from Tribler.Main.vwxGUI.UserDownloadChoice import UserDownloadChoice user_download_choice = UserDownloadChoice.get_singleton() initialdlstatus_dict = {} for id, state in user_download_choice.get_download_states().iteritems(): if state == 'stop': initialdlstatus_dict[id] = DLSTATUS_STOPPED self.utility.session.load_checkpoint(initialdlstatus_dict=initialdlstatus_dict) def guiservthread_checkpoint_timer(self): """ Periodically checkpoint Session """ if self.done: return try: print >> sys.stderr, "main: Checkpointing Session" self.utility.session.checkpoint() self.guiserver.add_task(self.guiservthread_checkpoint_timer, SESSION_CHECKPOINT_INTERVAL) except: print_exc() @forceWxThread def sesscb_ntfy_activities(self, events): if self.ready and self.frame.ready: for args in events: objectID = args[2] args = args[3:] self.frame.setActivity(objectID, *args) @forceWxThread def sesscb_ntfy_reachable(self, subject, changeType, objectID, msg): if self.ready and self.frame.ready: self.frame.SRstatusbar.onReachable() @forceWxThread def sesscb_ntfy_channelupdates(self, events): if self.ready and self.frame.ready: for args in events: subject = args[0] changeType = args[1] objectID = args[2] if self.frame.channellist: if len(args) > 3: myvote = args[3] else: myvote = False manager = self.frame.channellist.GetManager() manager.channelUpdated(objectID, subject == NTFY_VOTECAST, myvote=myvote) manager = self.frame.selectedchannellist.GetManager() manager.channelUpdated(objectID, stateChanged=changeType == NTFY_STATE, modified=changeType == NTFY_MODIFIED) if changeType == NTFY_CREATE: if self.frame.channellist: self.frame.channellist.SetMyChannelId(objectID) self.torrentfeed.register(self.utility.session, objectID) self.torrentfeed.addCallback(objectID, self.guiUtility.channelsearch_manager.createTorrentFromDef) self.frame.managechannel.channelUpdated(objectID, created=changeType == NTFY_CREATE, modified=changeType == NTFY_MODIFIED) @forceWxThread def sesscb_ntfy_torrentupdates(self, events): if self.ready and self.frame.ready: infohashes = [args[2] for args in events] if self.frame.searchlist: manager = self.frame.searchlist.GetManager() manager.torrentsUpdated(infohashes) manager = self.frame.selectedchannellist.GetManager() manager.torrentsUpdated(infohashes) manager = self.frame.playlist.GetManager() manager.torrentsUpdated(infohashes) manager = self.frame.librarylist.GetManager() manager.torrentsUpdated(infohashes) def sesscb_ntfy_torrentfinished(self, subject, changeType, objectID, *args): self.guiUtility.Notify("Download Completed", "Torrent '%s' has finished downloading. Now seeding." % args[0], icon='seed') if self.ready and self.frame.ready: self.guiUtility.torrentstate_manager.torrentFinished(objectID) def sesscb_ntfy_magnet(self, subject, changetype, objectID, *args): if changetype == NTFY_MAGNET_STARTED: self.guiUtility.library_manager.magnet_started(objectID) elif changetype == NTFY_MAGNET_GOT_PEERS: self.guiUtility.library_manager.magnet_got_peers(objectID, args[0]) elif changetype == NTFY_MAGNET_PROGRESS: self.guiUtility.library_manager.magnet_got_piece(objectID, args[0]) elif changetype == NTFY_MAGNET_CLOSE: self.guiUtility.library_manager.magnet_close(objectID) @forceWxThread def sesscb_ntfy_playlistupdates(self, subject, changeType, objectID, *args): if self.ready and self.frame.ready: if changeType == NTFY_INSERT: self.frame.managechannel.playlistCreated(objectID) manager = self.frame.selectedchannellist.GetManager() manager.playlistCreated(objectID) else: self.frame.managechannel.playlistUpdated(objectID, modified=changeType == NTFY_MODIFIED) if len(args) > 0: infohash = args[0] else: infohash = False manager = self.frame.selectedchannellist.GetManager() manager.playlistUpdated(objectID, infohash, modified=changeType == NTFY_MODIFIED) manager = self.frame.playlist.GetManager() manager.playlistUpdated(objectID, modified=changeType == NTFY_MODIFIED) @forceWxThread def sesscb_ntfy_commentupdates(self, subject, changeType, objectID, *args): if self.ready and self.frame.ready: self.frame.selectedchannellist.OnCommentCreated(objectID) self.frame.playlist.OnCommentCreated(objectID) @forceWxThread def sesscb_ntfy_modificationupdates(self, subject, changeType, objectID, *args): if self.ready and self.frame.ready: self.frame.selectedchannellist.OnModificationCreated(objectID) self.frame.playlist.OnModificationCreated(objectID) @forceWxThread def sesscb_ntfy_moderationupdats(self, subject, changeType, objectID, *args): if self.ready and self.frame.ready: self.frame.selectedchannellist.OnModerationCreated(objectID) self.frame.playlist.OnModerationCreated(objectID) @forceWxThread def sesscb_ntfy_markingupdates(self, subject, changeType, objectID, *args): if self.ready and self.frame.ready: self.frame.selectedchannellist.OnMarkingCreated(objectID) self.frame.playlist.OnModerationCreated(objectID) @forceWxThread def onError(self, e): print_exc() type, value, stack = sys.exc_info() backtrace = traceback.format_exception(type, value, stack) win = FeedbackWindow("Unfortunately, Tribler ran into an internal error") win.CreateOutputWindow('') for line in backtrace: win.write(line) win.ShowModal() def MacOpenFile(self, filename): print >> sys.stderr, filename target = FileDropTarget(self.frame) target.OnDropFiles(None, None, [filename]) def OnExit(self): print >> sys.stderr, "main: ONEXIT" self.ready = False self.done = True # write all persistent data to disk if self.i2is: self.i2is.shutdown() if self.torrentfeed: self.torrentfeed.shutdown() self.torrentfeed.delInstance() if self.webUI: self.webUI.stop() if self.guiserver: self.guiserver.shutdown(True) self.guiserver.delInstance() if self.videoplayer: self.videoplayer.shutdown() self.videoplayer.delInstance() delete_status_holders() if self.frame: self.frame.Destroy() del self.frame # Don't checkpoint, interferes with current way of saving Preferences, # see Tribler/Main/Dialogs/abcoption.py if self.utility: # Niels: lets add a max waiting time for this session shutdown. session_shutdown_start = time() self.utility.session.shutdown(hacksessconfcheckpoint=False) # Arno, 2012-07-12: Shutdown should be quick # Niels, 2013-03-21: However, setting it too low will prevent checkpoints from being written to disk waittime = 60 while not self.utility.session.has_shutdown(): diff = time() - session_shutdown_start if diff > waittime: print >> sys.stderr, "main: ONEXIT NOT Waiting for Session to shutdown, took too long" break print >> sys.stderr, "main: ONEXIT Waiting for Session to shutdown, will wait for an additional %d seconds" % (waittime - diff) sleep(3) print >> sys.stderr, "main: ONEXIT Session is shutdown" try: print >> sys.stderr, "main: ONEXIT cleaning database" peerdb = self.utility.session.open_dbhandler(NTFY_PEERS) peerdb._db.clean_db(randint(0, 24) == 0, exiting=True) except: print_exc() print >> sys.stderr, "main: ONEXIT deleting instances" Session.del_instance() GUIUtility.delInstance() GUIDBProducer.delInstance() DefaultDownloadStartupConfig.delInstance() if SQLiteCacheDB.hasInstance(): SQLiteCacheDB.getInstance().close_all() SQLiteCacheDB.delInstance() if not ALLOW_MULTIPLE: del self.single_instance_checker return 0 def db_exception_handler(self, e): if DEBUG: print >> sys.stderr, "main: Database Exception handler called", e, "value", e.args, "#" try: if e.args[1] == "DB object has been closed": return # We caused this non-fatal error, don't show. if self.error is not None and self.error.args[1] == e.args[1]: return # don't repeat same error except: print >> sys.stderr, "main: db_exception_handler error", e, type(e) print_exc() # print_stack() self.onError(e) def getConfigPath(self): return self.utility.getConfigPath() def startWithRightView(self): if self.params[0] != "": self.guiUtility.ShowPage('my_files') def i2ithread_readlinecallback(self, ic, cmd): """ Called by Instance2Instance thread """ print >> sys.stderr, "main: Another instance called us with cmd", cmd ic.close() if cmd.startswith('START '): param = cmd[len('START '):].strip() torrentfilename = None if param.startswith('http:'): # Retrieve from web f = tempfile.NamedTemporaryFile() n = urllib2.urlopen(param) data = n.read() f.write(data) f.close() n.close() torrentfilename = f.name else: torrentfilename = param # Switch to GUI thread # New for 5.0: Start in VOD mode def start_asked_download(): if torrentfilename.startswith("magnet:"): self.frame.startDownloadFromMagnet(torrentfilename) elif torrentfilename.startswith("tswift://") or torrentfilename.startswith("ppsp://"): self.frame.startDownloadFromSwift(torrentfilename) else: self.frame.startDownload(torrentfilename) self.guiUtility.ShowPage('my_files') wx.CallAfter(start_asked_download) def sesscb_reseed_via_swift(self, td, callback=None): # Arno, 2012-05-07: root hash calculation may take long time, halting # SessionCallbackThread meaning download statuses won't be updated. # Offload to diff thread. # t = Thread(target=self.workerthread_reseed_via_swift_run, args=(td, callback), name="SwiftRootHashCalculator") t.start() # apparently daemon by default def workerthread_reseed_via_swift_run(self, td, callback=None): # Open issues: # * how to display these "parallel" downloads in GUI? # * make swift reseed user configurable (see 'swiftreseed' in utility.py # * roothash calc on separate thread? # * Update pymDHT to one with swift interface. # * Save (infohash,roothash) pair such that when BT download is removed # the other is (kept/deleted/...) too. # try: if prctlimported: prctl.set_name(currentThread().getName()) # 1. Get torrent info tdef = td.get_def() destdir = td.get_dest_dir() # renaming swarmname for now not supported in swift if td.correctedinfoname != fix_filebasename(tdef.get_name_as_unicode()): return # 2. Convert to swift def sdef = SwiftDef() # RESEEDTODO: set to swift inf of pymDHT sdef.set_tracker("127.0.0.1:%d" % self.sconfig.get_swift_dht_listen_port()) iotuples = td.get_dest_files() for i, o in iotuples: # print >>sys.stderr,"python: add_content",i,o if len(iotuples) == 1: sdef.add_content(o) # single file .torrent else: xi = os.path.join(tdef.get_name_as_unicode(), i) if sys.platform == "win32": xi = xi.replace("\\", "/") si = xi.encode("UTF-8") # spec format sdef.add_content(o, si) # multi-file .torrent specpn = sdef.finalize(self.sconfig.get_swift_path(), destdir=destdir) # 3. Save swift files to metadata dir metadir = self.sconfig.get_swift_meta_dir() if len(iotuples) == 1: storagepath = iotuples[0][1] # Point to file on disk metapath = os.path.join(metadir, os.path.split(storagepath)[1]) try: shutil.move(storagepath + '.mhash', metapath + '.mhash') shutil.move(storagepath + '.mbinmap', metapath + '.mbinmap') except: print_exc() else: storagepath = destdir # Point to dest dir metapath = os.path.join(metadir, sdef.get_roothash_as_hex()) # Reuse .mhash and .mbinmap (happens automatically for single-file) try: shutil.move(specpn, metapath + '.mfspec') shutil.move(specpn + '.mhash', metapath + '.mhash') shutil.move(specpn + '.mbinmap', metapath + '.mbinmap') except: print_exc() # 4. Start Swift download via GUI Thread wx.CallAfter(self.frame.startReseedSwiftDownload, tdef, storagepath, sdef) # 5. Call the callback to notify if callback: callback(sdef) except: print_exc() raise