Skip to content

Commit

Permalink
feat: add option to set auto reload timer for live videos
Browse files Browse the repository at this point in the history
  • Loading branch information
vzhd1701 committed Jul 13, 2022
1 parent 3a2e1a3 commit 305e890
Show file tree
Hide file tree
Showing 10 changed files with 208 additions and 36 deletions.
8 changes: 7 additions & 1 deletion gridplayer/dialogs/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ def __init__(self, parent):
"video_defaults/muted": self.videoMuted,
"video_defaults/paused": self.videoPaused,
"video_defaults/stream_quality": self.streamQuality,
"video_defaults/auto_reload_timer": self.streamAutoReloadTimer,
"misc/overlay_hide": self.timeoutOverlayFlag,
"misc/overlay_timeout": self.timeoutOverlay,
"misc/mouse_hide": self.timeoutMouseHideFlag,
Expand Down Expand Up @@ -149,7 +150,7 @@ def ui_fill(self): # noqa: WPS213
self.fill_playlistSeekSyncMode()
self.fill_streamingResolverPriority()

def ui_set_limits(self):
def ui_set_limits(self): # noqa: WPS213
self.playerVideoDriverPlayers.setRange(1, MAX_VLC_PROCESSES)
self.timeoutOverlay.setRange(1, 60)
self.timeoutMouseHide.setRange(1, 60)
Expand All @@ -160,6 +161,11 @@ def ui_set_limits(self):
self.gridSize.setRange(0, 1000)
self.gridSize.setSpecialValueText(translate("Grid Size", "Auto"))

self.streamAutoReloadTimer.setRange(0, 1000)
self.streamAutoReloadTimer.setSpecialValueText(
translate("Auto Reload Timer", "Disabled")
)

def ui_customize_dynamic(self):
self.driver_selected(self.playerVideoDriver.currentIndex())
self.timeoutMouseHide.setEnabled(self.timeoutMouseHideFlag.isChecked())
Expand Down
62 changes: 46 additions & 16 deletions gridplayer/dialogs/settings_dialog_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,34 +311,24 @@ def setupUi(self, SettingsDialog):
QtWidgets.QFormLayout.FieldsStayAtSizeHint
)
self.formLayout_4.setObjectName("formLayout_4")
self.streamQualityLabel = QtWidgets.QLabel(self.page_defaults_video)
self.streamQualityLabel.setObjectName("streamQualityLabel")
self.formLayout_4.setWidget(
0, QtWidgets.QFormLayout.LabelRole, self.streamQualityLabel
)
self.streamQuality = QtWidgets.QComboBox(self.page_defaults_video)
self.streamQuality.setObjectName("streamQuality")
self.formLayout_4.setWidget(
0, QtWidgets.QFormLayout.FieldRole, self.streamQuality
)
self.videoAspectLabel = QtWidgets.QLabel(self.page_defaults_video)
self.videoAspectLabel.setObjectName("videoAspectLabel")
self.formLayout_4.setWidget(
1, QtWidgets.QFormLayout.LabelRole, self.videoAspectLabel
0, QtWidgets.QFormLayout.LabelRole, self.videoAspectLabel
)
self.videoAspect = QtWidgets.QComboBox(self.page_defaults_video)
self.videoAspect.setObjectName("videoAspect")
self.formLayout_4.setWidget(
1, QtWidgets.QFormLayout.FieldRole, self.videoAspect
0, QtWidgets.QFormLayout.FieldRole, self.videoAspect
)
self.repeatModeLabel = QtWidgets.QLabel(self.page_defaults_video)
self.repeatModeLabel.setObjectName("repeatModeLabel")
self.formLayout_4.setWidget(
2, QtWidgets.QFormLayout.LabelRole, self.repeatModeLabel
1, QtWidgets.QFormLayout.LabelRole, self.repeatModeLabel
)
self.repeatMode = QtWidgets.QComboBox(self.page_defaults_video)
self.repeatMode.setObjectName("repeatMode")
self.formLayout_4.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.repeatMode)
self.formLayout_4.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.repeatMode)
self.lay_page_defaults_video.addLayout(self.formLayout_4)
self.videoRandomLoop = QtWidgets.QCheckBox(self.page_defaults_video)
self.videoRandomLoop.setObjectName("videoRandomLoop")
Expand All @@ -349,6 +339,43 @@ def setupUi(self, SettingsDialog):
self.videoMuted = QtWidgets.QCheckBox(self.page_defaults_video)
self.videoMuted.setObjectName("videoMuted")
self.lay_page_defaults_video.addWidget(self.videoMuted)
self.label_12 = QtWidgets.QLabel(self.page_defaults_video)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_12.setFont(font)
self.label_12.setObjectName("label_12")
self.lay_page_defaults_video.addWidget(self.label_12)
self.formLayout_9 = QtWidgets.QFormLayout()
self.formLayout_9.setFieldGrowthPolicy(
QtWidgets.QFormLayout.FieldsStayAtSizeHint
)
self.formLayout_9.setObjectName("formLayout_9")
self.streamQualityLabel = QtWidgets.QLabel(self.page_defaults_video)
self.streamQualityLabel.setObjectName("streamQualityLabel")
self.formLayout_9.setWidget(
0, QtWidgets.QFormLayout.LabelRole, self.streamQualityLabel
)
self.streamQuality = QtWidgets.QComboBox(self.page_defaults_video)
self.streamQuality.setObjectName("streamQuality")
self.formLayout_9.setWidget(
0, QtWidgets.QFormLayout.FieldRole, self.streamQuality
)
self.label_13 = QtWidgets.QLabel(self.page_defaults_video)
self.label_13.setObjectName("label_13")
self.formLayout_9.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_13)
self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.streamAutoReloadTimer = QtWidgets.QSpinBox(self.page_defaults_video)
self.streamAutoReloadTimer.setObjectName("streamAutoReloadTimer")
self.horizontalLayout_5.addWidget(self.streamAutoReloadTimer)
self.label_14 = QtWidgets.QLabel(self.page_defaults_video)
self.label_14.setObjectName("label_14")
self.horizontalLayout_5.addWidget(self.label_14)
self.formLayout_9.setLayout(
1, QtWidgets.QFormLayout.FieldRole, self.horizontalLayout_5
)
self.lay_page_defaults_video.addLayout(self.formLayout_9)
spacerItem2 = QtWidgets.QSpacerItem(
20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding
)
Expand Down Expand Up @@ -501,7 +528,7 @@ def setupUi(self, SettingsDialog):
self.lay_main.setStretch(0, 1)

self.retranslateUi(SettingsDialog)
self.section_page.setCurrentIndex(5)
self.section_page.setCurrentIndex(4)
self.buttonBox.accepted.connect(SettingsDialog.accept) # type: ignore
self.buttonBox.rejected.connect(SettingsDialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(SettingsDialog)
Expand Down Expand Up @@ -608,14 +635,17 @@ def retranslateUi(self, SettingsDialog):
self.gridSizeLabel.setText(_translate("SettingsDialog", "Grid size"))
self.gridFit.setText(_translate("SettingsDialog", "Fit grid cells"))
self.gridShuffleOnLoad.setText(_translate("SettingsDialog", "Shuffle on load"))
self.streamQualityLabel.setText(_translate("SettingsDialog", "Stream quality"))
self.videoAspectLabel.setText(_translate("SettingsDialog", "Aspect mode"))
self.repeatModeLabel.setText(_translate("SettingsDialog", "Repeat mode"))
self.videoRandomLoop.setText(
_translate("SettingsDialog", "Start at random position")
)
self.videoPaused.setText(_translate("SettingsDialog", "Paused"))
self.videoMuted.setText(_translate("SettingsDialog", "Muted"))
self.label_12.setText(_translate("SettingsDialog", "Streaming Videos"))
self.streamQualityLabel.setText(_translate("SettingsDialog", "Stream quality"))
self.label_13.setText(_translate("SettingsDialog", "Auto reload time"))
self.label_14.setText(_translate("SettingsDialog", "(min)"))
self.playerVideoDriverBox.setTitle(
_translate("SettingsDialog", "Video Decoder")
)
Expand Down
1 change: 1 addition & 0 deletions gridplayer/models/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class Video(BaseModel):

# Streamable
stream_quality: str = default_field("video_defaults/stream_quality")
auto_reload_timer_min: int = default_field("video_defaults/auto_reload_timer")

@property
def uri_name(self) -> str:
Expand Down
13 changes: 13 additions & 0 deletions gridplayer/player/managers/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,13 @@
"key": "F5",
"func": ("active", "reload"),
},
"Auto Reload: %v": {
"title": "{0}: %v".format(translate("Actions", "Auto Reload")),
"icon": "reload",
"func": ("active", "auto_reload_timer"),
"value_getter": ("active", "get_auto_reload_timer"),
"show_if": "is_active_live",
},
"Close": {
"title": translate("Actions", "Close"),
"key": "Ctrl+F4",
Expand Down Expand Up @@ -703,6 +710,12 @@
"key": "Shift+F5",
"func": "reload_all",
},
"Auto Reload [ALL]": {
"title": translate("Actions", "Auto Reload"),
"icon": "reload",
"func": "all_set_auto_reload_timer",
"show_if": "is_any_videos_live",
},
# Playlist
"Seek Sync (Disabled)": {
"title": translate("Actions", "Disabled"),
Expand Down
6 changes: 3 additions & 3 deletions gridplayer/player/managers/active_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ def is_no_active_block(self):

def cmd_active(self, command, *args):
if self.is_no_active_block:
return
return None

is_inactive_command = command in {"switch_stream_quality", "reload", "close"}

if not is_inactive_command and not self.is_active_initialized():
return
return None

getattr(self._ctx.active_block, command)(*args)
return getattr(self._ctx.active_block, command)(*args)

def is_active_initialized(self):
if self.is_no_active_block:
Expand Down
2 changes: 2 additions & 0 deletions gridplayer/player/managers/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
"Stream Quality",
"Rename",
"Reload",
"Auto Reload: %v",
"Close",
],
"video_all": [
Expand Down Expand Up @@ -198,6 +199,7 @@
),
"---",
"Reload [ALL]",
"Auto Reload [ALL]",
),
(
"Seek Sync",
Expand Down
22 changes: 21 additions & 1 deletion gridplayer/player/managers/video_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from PyQt5.QtCore import Qt, pyqtSignal

from gridplayer.dialogs.input_dialog import QCustomSpinboxTimeInput
from gridplayer.dialogs.input_dialog import QCustomSpinboxInput, QCustomSpinboxTimeInput
from gridplayer.models.video import Video
from gridplayer.params.static import SeekSyncMode, VideoAspect, VideoRepeat
from gridplayer.player.managers.base import ManagerBase
Expand Down Expand Up @@ -122,6 +122,7 @@ class VideoBlocksManager(ManagerBase):
all_scale_reset = pyqtSignal()

all_set_aspect = pyqtSignal(VideoAspect)
all_set_auto_reload_timer = pyqtSignal(int)

def __init__(self, **kwargs):
super().__init__(**kwargs)
Expand All @@ -144,10 +145,12 @@ def commands(self):
"all": self.cmd_all,
"all_play_pause": self.cmd_all_play_pause,
"all_seek_timecode": self.cmd_seek_timecode,
"all_set_auto_reload_timer": self.cmd_set_auto_reload_timer,
"is_videos": lambda: bool(self._ctx.video_blocks),
"is_any_videos_initialized": self.is_any_videos_initialized,
"is_any_videos_seekable": self.is_any_videos_seekable,
"is_any_videos_local_file": self.is_any_videos_local_file,
"is_any_videos_live": self.is_any_videos_live,
"is_seek_sync_mode_set_to": self.is_seek_sync_mode_set_to,
"set_seek_sync_mode": self.set_seek_sync_mode,
"reload_all": self.reload_videos,
Expand Down Expand Up @@ -185,6 +188,19 @@ def cmd_seek_timecode(self):

self.all_seek.emit(time_ms)

def cmd_set_auto_reload_timer(self):
time_minutes = QCustomSpinboxInput.get_int(
parent=self.parent(),
title=translate(
"Dialog - Set auto reload timer", "Set auto reload timer", "Header"
),
special_text=translate("Auto Reload Timer", "Disabled"),
_min=0,
_max=1000,
)

self.all_set_auto_reload_timer.emit(time_minutes)

def cmd_shuffle_video_blocks(self):
self._ctx.video_blocks.shuffle()
self.video_order_changed.emit()
Expand Down Expand Up @@ -227,6 +243,9 @@ def is_any_videos_initialized(self):
def is_any_videos_seekable(self):
return any(not vb.is_live for vb in self._ctx.video_blocks.initialized)

def is_any_videos_live(self):
return any(vb.is_live for vb in self._ctx.video_blocks.initialized)

def is_any_videos_local_file(self):
return any(vb.is_local_file for vb in self._ctx.video_blocks.initialized)

Expand Down Expand Up @@ -326,6 +345,7 @@ def _add_video_block(self, video):
(self.all_scale_decrease, vb.scale_decrease),
(self.all_scale_reset, vb.scale_reset),
(self.all_set_aspect, vb.set_aspect),
(self.all_set_auto_reload_timer, vb.set_auto_reload_timer),
(self.all_previous_video, vb.previous_video),
(self.all_next_video, vb.next_video),
(self.hide_overlay, vb.hide_overlay),
Expand Down
1 change: 1 addition & 0 deletions gridplayer/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def default_language():
"video_defaults/muted": True,
"video_defaults/paused": False,
"video_defaults/stream_quality": "best",
"video_defaults/auto_reload_timer": 0,
"misc/overlay_hide": True,
"misc/overlay_timeout": 3,
"misc/mouse_hide": True,
Expand Down
60 changes: 59 additions & 1 deletion gridplayer/widgets/video_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from PyQt5.QtGui import QCursor
from PyQt5.QtWidgets import QStackedLayout, QWidget

from gridplayer.dialogs.input_dialog import QCustomSpinboxTimeInput
from gridplayer.dialogs.input_dialog import QCustomSpinboxInput, QCustomSpinboxTimeInput
from gridplayer.dialogs.rename_dialog import QVideoRenameDialog
from gridplayer.exceptions import PlayerException
from gridplayer.models.stream import Streams
Expand Down Expand Up @@ -80,6 +80,16 @@ def wrapper(*args, **kwargs):
return wrapper


def only_live(func):
def wrapper(*args, **kwargs):
self = args[0] # noqa: WPS117
if not self.is_live:
return None
return func(*args, **kwargs)

return wrapper


def only_local_file(func):
def wrapper(*args, **kwargs):
self = args[0] # noqa: WPS117
Expand Down Expand Up @@ -157,6 +167,9 @@ def __init__(self, video_driver, context, **kwargs):
self._in_progress_timer.setInterval(IN_PROGRESS_THRESHOLD_MS)
self._in_progress_timer.timeout.connect(self.is_in_progress_change)

self._reload_timer = QTimer(self)
self._reload_timer.timeout.connect(self.reload)

self.url_resolver = self.init_url_resolver()
self.video_driver = self.init_video_driver()

Expand Down Expand Up @@ -421,6 +434,48 @@ def seek_timecode(self):

self.manual_seek("seek", time_ms)

@only_initialized
@only_live
def auto_reload_timer(self):
time_min = QCustomSpinboxInput.get_int(
parent=self.parent(),
title=translate(
"Dialog - Set auto reload timer", "Set auto reload timer", "Header"
),
special_text=translate("Auto Reload Timer", "Disabled"),
initial_value=self.video_params.auto_reload_timer_min,
_min=0,
_max=1000,
)

self.set_auto_reload_timer(time_min)

@only_initialized
@only_live
def set_auto_reload_timer(self, time_min):
self.video_params.auto_reload_timer_min = time_min

time_ms = time_min * 60 * 1000

if time_ms == 0:
self._reload_timer.stop()
self._reload_timer.setInterval(0)
return

self._reload_timer.setInterval(time_ms)
self._reload_timer.start()

@only_initialized
@only_live
def get_auto_reload_timer(self):
if self.video_params.auto_reload_timer_min == 0:
return translate("Auto Reload Timer", "Disabled")

return "{0} {1}".format(
self.video_params.auto_reload_timer_min,
translate("Auto Reload Timer", "minute(s)"),
)

def is_under_cursor(self):
return self.rect().contains(self.mapFromGlobal(QCursor.pos()))

Expand Down Expand Up @@ -568,6 +623,7 @@ def apply_snapshot(self, snapshot: Video):
self.set_rate(snapshot.rate, is_silent=True)

self.switch_stream_quality(snapshot.stream_quality)
self.set_auto_reload_timer(snapshot.auto_reload_timer_min)

self.video_params = snapshot.copy()

Expand Down Expand Up @@ -653,6 +709,8 @@ def load_video_finish(self):
self.set_loop_end_time(self.video_params.loop_end)
self.set_rate(self.video_params.rate, is_silent=True)

self.set_auto_reload_timer(self.video_params.auto_reload_timer_min)

self.video_status.hide()
self.show_overlay()

Expand Down
Loading

0 comments on commit 305e890

Please sign in to comment.