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