class SRstatusbar(wx.StatusBar): def __init__(self, parent): wx.StatusBar.__init__(self, parent, style=wx.ST_SIZEGRIP) # On Linux/OS X the resize handle and icons overlap, therefore we add an extra field. # On Windows this field is automatically set to 1 when the wx.ST_SIZEGRIP is set. self.SetFieldsCount(7) self.SetStatusStyles([wx.SB_FLAT] * 7) self.SetStatusWidths([-1, 250, 50, 19, 19, 19, 19]) self._gui_image_manager = GuiImageManager.getInstance() self.guiutility = GUIUtility.getInstance() self.utility = self.guiutility.utility self.library_manager = self.guiutility.library_manager self.ff_checkbox = wx.CheckBox(self, -1, 'Family filter', style=wx.ALIGN_RIGHT) self.ff_checkbox.Bind(wx.EVT_CHECKBOX, self.OnCheckbox) self.ff_checkbox.SetValue(self.guiutility.getFamilyFilter()) self.speed_down_icon = self._gui_image_manager.getBitmap(self, u"arrow", self.GetBackgroundColour(), state=0) self.speed_down_sbmp = wx.StaticBitmap(self, -1, self.speed_down_icon) self.speed_down_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_down = wx.StaticText(self, -1, '') self.speed_down.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_up_icon = self.speed_down_icon.ConvertToImage().Rotate90().Rotate90().ConvertToBitmap() self.speed_up_sbmp = wx.StaticBitmap(self, -1, self.speed_up_icon) self.speed_up_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.speed_up = wx.StaticText(self, -1, '') self.speed_up.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.free_space_icon = self._gui_image_manager.getImage(u"drive.png") self.free_space_sbmp = wx.StaticBitmap(self, -1, self.free_space_icon) self.free_space = wx.StaticText(self, -1, '') self.searchConnectionImages = [u"progressbarEmpty.png", u"progressbarFull.png"] self.searchConnectionImages = [self._gui_image_manager.getImage(image) for image in self.searchConnectionImages] self.activityImages = [u"statusbar_activity.png", u"statusbar_noactivity.png"] self.activityImages = [self._gui_image_manager.getImage(image) for image in self.activityImages] self.connection = HorizontalGauge(self, self.searchConnectionImages[0], self.searchConnectionImages[1]) self.activity = wx.StaticBitmap(self, -1, self.activityImages[1]) self.activity_timer = None self.channelconnections = 0 self.bmp_firewall_warning = self._gui_image_manager.getImage(u"statusbar_warning.png") self.bmp_firewall_ok = self._gui_image_manager.getImage(u"statusbar_ok.png") self.firewallStatus = ActionButton(self, -1, self.bmp_firewall_warning) self.firewallStatus.SetSize((16, 16)) self.firewallStatus.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) self.firewallStatus.SetToolTipString('Port status unknown') self.firewallStatus.Enable(False) self.firewallStatus.SetBitmapDisabled(self.bmp_firewall_warning) self.SetTransferSpeeds(0, 0) self.Bind(wx.EVT_SIZE, self.OnSize) self.library_manager.add_download_state_callback(self.RefreshTransferSpeed) @forceWxThread def RefreshFreeSpace(self, space): if space >= 0: space_str = size_format(space, truncate=1) space_label = space_str.replace(' ', '') space_tooltip = 'You currently have %s of disk space available on your default download location.' % space_str self.free_space.SetLabel(space_label) self.free_space.SetToolTipString(space_tooltip) self.free_space.Show(True) self.free_space_sbmp.SetToolTipString(space_tooltip) self.free_space_sbmp.Show(True) else: self.free_space.Show(False) self.free_space_sbmp.Show(False) self.Reposition() def RefreshTransferSpeed(self, dslist, magnetlist): if not self: return total_down, total_up = 0.0, 0.0 for ds in dslist: total_down += ds.get_current_speed(DOWNLOAD) total_up += ds.get_current_speed(UPLOAD) self.SetTransferSpeeds(total_down, total_up) @warnWxThread def SetTransferSpeeds(self, down, up): self.speed_down.SetLabel(speed_format(down)) self.speed_up.SetLabel(speed_format(up)) self.Reposition() def SetGlobalMaxSpeed(self, direction, value): if direction in [UPLOAD, DOWNLOAD]: if direction == UPLOAD: self.utility.write_config('maxuploadrate', value) self.guiutility.utility.session.set_max_upload_speed(value) else: self.utility.write_config('maxdownloadrate', value) self.guiutility.utility.session.set_max_download_speed(value) def GetSpeedChoices(self, value): values = round_range(max(0, value)) if value != 0 else range(0, 1000, 100) values = [value or -1 for value in values] if value != 0 and value not in values: values.append(value) values.sort() values.append(0) return [('unlimited' if value == 0 else ('0' if value == -1 else str(value)), value) for value in values] def OnDownloadPopup(self, event): menu = wx.Menu() current = self.utility.read_config('maxdownloadrate') value_tuples = self.GetSpeedChoices(current) for value_str, value in value_tuples: itemid = wx.NewId() menu.AppendRadioItem(itemid, value_str) menu.Bind(wx.EVT_MENU, lambda x, v=value: self.SetGlobalMaxSpeed(DOWNLOAD, v), id=itemid) menu.Check(itemid, current == value) self.speed_down.PopupMenu(menu, event.GetPosition()) menu.Destroy() self.speed_down.Layout() def OnUploadPopup(self, event): menu = wx.Menu() current = self.utility.read_config('maxuploadrate') value_tuples = self.GetSpeedChoices(current) for value_str, value in value_tuples: itemid = wx.NewId() menu.AppendRadioItem(itemid, value_str) menu.Bind(wx.EVT_MENU, lambda x, v=value: self.SetGlobalMaxSpeed(UPLOAD, v), id=itemid) menu.Check(itemid, current == value) self.speed_up.PopupMenu(menu, event.GetPosition()) menu.Destroy() self.speed_up.Layout() def OnCheckbox(self, event): checkbox = event.GetEventObject() checkbox.Enable(False) wx.CallLater(1000, checkbox.Enable, True) wx.CallLater(100, self.__toggleFF, event.GetEventObject().GetValue()) @warnWxThread def __toggleFF(self, newvalue): if newvalue != self.guiutility.getFamilyFilter(): self.guiutility.toggleFamilyFilter(newvalue) @warnWxThread def SetConnections(self, connectionPercentage, totalConnections, channelConnections): self.connection.SetPercentage(connectionPercentage) self.connection.SetToolTipString('Connected to %d peers' % totalConnections) self.channelconnections = channelConnections def GetConnections(self): return self.connection.GetPercentage() def GetChannelConnections(self): return self.channelconnections @warnWxThread def onReachable(self, event=None): if not self.guiutility.firewall_restart: self.firewallStatus.SetBitmapLabel(self.bmp_firewall_ok) self.firewallStatus.SetBitmapDisabled(self.bmp_firewall_ok) self.firewallStatus.SetToolTipString('Port is working') @warnWxThread def IsReachable(self): if not self.guiutility.firewall_restart: return self.firewallStatus.GetBitmapLabel() == self.bmp_firewall_ok return False @warnWxThread def onActivity(self, msg): if self.activity_timer: self.activity_timer.Stop() def revert(): if not self: return self.activity.SetBitmap(self.activityImages[1]) self.activity.Refresh() self.activity.SetBitmap(self.activityImages[0]) self.activity.Refresh() self.activity.SetToolTipString(msg) self.activity_timer = wx.CallLater(300, revert) def OnSize(self, event): self.Reposition() def Reposition(self): self.Freeze() rect = self.GetFieldRect(0) self.ff_checkbox.SetPosition((rect.x + 2, rect.y + 2)) self.ff_checkbox.SetSize((-1, rect.height - 4)) rect = self.GetFieldRect(1) x = rect.x + rect.width - 15 for control in reversed([self.speed_down_sbmp, self.speed_down, self.speed_up_sbmp, self.speed_up]): spacer = 10 if not isinstance(control, wx.StaticBitmap) else 7 x -= control.GetSize()[0] + spacer yAdd = (rect.height - control.GetSize()[1]) / 2 control.SetPosition((x, rect.y + yAdd)) rect = self.GetFieldRect(2) x = rect.x + rect.width for control in [self.free_space, self.free_space_sbmp]: size = control.GetSize() yAdd = (rect.height - size[1]) / 2 x -= size[0] + 5 control.SetPosition((x, rect.y + yAdd)) rect = self.GetFieldRect(3) size = self.connection.GetSize() yAdd = (rect.height - size[1]) / 2 xAdd = (rect.width - size[0]) / 2 self.connection.SetPosition((rect.x + xAdd, rect.y + yAdd)) rect = self.GetFieldRect(4) size = self.activity.GetSize() yAdd = (rect.height - size[1]) / 2 xAdd = (rect.width - size[0]) / 2 self.activity.SetPosition((rect.x + xAdd, rect.y + yAdd)) rect = self.GetFieldRect(5) size = self.firewallStatus.GetSize() yAdd = (rect.height - size[1]) / 2 xAdd = (rect.width - size[0]) / 2 self.firewallStatus.SetPosition((rect.x + xAdd, rect.y + yAdd)) self.sizeChanged = False self.Thaw()
class EmbeddedPlayerPanel(wx.Panel): """ The Embedded Player consists of a VLCWindow and the media controls such as Play/Pause buttons and Volume Control. """ VIDEO_SIZE = (320, 240) def __init__(self, parent, utility, vlcwrap, bg): wx.Panel.__init__(self, parent, -1) self.utility = utility self.guiutility = utility.guiUtility self.parent = parent self.SetBackgroundColour(DEFAULT_BACKGROUND) self.volume = 0.48 self.oldvolume = 0.48 self.estduration = None self.fullscreenwindow = None self.download = None self.update = True self.timeoffset = None vSizer = wx.BoxSizer(wx.VERTICAL) self.vlcwrap = vlcwrap if vlcwrap: self.vlcwin = VLCWindow(self, vlcwrap) self.vlcwin.SetMinSize(EmbeddedPlayerPanel.VIDEO_SIZE) vSizer.Add(self.vlcwin, 1, wx.EXPAND, 0) self.logowin = LogoWindow(self) self.logowin.SetMinSize(EmbeddedPlayerPanel.VIDEO_SIZE) vSizer.Add(self.logowin, 1, wx.EXPAND, 0) self.ctrlpanel = FancyPanel(self, border=wx.TOP) self.ctrlpanel.SetMinSize((-1, 30)) self.ctrlpanel.SetBorderColour(SEPARATOR_GREY) self.ctrlpanel.SetBackgroundColour(GRADIENT_LGREY, GRADIENT_DGREY) self.ctrlsizer = wx.BoxSizer(wx.HORIZONTAL) self.slider = VideoSlider(self.ctrlpanel) self.slider.Enable(False) self.timeposition = TransparentText(self.ctrlpanel, -1, "--:-- / --:--") self.bmp_muted = wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_muted.png")) self.bmp_unmuted = wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_unmuted.png")) self.mute = ActionButton(self.ctrlpanel, -1, self.bmp_unmuted) self.mute.Bind(wx.EVT_LEFT_UP, self.MuteClicked) self.bmp_pause = wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_pause.png")) self.bmp_play = wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_play.png")) self.ppbtn = ActionButton(self.ctrlpanel, -1, self.bmp_play) self.ppbtn.Bind(wx.EVT_LEFT_UP, self.PlayPause) self.ppbtn.Enable(False) self.sbtn = ActionButton(self.ctrlpanel, -1, wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_stop.png"))) self.sbtn.Bind(wx.EVT_LEFT_UP, self.OnStop) self.sbtn.Enable(False) self.volctrl = VideoVolume(self.ctrlpanel, -1) self.volctrl.SetVolumeHandler(self.OnVolumeChanged) self.volctrl.SetValue(self.volume) self.volctrl.SetMinSize((30, 17)) self.fsbtn = ActionButton(self.ctrlpanel, -1, wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_fullscreen.png"))) self.fsbtn.Bind(wx.EVT_LEFT_UP, self.FullScreen) self.fsbtn.Enable(False) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.ppbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.sbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.slider, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5) self.ctrlsizer.Add(self.timeposition, 0, wx.ALIGN_CENTER_VERTICAL) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.mute, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((5, -1)) self.ctrlsizer.Add(self.volctrl, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.fsbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlpanel.SetSizer(self.ctrlsizer) vSizer.Add(self.ctrlpanel, 0, wx.ALIGN_BOTTOM | wx.EXPAND) self.SetSizer(vSizer) self.playtimer = None self.timer = None if self.vlcwrap: self.SetMinSize((EmbeddedPlayerPanel.VIDEO_SIZE[0], -1)) self.vlcwin.Show(True) self.logowin.Show(False) self.ctrlsizer.ShowItems(True) self.guiutility.frame.Layout() def OnVolumeChanged(self, volume): if self.mute.GetBitmapLabel() == self.bmp_muted: # unmute self.mute.SetBitmapLabel(self.bmp_unmuted, recreate=True) self.volume = volume self.oldvolume = self.volume self.SetVolume(self.volume) def MuteClicked(self, event): if self.mute.GetBitmapLabel() == self.bmp_muted: self.volume = self.oldvolume else: self.volume = 0 self.volctrl.SetValue(self.volume) self.SetVolume(self.volume) self.mute.SetBitmapLabel(self.bmp_unmuted if self.mute.GetBitmapLabel() == self.bmp_muted else self.bmp_muted, recreate=True) @warnWxThread def Load(self, url, streaminfo=None): if DEBUG: print >> sys.stderr, "embedplay: Load:", url, streaminfo, currentThread().getName() if streaminfo is not None: self.estduration = streaminfo.get('estduration', None) self.download = VideoPlayer.getInstance().get_vod_download() # 19/02/10 Boudewijn: no self.slider when self.vlcwrap is None # 26/05/09 Boudewijn: when using the external player we do not have a vlcwrap if self.vlcwrap: self.slider.Enable(True) # Arno, 2009-02-17: If we don't do this VLC gets the wrong playlist somehow self.vlcwrap.stop() self.vlcwrap.playlist_clear() self.vlcwrap.load(url, streaminfo=streaminfo) # Enable update of progress slider wx.CallAfter(self.slider.SetValue, 0) if self.timer is None: self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.UpdateSlider) self.timer.Start(500) self.fsbtn.Enable(True) self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(True) self.sbtn.Enable(True) def StartPlay(self): """ Start playing the new item after VLC has stopped playing the old one """ if DEBUG: print >> sys.stderr, "embedplay: PlayWhenStopped" self.playtimer = DelayTimer(self) @warnWxThread def Play(self, evt=None): if DEBUG: print >> sys.stderr, "embedplay: Play pressed" # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: if self.GetState() != MEDIASTATE_PLAYING: self.HideLoading() self.vlcwrap.start() self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(True) elif DEBUG: print >> sys.stderr, "embedplay: Play pressed, already playing" @warnWxThread def Pause(self, evt=None, gui_vod_event=False): if DEBUG: print >> sys.stderr, "embedplay: Pause pressed" # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: if self.GetState() == MEDIASTATE_PLAYING: self.vlcwrap.pause() self.ppbtn.SetBitmapLabel(self.bmp_play, recreate=True) if gui_vod_event: self.ppbtn.Enable(False) self.ShowLoading() elif DEBUG: print >> sys.stderr, "embedplay: Pause pressed, not playing" @warnWxThread def Resume(self, evt=None): if DEBUG: print >> sys.stderr, "embedplay: Resume pressed" if self.vlcwrap: if self.GetState() != MEDIASTATE_PLAYING: self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(True) self.HideLoading() self.vlcwrap.resume() @warnWxThread def PlayPause(self, evt=None): if DEBUG: print >> sys.stderr, "embedplay: PlayPause pressed" # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: if self.GetState() in [MEDIASTATE_ENDED, MEDIASTATE_STOPPED]: # Ensures that the related download also starts self.guiutility.library_manager.startLastVODTorrent() else: self.vlcwrap.resume() self.ppbtn.SetBitmapLabel(self.bmp_play if self.ppbtn.GetBitmapLabel() == self.bmp_pause else self.bmp_pause, recreate=True) self.ppbtn.Enable(True) @warnWxThread def Seek(self, evt=None): if DEBUG: print >> sys.stderr, "embedplay: Seek" # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(not bool(self.download)) position = self.slider.GetValue() self.update = False try: if self.download: self.download.pause_vod() self.download.vod_seekpos = None self.ShowLoading() self.vlcwrap.set_media_position_relative(position, self.GetState() in [MEDIASTATE_ENDED, MEDIASTATE_STOPPED]) length = self.vlcwrap.get_stream_information_length() length = length / 1000 if length > 0 else (self.estduration or (self.download and self.download.get_vod_duration())) time_position = length * position self.timeoffset = time_position - (self.vlcwrap.get_media_position() / 1000) self.update = True except: print_exc() if DEBUG: print >> sys.stderr, 'embedplay: Could not seek' def FullScreen(self, evt=None): # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap and self.fsbtn.IsEnabled(): self._ToggleFullScreen() def OnFullScreenKey(self, event): if event.GetUnicodeKey() == wx.WXK_ESCAPE: self._ToggleFullScreen() elif event.GetUnicodeKey() == wx.WXK_SPACE: self._TogglePause() def _TogglePause(self): if self.GetState() == MEDIASTATE_PLAYING: self.vlcwrap.pause() else: self.vlcwrap.resume() @warnWxThread def _ToggleFullScreen(self): if isinstance(self.parent, wx.Frame): # are we shown in popup frame if self.ctrlsizer.IsShown(0): # we are not in fullscreen -> ctrlsizer is showing self.parent.ShowFullScreen(True) self.ctrlsizer.ShowItems(False) self.Layout() # Niels: 07-03-2012, only evt_close seems to work :( quitId = wx.NewId() pauseId = wx.NewId() self.parent.Bind(wx.EVT_MENU, lambda event: self._ToggleFullScreen(), id=quitId) self.parent.Bind(wx.EVT_MENU, lambda event: self._TogglePause(), id=pauseId) self.parent.Bind(wx.EVT_CLOSE, lambda event: self._ToggleFullScreen()) self.parent.Bind(wx.EVT_LEFT_DCLICK, lambda event: self._ToggleFullScreen()) accelerators = [(wx.ACCEL_NORMAL, wx.WXK_ESCAPE, quitId), (wx.ACCEL_CTRL, wx.WXK_SPACE, pauseId)] self.parent.SetAcceleratorTable(wx.AcceleratorTable(accelerators)) else: self.parent.ShowFullScreen(False) self.ctrlsizer.ShowItems(True) self.Layout() self.parent.SetAcceleratorTable(wx.NullAcceleratorTable) self.parent.Unbind(wx.EVT_CLOSE) else: # saving media player state cur_time = self.vlcwrap.get_media_position() cur_state = self.vlcwrap.get_our_state() self.vlcwrap.stop() if not self.fullscreenwindow: # create a new top level frame where to attach the vlc widget and # render the fullscreen video self.fullscreenwindow = wx.Frame(None, title="FullscreenVLC") self.fullscreenwindow.SetBackgroundColour("BLACK") eventPanel = wx.Panel(self.fullscreenwindow) eventPanel.SetBackgroundColour(wx.BLACK) eventPanel.Bind(wx.EVT_KEY_DOWN, lambda event: self.OnFullScreenKey(event)) self.fullscreenwindow.Bind(wx.EVT_CLOSE, lambda event: self._ToggleFullScreen()) self.fullscreenwindow.ShowFullScreen(True) eventPanel.SetFocus() self.vlcwrap.set_window(self.fullscreenwindow) else: self.TellLVCWrapWindow4Playback() self.fullscreenwindow.Destroy() self.fullscreenwindow = None # restoring state if cur_state == MEDIASTATE_PLAYING: self.vlcwrap.start(cur_time) elif cur_state == MEDIASTATE_PAUSED: self.vlcwrap.start(cur_time) def doPause(cur_time): self.vlcwrap.pause() self.vlcwrap.set_media_position(cur_time) wx.CallLater(500, doPause, cur_time) def Save(self, evt=None): # save media content in different directory if self.save_button.isToggled(): self.save_callback() def SetVolume(self, volume, evt=None): if DEBUG: print >> sys.stderr, "embedplay: SetVolume:", self.volume # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: self.vlcwrap.sound_set_volume(volume) def OnStop(self, event=None): if self.vlcwrap and self.sbtn.IsEnabled(): self.Stop() self.ppbtn.Enable(True) # Ensures that the related download also stops. self.guiutility.library_manager.stopLastVODTorrent() @forceWxThread def Stop(self): if DEBUG: print >> sys.stderr, "embedplay: Stop" # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: self.vlcwrap.stop() self.timeposition.SetLabel('--:-- / --:--') self.slider.SetValue(0) self.fsbtn.Enable(False) self.sbtn.Enable(False) self.ppbtn.SetBitmapLabel(self.bmp_play, recreate=True) self.slider.Enable(False) self.HideLoading() if self.timer is not None: self.timer.Stop() def GetState(self): """ Returns the state of VLC as summarized by Fabian: MEDIASTATE_PLAYING, MEDIASTATE_PAUSED, MEDIASTATE_ENDED, MEDIASTATE_STOPPED """ # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: status = self.vlcwrap.get_our_state() if DEBUG: print >> sys.stderr, "embedplay: GetState", status return status # catchall return MEDIASTATE_STOPPED def Reset(self): self.Stop() self.slider.SetPieces([]) @forceWxThread def UpdateStatus(self, progress, progress_consec, pieces_complete): self.logowin.loading.SetValue(progress) if self.vlcwrap: self.slider.SetPieces(pieces_complete) @warnWxThread def UpdateSlider(self, evt): # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap and self.update: if self.GetState() not in [MEDIASTATE_ENDED, MEDIASTATE_STOPPED]: length = self.vlcwrap.get_stream_information_length() length = length / 1000 if length > 0 else (self.estduration or (self.download and self.download.get_vod_duration())) cur = self.vlcwrap.get_media_position() / 1000 if length and self.timeoffset: cur += self.timeoffset if cur >= 0 and length: self.slider.SetValue(float(cur) / length) cur_str = self.FormatTime(float(cur)) if cur >= 0 else '--:--' length_str = self.FormatTime(length) if length else '--:--' self.timeposition.SetLabel('%s / %s' % (cur_str, length_str)) self.ctrlsizer.Layout() elif self.GetState() == MEDIASTATE_ENDED: self.OnStop(None) def FormatTime(self, s): longformat = time.strftime('%d:%H:%M:%S', time.gmtime(s)) if longformat.startswith('01:'): longformat = longformat[3:] while longformat.startswith('00:') and len(longformat) > len('00:00'): longformat = longformat[3:] return longformat def TellLVCWrapWindow4Playback(self): if self.vlcwrap: self.vlcwin.tell_vclwrap_window_for_playback() def ShowLoading(self): if self.vlcwrap: self.logowin.loading.SetValue(0.0) self.logowin.show_loading() self.logowin.Show(True) self.vlcwin.Show(False) self.Layout() def HideLoading(self): if self.vlcwrap: self.logowin.hide_loading() self.logowin.Show(False) self.vlcwin.Show(True) self.Layout()
class EmbeddedPlayerPanel(wx.Panel): """ The Embedded Player consists of a VLCWindow and the media controls such as Play/Pause buttons and Volume Control. """ VIDEO_SIZE = (320, 240) def __init__(self, parent, utility, vlcwrap, bg_color): wx.Panel.__init__(self, parent, -1) self._logger = logging.getLogger(self.__class__.__name__) self._gui_image_manager = GuiImageManager.getInstance() self.utility = utility self.guiutility = utility.guiUtility self.videoplayer = self.guiutility.videoplayer self.parent = parent self.SetBackgroundColour(bg_color) self.fullscreenwindow = None self.download = None self.download_hash = None self.update = True self.timeoffset = None self.oldvolume = 0 vSizer = wx.BoxSizer(wx.VERTICAL) self.vlcwrap = vlcwrap if vlcwrap: self.vlcwin = VLCWindow(self, vlcwrap) self.vlcwin.SetMinSize(EmbeddedPlayerPanel.VIDEO_SIZE) vSizer.Add(self.vlcwin, 1, wx.EXPAND, 0) self.logowin = LogoWindow(self) self.logowin.SetMinSize(EmbeddedPlayerPanel.VIDEO_SIZE) vSizer.Add(self.logowin, 1, wx.EXPAND, 0) self.ctrlpanel = FancyPanel(self, border=wx.TOP) self.ctrlpanel.SetMinSize((-1, 30)) self.ctrlpanel.SetBorderColour(SEPARATOR_GREY) self.ctrlpanel.SetBackgroundColour(GRADIENT_LGREY, GRADIENT_DGREY) self.ctrlsizer = wx.BoxSizer(wx.HORIZONTAL) self.slider = VideoSlider(self.ctrlpanel) self.slider.Enable(False) self.timeposition = TransparentText(self.ctrlpanel, -1, "--:-- / --:--") self.bmp_muted = self._gui_image_manager.getImage( u"video_muted.png") self.bmp_unmuted = self._gui_image_manager.getImage( u"video_unmuted.png") self.mute = ActionButton(self.ctrlpanel, -1, self.bmp_unmuted) self.mute.Bind(wx.EVT_LEFT_UP, self.MuteClicked) self.bmp_pause = self._gui_image_manager.getImage( u"video_pause.png") self.bmp_play = self._gui_image_manager.getImage(u"video_play.png") self.ppbtn = ActionButton(self.ctrlpanel, -1, self.bmp_play) self.ppbtn.Bind(wx.EVT_LEFT_UP, self.PlayPause) self.ppbtn.Enable(False) self.sbtn = ActionButton( self.ctrlpanel, -1, self._gui_image_manager.getImage(u"video_stop.png")) self.sbtn.Bind(wx.EVT_LEFT_UP, self.OnStop) self.sbtn.Enable(False) self.volctrl = VideoVolume(self.ctrlpanel, -1) self.volctrl.SetVolumeHandler(self.OnVolumeChanged) self.volctrl.SetMinSize((30, 17)) self.volctrl.Enable(False) self.fsbtn = ActionButton( self.ctrlpanel, -1, self._gui_image_manager.getImage(u"video_fullscreen.png")) self.fsbtn.Bind(wx.EVT_LEFT_UP, self.FullScreen) self.fsbtn.Enable(False) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.ppbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.sbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.slider, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5) self.ctrlsizer.Add(self.timeposition, 0, wx.ALIGN_CENTER_VERTICAL) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.mute, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((5, -1)) self.ctrlsizer.Add(self.volctrl, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.fsbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlpanel.SetSizer(self.ctrlsizer) vSizer.Add(self.ctrlpanel, 0, wx.ALIGN_BOTTOM | wx.EXPAND) self.notifier = self.guiutility.utility.session.notifier self.SetSizer(vSizer) self.playtimer = None self.timer = None if self.vlcwrap: self.SetMinSize((EmbeddedPlayerPanel.VIDEO_SIZE[0], -1)) self.vlcwin.Show(True) self.logowin.Show(False) self.ctrlsizer.ShowItems(True) self.guiutility.frame.Layout() self.guiutility.library_manager.add_download_state_callback( self.OnStatesCallback) self.guiutility.utility.session.add_observer( self.OnVideoBuffering, NTFY_TORRENTS, [NTFY_VIDEO_BUFFERING]) self.videoplayer.set_internalplayer_callback(self.LoadAndStartPlay) def OnVideoBuffering(self, subject, changeType, torrent_tuple): if not self: return download_hash, _, is_buffering = torrent_tuple if self.download and self.download.get_def().get_infohash( ) == download_hash: @forceWxThread def do_gui(): if is_buffering: self.Pause(gui_vod_event=True) else: self.Resume() do_gui() def OnStatesCallback(self, dslist, magnetlist): if not self or not self.download: return for ds in dslist: if ds.get_download() == self.download and self.download.get_mode( ) == DLMODE_VOD: if ds.get_status() == DLSTATUS_HASHCHECKING: progress = ds.get_progress() label = 'Checking\n%d%%' % (progress * 100) elif ds.get_status() == DLSTATUS_STOPPED_ON_ERROR: progress = 0 label = 'Loading\nfailed' else: progress = ds.get_vod_prebuffering_progress() label = 'Loading\n%d%%' % (progress * 100) pieces_complete = ds.get_pieces_complete( ) if ds.get_progress() < 1.0 else [True] self.UpdateStatus(label, progress, pieces_complete) def OnVolumeChanged(self, volume): if self.mute.GetBitmapLabel() == self.bmp_muted: # unmute self.mute.SetBitmapLabel(self.bmp_unmuted, recreate=True) self.volume = volume self.oldvolume = self.volume self.SetVolume(self.volume) def MuteClicked(self, event): if self.mute.GetBitmapLabel() == self.bmp_muted: self.volume = self.oldvolume else: self.volume = 0 self.volctrl.SetValue(self.volume) self.SetVolume(self.volume) self.mute.SetBitmapLabel( self.bmp_unmuted if self.mute.GetBitmapLabel() == self.bmp_muted else self.bmp_muted, recreate=True) @forceWxThread def LoadAndStartPlay(self, url, download): self.Load(url, download) self.StartPlay() @warnWxThread def Load(self, url, download): self._logger.debug("embedplay: Load: %s %s", url, currentThread().getName()) self.download = download self.download_hash = download.get_def().get_infohash() # 19/02/10 Boudewijn: no self.slider when self.vlcwrap is None # 26/05/09 Boudewijn: when using the external player we do not have a vlcwrap if self.vlcwrap: self.slider.Enable(False) # Arno, 2009-02-17: If we don't do this VLC gets the wrong playlist somehow self.vlcwrap.stop() self.vlcwrap.load(url) # Enable update of progress slider wx.CallAfter(self.slider.SetValue, 0) if self.timer is None: self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.UpdateSlider) self.timer.Start(500) self.volume = self.vlcwrap.sound_get_volume() self.oldvolume = self.vlcwrap.sound_get_volume() self.volctrl.SetValue(self.volume) self.volctrl.Enable(True) self.fsbtn.Enable(True) self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(True) self.sbtn.Enable(True) def StartPlay(self): """ Start playing the new item after VLC has stopped playing the old one """ self._logger.debug("embedplay: PlayWhenStopped") self.playtimer = DelayTimer(self) @warnWxThread def Play(self, evt=None): self._logger.debug("embedplay: Play pressed") # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: if self.GetState() != MEDIASTATE_PLAYING: self.vlcwrap.start() self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(True) else: self._logger.debug("embedplay: Play pressed, already playing") @warnWxThread def Pause(self, evt=None, gui_vod_event=False): self._logger.debug("embedplay: Pause pressed") if self.vlcwrap: if self.GetState() == MEDIASTATE_PLAYING: self.vlcwrap.pause() self.ppbtn.SetBitmapLabel(self.bmp_play, recreate=True) if gui_vod_event: self.ppbtn.Enable(False) self.ShowLoading() @warnWxThread def Resume(self, evt=None): self._logger.debug("embedplay: Resume pressed") if self.vlcwrap: if self.GetState() != MEDIASTATE_PLAYING: self.vlcwrap.resume() self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(True) self.slider.Enable(True) self.HideLoading() @warnWxThread def PlayPause(self, evt=None): self._logger.debug("embedplay: PlayPause pressed") # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: if self.GetState() in [MEDIASTATE_ENDED, MEDIASTATE_STOPPED]: # Ensures that the related download also starts self.guiutility.library_manager.startLastVODTorrent() else: self.vlcwrap.resume() self.ppbtn.SetBitmapLabel( self.bmp_play if self.ppbtn.GetBitmapLabel() == self.bmp_pause else self.bmp_pause, recreate=True) self.ppbtn.Enable(True) @warnWxThread def Seek(self, evt=None): self._logger.debug("embedplay: Seek") # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(self.download.get_progress() == 1.0) position = self.slider.GetValue() self.update = False try: self.Pause(gui_vod_event=True) self.videoplayer.seek(position) self.vlcwrap.set_media_position_relative( position, self.GetState() in [MEDIASTATE_ENDED, MEDIASTATE_STOPPED]) length = self.vlcwrap.get_stream_information_length() length = length / 1000 if length > 0 else self.videoplayer.get_vod_duration( self.download_hash) time_position = length * position self.timeoffset = time_position - ( self.vlcwrap.get_media_position() / 1000) self.update = True except: print_exc() self._logger.debug('embedplay: Could not seek') def FullScreen(self, evt=None): # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap and self.fsbtn.IsEnabled(): self._ToggleFullScreen() def OnFullScreenKey(self, event): if event.GetUnicodeKey() == wx.WXK_ESCAPE: self._ToggleFullScreen() elif event.GetUnicodeKey() == wx.WXK_SPACE: self._TogglePause() def _TogglePause(self): if self.GetState() == MEDIASTATE_PLAYING: self.vlcwrap.pause() else: self.vlcwrap.resume() @warnWxThread def _ToggleFullScreen(self): # saving media player state cur_time = self.vlcwrap.get_media_position() cur_state = self.vlcwrap.get_our_state() self.vlcwrap.stop() if not self.fullscreenwindow: # create a new top level frame where to attach the vlc widget and # render the fullscreen video self.fullscreenwindow = wx.Frame(None, title="FullscreenVLC") self.fullscreenwindow.SetBackgroundColour("BLACK") eventPanel = wx.Panel(self.fullscreenwindow) eventPanel.SetBackgroundColour(wx.BLACK) eventPanel.Bind(wx.EVT_KEY_DOWN, lambda event: self.OnFullScreenKey(event)) self.fullscreenwindow.Bind(wx.EVT_CLOSE, lambda event: self._ToggleFullScreen()) self.fullscreenwindow.Show() self.fullscreenwindow.ShowFullScreen(True) eventPanel.SetFocus() self.vlcwrap.set_window(self.fullscreenwindow) else: self.vlcwrap.set_window(self.vlcwin) self.fullscreenwindow.Destroy() self.fullscreenwindow = None # restoring state if cur_state == MEDIASTATE_PLAYING: self.vlcwrap.start(cur_time) elif cur_state == MEDIASTATE_PAUSED: self.vlcwrap.start(cur_time) def doPause(cur_time): self.vlcwrap.pause() self.vlcwrap.set_media_position(cur_time) wx.CallLater(500, doPause, cur_time) def SetVolume(self, volume, evt=None): self._logger.debug("embedplay: SetVolume: %s", self.volume) # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: self.vlcwrap.sound_set_volume(volume) def OnStop(self, event=None): if self.vlcwrap and self.sbtn.IsEnabled(): self.Stop() self.ppbtn.Enable(True) # Ensures that the related download also stops. self.guiutility.library_manager.stopLastVODTorrent() @forceWxThread def Stop(self): self._logger.debug("embedplay: Stop") # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: self.vlcwrap.stop() self.timeposition.SetLabel('--:-- / --:--') self.slider.SetValue(0) self.timeoffset = None self.fsbtn.Enable(False) self.sbtn.Enable(False) self.ppbtn.SetBitmapLabel(self.bmp_play, recreate=True) self.slider.Enable(False) self.HideLoading() if self.timer is not None: self.timer.Stop() def GetState(self): """ Returns the state of VLC as summarized by Fabian: MEDIASTATE_PLAYING, MEDIASTATE_PAUSED, MEDIASTATE_ENDED, MEDIASTATE_STOPPED """ # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: status = self.vlcwrap.get_our_state() self._logger.debug("embedplay: GetState %s", status) return status # catchall return MEDIASTATE_STOPPED def Reset(self): self.Stop() self.slider.SetPieces([]) @forceWxThread def UpdateStatus(self, label, progress, pieces_complete): self.logowin.loading.SetValue(progress) self.logowin.loading.SetLabel(label) if self.vlcwrap: self.slider.SetPieces(pieces_complete) @warnWxThread def UpdateSlider(self, evt): # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap and self.update: if self.GetState() not in [MEDIASTATE_ENDED, MEDIASTATE_STOPPED]: length = self.vlcwrap.get_stream_information_length() length = length / 1000 if length > 0 else self.videoplayer.get_vod_duration( self.download_hash) cur = self.vlcwrap.get_media_position() / 1000 if length and self.timeoffset: cur += self.timeoffset if cur >= 0 and length: self.slider.SetValue(float(cur) / length) cur_str = self.FormatTime(float(cur)) if cur >= 0 else '--:--' length_str = self.FormatTime(length) if length else '--:--' self.timeposition.SetLabel('%s / %s' % (cur_str, length_str)) self.ctrlsizer.Layout() elif self.GetState() == MEDIASTATE_ENDED: download, fileindex = (self.videoplayer.get_vod_download(), self.videoplayer.get_vod_fileindex()) self.OnStop(None) if download: self.notifier.notify( NTFY_TORRENTS, NTFY_VIDEO_ENDED, (download.get_def().get_infohash(), fileindex)) if self.fullscreenwindow: self._ToggleFullScreen() def FormatTime(self, s): longformat = time.strftime('%d:%H:%M:%S', time.gmtime(s)) if longformat.startswith('01:'): longformat = longformat[3:] while longformat.startswith('00:') and len(longformat) > len('00:00'): longformat = longformat[3:] return longformat def ShowLoading(self): if self.vlcwrap: self.logowin.loading.SetValue(0.0) self.logowin.show_loading() self.logowin.Show(True) self.vlcwin.Show(False) self.Layout() def HideLoading(self): if self.vlcwrap: self.logowin.hide_loading() self.logowin.Show(False) self.vlcwin.Show(True) self.Layout() def RecreateVLCWindow(self): if self.vlcwrap: vlcwin = VLCWindow(self, self.vlcwrap) vlcwin.SetMinSize(EmbeddedPlayerPanel.VIDEO_SIZE) vlcwin.Show(self.vlcwin.IsShown()) self.GetSizer().Replace(self.vlcwin, vlcwin) self.vlcwin.Destroy() self.vlcwin = vlcwin
class SRstatusbar(wx.StatusBar): def __init__(self, parent): wx.StatusBar.__init__(self, parent, style=wx.ST_SIZEGRIP) # On Linux/OS X the resize handle and icons overlap, therefore we add an extra field. # On Windows this field is automatically set to 1 when the wx.ST_SIZEGRIP is set. self.SetFieldsCount(6) self.SetStatusStyles([wx.SB_FLAT] * 6) self.SetStatusWidths([-1, 250, 19, 19, 19, 19]) self.guiutility = GUIUtility.getInstance() self.utility = self.guiutility.utility self.library_manager = self.guiutility.library_manager self.uelog = UserEventLogDBHandler.getInstance() self.ff_checkbox = wx.CheckBox(self, -1, 'Family filter', style=wx.ALIGN_RIGHT) self.ff_checkbox.Bind(wx.EVT_CHECKBOX, self.OnCheckbox) self.ff_checkbox.SetValue(self.guiutility.getFamilyFilter()) self.speed_down_icon = NativeIcon.getInstance().getBitmap( self, 'arrow', self.GetBackgroundColour(), state=0) self.speed_down_sbmp = wx.StaticBitmap(self, -1, self.speed_down_icon) self.speed_down_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_down = StaticText(self, -1, '', style=wx.ST_NO_AUTORESIZE) self.speed_down.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_up_icon = self.speed_down_icon.ConvertToImage().Rotate90( ).Rotate90().ConvertToBitmap() self.speed_up_sbmp = wx.StaticBitmap(self, -1, self.speed_up_icon) self.speed_up_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.speed_up = StaticText(self, -1, '', style=wx.ST_NO_AUTORESIZE) self.speed_up.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.searchConnectionImages = [ 'progressbarEmpty.png', 'progressbarFull.png' ] self.searchConnectionImages = [ os.path.join(self.guiutility.vwxGUI_path, 'images', image) for image in self.searchConnectionImages ] self.searchConnectionImages = [ wx.Bitmap(image, wx.BITMAP_TYPE_ANY) for image in self.searchConnectionImages ] self.activityImages = [ 'statusbar_activity.png', 'statusbar_noactivity.png' ] self.activityImages = [ os.path.join(self.guiutility.vwxGUI_path, 'images', image) for image in self.activityImages ] self.activityImages = [ wx.Bitmap(image, wx.BITMAP_TYPE_ANY) for image in self.activityImages ] self.connection = HorizontalGauge(self, self.searchConnectionImages[0], self.searchConnectionImages[1]) self.activity = wx.StaticBitmap(self, -1, self.activityImages[1]) self.activity_timer = None self.channelconnections = 0 self.bmp_firewall_warning = wx.Bitmap( os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "statusbar_warning.png")) self.bmp_firewall_ok = wx.Bitmap( os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "statusbar_ok.png")) self.firewallStatus = ActionButton(self, -1, self.bmp_firewall_warning) self.firewallStatus.SetSize((16, 16)) self.firewallStatus.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) self.firewallStatus.SetToolTipString('Port status unknown') self.firewallStatus.Enable(False) self.firewallStatus.SetBitmapDisabled(self.bmp_firewall_warning) self.SetTransferSpeeds(0, 0) self.Bind(wx.EVT_SIZE, self.OnSize) self.library_manager.add_download_state_callback( self.RefreshTransferSpeed) def RefreshTransferSpeed(self, dslist, magnetlist): total_down, total_up = 0.0, 0.0 for ds in dslist: total_down += ds.get_current_speed(DOWNLOAD) total_up += ds.get_current_speed(UPLOAD) self.SetTransferSpeeds(total_down * 1024, total_up * 1024) def SetTransferSpeeds(self, down, up): self.speed_down.SetLabel(self.utility.speed_format_new(down)) self.speed_up.SetLabel(self.utility.speed_format_new(up)) self.Reposition() def SetGlobalMaxSpeed(self, direction, value): if direction in [UPLOAD, DOWNLOAD]: if direction == UPLOAD: self.utility.setMaxUp(value) else: self.utility.setMaxDown(value) value = 0 if value == 'unlimited' else ( -1 if int(value) == 0 else int(value)) self.guiutility.app.ratelimiter.set_global_max_speed( direction, value) def OnDownloadPopup(self, event): menu = wx.Menu() curr_valdown = self.utility.getMaxDown() # values = ['75', '300', '600'] values = self.utility.round_range( int(curr_valdown)) if curr_valdown.isdigit() else range( 0, 1000, 100) values = map(str, values) if curr_valdown.isdigit() and curr_valdown not in values: values.append(curr_valdown) values.sort(cmp=lambda x, y: cmp(int(x), int(y))) values.append('unlimited') for valdown in values: itemid = wx.NewId() menu.AppendRadioItem(itemid, str(valdown)) menu.Bind(wx.EVT_MENU, lambda x, valdown=valdown: self.SetGlobalMaxSpeed( DOWNLOAD, valdown), id=itemid) menu.Check(itemid, curr_valdown == str(valdown)) self.speed_down.PopupMenu(menu, event.GetPosition()) menu.Destroy() self.speed_down.Layout() def OnUploadPopup(self, event): menu = wx.Menu() curr_valup = self.utility.getMaxUp() # values = ['0', '50', '100'] values = self.utility.round_range( int(curr_valup)) if curr_valup.isdigit() else range(0, 1000, 100) values = map(str, values) if curr_valup.isdigit() and curr_valup not in values: values.append(curr_valup) values.sort(cmp=lambda x, y: cmp(int(x), int(y))) values.append('unlimited') for valup in values: itemid = wx.NewId() menu.AppendRadioItem(itemid, str(valup)) menu.Bind( wx.EVT_MENU, lambda x, valup=valup: self.SetGlobalMaxSpeed(UPLOAD, valup), id=itemid) menu.Check(itemid, curr_valup == str(valup)) self.speed_up.PopupMenu(menu, event.GetPosition()) menu.Destroy() self.speed_up.Layout() def OnCheckbox(self, event): checkbox = event.GetEventObject() checkbox.Enable(False) wx.CallLater(1000, checkbox.Enable, True) wx.CallLater(100, self.__toggleFF, event.GetEventObject().GetValue()) def __toggleFF(self, newvalue): if newvalue != self.guiutility.getFamilyFilter(): self.guiutility.toggleFamilyFilter(newvalue) def db_callback(): self.uelog.addEvent( message="SRstatusbar: user toggled family filter", type=2) startWorker(None, db_callback, retryOnBusy=True) def SetConnections(self, connectionPercentage, totalConnections, channelConnections): self.connection.SetPercentage(connectionPercentage) self.connection.SetToolTipString('Connected to %d peers' % totalConnections) self.channelconnections = channelConnections def GetConnections(self): return self.connection.GetPercentage() def GetChannelConnections(self): return self.channelconnections def onReachable(self, event=None): if not self.guiutility.firewall_restart: self.firewallStatus.SetBitmapLabel(self.bmp_firewall_ok) self.firewallStatus.SetBitmapDisabled(self.bmp_firewall_ok) self.firewallStatus.SetToolTipString('Port is working') def IsReachable(self): if not self.guiutility.firewall_restart: return self.firewallStatus.GetBitmapLabel() == self.bmp_firewall_ok return False def onActivity(self, msg): if self.activity_timer: self.activity_timer.Stop() def revert(): self.activity.SetBitmap(self.activityImages[1]) self.activity.Refresh() self.activity.SetBitmap(self.activityImages[0]) self.activity.Refresh() self.activity.SetToolTipString(msg) self.activity_timer = wx.CallLater(300, revert) def format_bytes(self, bytes): if bytes < 1000: return '%d B' % bytes if bytes < 1024: return '%1.1f KB' % (bytes / 1024.0) if bytes < 1022796: return '%d KB' % (bytes // 1024) if bytes < 1048576: return '%1.1f MB' % (bytes // 1048576.0) if bytes < 1047527425: return '%d MB' % (bytes // 1048576) if bytes < 1073741824: return '%1.1f GB' % (bytes // 1073741824.0) return '%d GB' % (bytes // 1073741824) def OnSize(self, event): self.Reposition() def Reposition(self): self.Freeze() rect = self.GetFieldRect(0) self.ff_checkbox.SetPosition((rect.x + 2, rect.y + 2)) self.ff_checkbox.SetSize((-1, rect.height - 4)) rect = self.GetFieldRect(1) x = rect.x + rect.width - 15 for control in reversed([ self.speed_down_sbmp, self.speed_down, self.speed_up_sbmp, self.speed_up ]): spacer = 10 if not isinstance(control, wx.StaticBitmap) else 7 x -= control.GetSize()[0] + spacer yAdd = (rect.height - control.GetSize()[1]) / 2 control.SetPosition((x, rect.y + yAdd)) rect = self.GetFieldRect(2) size = self.connection.GetSize() yAdd = (rect.height - size[1]) / 2 xAdd = (rect.width - size[0]) / 2 self.connection.SetPosition((rect.x + xAdd, rect.y + yAdd)) rect = self.GetFieldRect(3) size = self.activity.GetSize() yAdd = (rect.height - size[1]) / 2 xAdd = (rect.width - size[0]) / 2 self.activity.SetPosition((rect.x + xAdd, rect.y + yAdd)) rect = self.GetFieldRect(4) size = self.firewallStatus.GetSize() yAdd = (rect.height - size[1]) / 2 xAdd = (rect.width - size[0]) / 2 self.firewallStatus.SetPosition((rect.x + xAdd, rect.y + yAdd)) self.sizeChanged = False self.Thaw()
class SRstatusbar(wx.StatusBar): def __init__(self, parent): wx.StatusBar.__init__(self, parent, style=wx.ST_SIZEGRIP) self._gui_image_manager = GuiImageManager.getInstance() self.guiutility = GUIUtility.getInstance() self.utility = self.guiutility.utility self.library_manager = self.guiutility.library_manager self.ff_checkbox = wx.CheckBox(self, -1, 'Family filter', style=wx.ALIGN_RIGHT) self.ff_checkbox.Bind(wx.EVT_CHECKBOX, self.OnCheckbox) self.ff_checkbox.SetValue(self.guiutility.getFamilyFilter()) self.tunnel_contrib = wx.StaticText(self, -1, '') self.tunnel_contrib.SetToolTipString('Total Anonymity Contribution') self.tunnel_contribNet = wx.StaticText(self, -1, '') self.tunnel_contribNet.SetToolTipString( 'Anonymity Contribution Balance') self.speed_down_icon = self._gui_image_manager.getBitmap( self, u"arrow", self.GetBackgroundColour(), state=0) self.speed_down_sbmp = wx.StaticBitmap(self, -1, self.speed_down_icon) self.speed_down_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_down = wx.StaticText(self, -1, '') self.speed_down.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_up_icon = self.speed_down_icon.ConvertToImage().Rotate90( ).Rotate90().ConvertToBitmap() self.speed_up_sbmp = wx.StaticBitmap(self, -1, self.speed_up_icon) self.speed_up_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.speed_up = wx.StaticText(self, -1, '') self.speed_up.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.free_space_icon = self._gui_image_manager.getImage(u"drive.png") self.free_space_sbmp = wx.StaticBitmap(self, -1, self.free_space_icon) self.free_space = wx.StaticText(self, -1, '') self.searchConnectionImages = [ u"progressbarEmpty.png", u"progressbarFull.png" ] self.searchConnectionImages = [ self._gui_image_manager.getImage(image) for image in self.searchConnectionImages ] self.activityImages = [ u"statusbar_activity.png", u"statusbar_noactivity.png" ] self.activityImages = [ self._gui_image_manager.getImage(image) for image in self.activityImages ] self.connection = HorizontalGauge(self, self.searchConnectionImages[0], self.searchConnectionImages[1]) self.connection.SetBackgroundColour(self.GetBackgroundColour()) self.activity = wx.StaticBitmap(self, -1, self.activityImages[1]) self.activity_timer = None self.channelconnections = 0 self.bmp_firewall_warning = self._gui_image_manager.getImage( u"statusbar_warning.png") self.bmp_firewall_ok = self._gui_image_manager.getImage( u"statusbar_ok.png") self.firewallStatus = ActionButton(self, -1, self.bmp_firewall_warning) self.firewallStatus.SetSize((16, 16)) self.firewallStatus.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) self.firewallStatus.SetToolTipString('Port status unknown') self.firewallStatus.Enable(False) self.firewallStatus.SetBitmapDisabled(self.bmp_firewall_warning) # On Linux/OS X the resize handle and icons overlap, therefore we add an extra field. # On Windows this field is automatically set to 1 when the wx.ST_SIZEGRIP (parent class constructor) is set. self.fields = [ (-1, wx.SB_FLAT, [self.ff_checkbox]), (100, wx.SB_FLAT, [self.tunnel_contrib, self.tunnel_contribNet]), (200, wx.SB_FLAT, [ self.speed_down_sbmp, self.speed_down, self.speed_up_sbmp, self.speed_up ]), (75, wx.SB_FLAT, [self.free_space_sbmp, self.free_space]), (19, wx.SB_FLAT, [self.connection]), (19, wx.SB_FLAT, [self.activity]), (19, wx.SB_FLAT, [self.firewallStatus]) ] if sys.platform != "win32": self.fields.append((19, wx.SB_FLAT, [])) self.SetFieldsCount(len(self.fields)) self.SetStatusWidths([field[0] for field in self.fields]) self.SetStatusStyles([field[1] for field in self.fields]) self.SetTransferSpeeds(speed_format(0), speed_format(0)) self.Bind(wx.EVT_SIZE, self.OnSize) self.library_manager.add_download_state_callback( self.RefreshTransferSpeed) def UpdateTunnelContrib(self): totalup = ( sum(_barter_statistics.bartercast[ BartercastStatisticTypes.TUNNELS_BYTES_SENT].values()) + sum(_barter_statistics.bartercast[ BartercastStatisticTypes.TUNNELS_RELAY_BYTES_SENT].values()) + sum(_barter_statistics.bartercast[ BartercastStatisticTypes.TUNNELS_EXIT_BYTES_SENT].values())) totaldown = ( sum(_barter_statistics.bartercast[ BartercastStatisticTypes.TUNNELS_BYTES_RECEIVED].values()) + sum(_barter_statistics.bartercast[ BartercastStatisticTypes.TUNNELS_RELAY_BYTES_RECEIVED].values( )) + sum(_barter_statistics.bartercast[ BartercastStatisticTypes.TUNNELS_EXIT_BYTES_RECEIVED].values()) ) self.SetTunnelContrib(totalup + totaldown, totalup - totaldown) @warnWxThread def SetTunnelContrib(self, totalcontrib, netcontrib): self.tunnel_contrib.SetLabel('Total: %s' % size_format(totalcontrib, truncate=2)) self.tunnel_contribNet.SetLabel('Balance: %s' % size_format(netcontrib, truncate=2)) self.Reposition() @forceWxThread def RefreshFreeSpace(self, space): if space >= 0: space_str = size_format(space, truncate=1) space_label = space_str.replace(' ', '') space_tooltip = 'You currently have %s of disk space available on your default download location.' % space_str self.free_space.SetLabel(space_label) self.free_space.Show(True) self.free_space_sbmp.Show(True) # TODO martijn: we disabled some tooltips that are periodically updated on OS X. # There seems to be a bug (in wx3) where the tooltip would always show when being updated. if sys.platform != 'darwin': self.free_space_sbmp.SetToolTipString(space_tooltip) self.free_space.SetToolTipString(space_tooltip) else: self.free_space.Show(False) self.free_space_sbmp.Show(False) self.Reposition() def RefreshTransferSpeed(self, dslist, magnetlist): if not self: return self.UpdateTunnelContrib() total_down, total_up = get_download_upload_speed(dslist) self.SetTransferSpeeds(speed_format(total_down), speed_format(total_up)) @warnWxThread def SetTransferSpeeds(self, down, up): self.speed_down.SetLabel(down) self.speed_up.SetLabel(up) self.Reposition() def SetGlobalMaxSpeed(self, direction, value): if direction in [UPLOAD, DOWNLOAD]: if direction == UPLOAD: self.utility.write_config('maxuploadrate', value) self.guiutility.utility.session.set_max_upload_speed(value) else: self.utility.write_config('maxdownloadrate', value) self.guiutility.utility.session.set_max_download_speed(value) def GetSpeedChoices(self, value): values = round_range(max(0, value)) if value != 0 else range( 0, 1000, 100) values = [value or -1 for value in values] if value != 0 and value not in values: values.append(value) values.sort() values.append(0) return [('unlimited' if value == 0 else ('0' if value == -1 else str(value)), value) for value in values] def OnDownloadPopup(self, event): menu = wx.Menu() current = self.utility.read_config('maxdownloadrate') value_tuples = self.GetSpeedChoices(current) for value_str, value in value_tuples: itemid = wx.NewId() menu.AppendRadioItem(itemid, value_str) menu.Bind(wx.EVT_MENU, lambda x, v=value: self.SetGlobalMaxSpeed(DOWNLOAD, v), id=itemid) menu.Check(itemid, current == value) self.speed_down.PopupMenu(menu, event.GetPosition()) menu.Destroy() self.speed_down.Layout() def OnUploadPopup(self, event): menu = wx.Menu() current = self.utility.read_config('maxuploadrate') value_tuples = self.GetSpeedChoices(current) for value_str, value in value_tuples: itemid = wx.NewId() menu.AppendRadioItem(itemid, value_str) menu.Bind(wx.EVT_MENU, lambda x, v=value: self.SetGlobalMaxSpeed(UPLOAD, v), id=itemid) menu.Check(itemid, current == value) self.speed_up.PopupMenu(menu, event.GetPosition()) menu.Destroy() self.speed_up.Layout() def OnCheckbox(self, event): checkbox = event.GetEventObject() checkbox.Enable(False) wx.CallLater(1000, checkbox.Enable, True) wx.CallLater(100, self.__toggleFF, event.GetEventObject().GetValue()) @warnWxThread def __toggleFF(self, newvalue): if newvalue != self.guiutility.getFamilyFilter(): self.guiutility.toggleFamilyFilter(newvalue) @warnWxThread def SetConnections(self, connectionPercentage, totalConnections, channelConnections): self.connection.SetPercentage(connectionPercentage) if sys.platform != 'darwin': self.connection.SetToolTipString('Connected to %d peers' % totalConnections) self.channelconnections = channelConnections def GetConnections(self): return self.connection.GetPercentage() def GetChannelConnections(self): return self.channelconnections @warnWxThread def onReachable(self, event=None): if not self.guiutility.firewall_restart: self.firewallStatus.SetBitmapLabel(self.bmp_firewall_ok) self.firewallStatus.SetBitmapDisabled(self.bmp_firewall_ok) self.firewallStatus.SetToolTipString('Port is working') @warnWxThread def IsReachable(self): if not self.guiutility.firewall_restart: return self.firewallStatus.GetBitmapLabel() == self.bmp_firewall_ok return False @warnWxThread def onActivity(self, msg): if self.activity_timer: self.activity_timer.Stop() def revert(): if not self: return self.activity.SetBitmap(self.activityImages[1]) self.activity.Refresh() self.activity.SetBitmap(self.activityImages[0]) self.activity.Refresh() if sys.platform != 'darwin': self.activity.SetToolTipString(msg) self.activity_timer = wx.CallLater(300, revert) def OnSize(self, event): self.Reposition() def Reposition(self): self.Freeze() # default spacing rules # - field has 1 control, center it # - field has -1 width (fill), skip it # - starting from the right align all controls with 10 spacing between them, or 7 if it it a bitmap for field_index, field in enumerate(self.fields): if field[0] == -1: continue rect = self.GetFieldRect(field_index) if len(field[2]) == 1: control = field[2][0] control.SetPosition( (rect.x + (rect.width - control.GetSize()[0]) / 2, rect.y + (rect.height - control.GetSize()[1]) / 2)) else: x = rect.x + rect.width for control in reversed(field[2]): spacer = 10 if not isinstance(control, wx.StaticBitmap) else 7 x -= control.GetSize()[0] + spacer control.SetPosition( (x, rect.y + (rect.height - control.GetSize()[1]) / 2)) # any other layout work not covered by the default rules should happen here. rect = self.GetFieldRect(0) self.ff_checkbox.SetPosition((rect.x + 2, rect.y + 2)) self.ff_checkbox.SetSize((-1, rect.height - 4)) self.sizeChanged = False self.Thaw()