def _update_video_row(self): """Determines the most recent row number, relative to video time. :returns: True if the row has changed, False otherwise. """ if (self._last_video_time is None): # Clear the video row. if (self._last_video_row is not None): self._last_video_row = None return True else: return False result = None start_row = 0 if (self._last_video_row is not None): # Take a shortcut: Scan from where we used to be. if (common.delta_seconds(self._snarks[self._last_video_row]["time"]) < self._last_video_time): start_row = self._last_video_row for i in range(start_row, len(self._snarks)-1): snark = self._snarks[i] if (common.delta_seconds(snark["time"]) <= self._last_video_time): next_snark = self._snarks[i+1] if (common.delta_seconds(next_snark["time"]) > self._last_video_time): result = i break if (result != self._last_video_row): self._last_video_row = result return True else: return False
def set_video_time(self, milliseconds): """Notifies this widget that the video time has changed. All snarks within the config's show_time will be shown, excluding any that are ignored. """ seconds = milliseconds // 1000 if (self._last_video_time is None or seconds != self._last_video_time): self._last_video_time = seconds if (self._update_video_row() is True): self.snark_table.set_video_row(self._last_video_row) self.snark_grid.ForceRefresh() # If within the duration of a snark's show time, display it. if (self._last_video_row is not None): last_video_snark = self._snarks[self._last_video_row] if (abs(common.delta_seconds(last_video_snark["time"]) - seconds) <= common.delta_seconds(self._config.show_time)): # Back up a bit to collate simultaneous snarks. msgs = [] for i in range(self._last_video_row, -1, -1): snark = self._snarks[i] if (snark["time"] != last_video_snark["time"]): break if ("_ignored" in snark and snark["_ignored"]): continue msgs.insert(0, "%s: %s" % (snark["user"], snark["msg"])) msg = "\n".join(msgs) if (len(msg) > 0): wx.GetApp().player_frame.show_vlc_message(msg)
def delta_repr(delta): """Returns a pretty repr string of a timedelta. If delta is None, repr(None) will be returned. """ if (delta is None): return repr(None) minutes, seconds = divmod(common.delta_seconds(delta), 60) return "timedelta(minutes=%d, seconds=%d)" % (minutes, seconds)
def _on_goto(self, e): """Seeks the video to the currently selected snark row's time.""" rows = self.snark_grid.GetSelectedRows() if (not rows): self.statusbar.SetStatusText("No snark selected.", self.STATUS_HELP) else: wx.GetApp().player_frame.set_vlc_time(max(0, (common.delta_seconds(self._snarks[rows[0]]["time"])-self.seek_preroll) * 1000)) if (e is not None): e.Skip(False) # Consume the event.
def on_snarks_changed(self, e): """Responds to config/snarks list changes. See common.SnarksWrapper.add_snarks_listener(). :param e: A SnarksEvent. """ if (common.SnarksEvent.FLAG_CONFIG_SHOW_TIME not in e.get_flags()): return self._config = e.get_source().clone_config() show_time_milliseconds = common.delta_seconds(self._config.show_time)*1000 self.vlc_player.video_set_marquee_int(vlc.VideoMarqueeOption.Timeout, show_time_miliseconds) # Milliseconds. 0=Forever.
def init_vlc(self): """Sets the window id where VLC will render video output. On platforms with GTK, this might only be possible after the window has been created. """ # Gotta mention marq in the instance for marquee methods to work. # Gotta show title for marquee to be visible. # Verbose -1 suppresses spam about "vlc_object_find_name" not being safe. self.vlc_obj = vlc.Instance("--video-title-show", "--video-title-timeout=1", "--sub-filter=logo:marq", "--verbose=-1") self.vlc_player = self.vlc_obj.media_player_new() self.vlc_event_manager = None show_time_milliseconds = common.delta_seconds(self._config.show_time)*1000 #self.vlc_player.video_set_marquee_int(vlc.VideoMarqueeOption.Enable, 1) # Must enable while video is shown. self.vlc_player.video_set_marquee_int(vlc.VideoMarqueeOption.Position, vlc.Position.Bottom) self.vlc_player.video_set_marquee_int(vlc.VideoMarqueeOption.Refresh, 100) # Milliseconds. self.vlc_player.video_set_marquee_int(vlc.VideoMarqueeOption.Timeout, show_time_milliseconds) # Milliseconds. 0=Forever. #self.vlc_player.video_set_marquee_string(vlc.VideoMarqueeOption.Text, "aaaaaaaaaa") this_platform = platform.system() if (re.search("Linux", this_platform, re.IGNORECASE)): self.vlc_player.set_xwindow(self.video_panel.GetHandle()) elif (re.search("Windows", this_platform, re.IGNORECASE)): self.vlc_player.set_hwnd(self.video_panel.GetHandle()) elif (re.search("Darwin", this_platform, re.IGNORECASE)): # Reportedly this is broken. # In OSX, the vlc window can not be attached. # And there's some weirdness concerning wx on Carbon vs new Cocoa. self.vlc_player.set_nsobject(self.video_panel.GetHandle()) # or self.vlc_player.set_agl(self.video_panel.GetHandle()) else: logging.error("Could not associate VLC video overlay with the GUI window.") if (not self.vlc_event_manager): self.vlc_event_manager = self.vlc_player.event_manager() self.vlc_event_manager.event_attach(vlc.EventType.MediaPlayerMediaChanged, self._on_vlc_event) self.vlc_event_manager.event_attach(vlc.EventType.MediaPlayerSeekableChanged, self._on_vlc_event) self.vlc_event_manager.event_attach(vlc.EventType.MediaPlayerPausableChanged, self._on_vlc_event) self.vlc_event_manager.event_attach(vlc.EventType.MediaPlayerPlaying, self._on_vlc_event) self.vlc_event_manager.event_attach(vlc.EventType.MediaPlayerPaused, self._on_vlc_event) self.vlc_event_manager.event_attach(vlc.EventType.MediaPlayerStopped, self._on_vlc_event) self.vlc_event_manager.event_attach(vlc.EventType.MediaPlayerLengthChanged, self._on_vlc_event) self.vlc_event_manager.event_attach(vlc.EventType.MediaPlayerTimeChanged, self._on_vlc_event) # Start polling GUI controls to nag vlc. self.pulse_timer.Start(milliseconds=250)
def _on_next_user(self, e): """Selects the next snark row by the currently selected snark's user. If possible, the video will seek to the new snark's time. """ rows = self.snark_grid.GetSelectedRows() if (not rows): self.statusbar.SetStatusText("No snark selected.", self.STATUS_HELP) else: for i in range(rows[0]+1, len(self._snarks)): if (self._snarks[i]["user"] == self._snarks[rows[0]]["user"]): self.snark_grid.SelectRow(i, False) #self.snark_grid.MakeCellVisible(i, 0) cell_bounds = self.snark_grid.CellToRect(i, 0) self.snark_grid.Scroll(0, cell_bounds.y // self.snark_grid.GetScrollLineY()) wx.GetApp().player_frame.set_vlc_time(max(0, (common.delta_seconds(self._snarks[i]["time"])-self.seek_preroll) * 1000)) break if (e is not None): e.Skip(False) # Consume the event.