Example #1
0
  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
Example #2
0
  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)
Example #3
0
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)
Example #4
0
  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.
Example #5
0
  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.
Example #6
0
  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)
Example #7
0
  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.