1+ # Licensed under the GPL-3.0 License.
2+ # Created for TagStudio: https://github.com/CyanVoxel/TagStudio
3+
14import logging
2- import os
3- import typing
45
5- # os.environ["QT_MEDIA_BACKEND"] = "ffmpeg"
6+ from pathlib import Path
7+ import typing
68
79from PySide6 .QtCore import (
810 Qt ,
1820from PySide6 .QtMultimediaWidgets import QGraphicsVideoItem
1921from PySide6 .QtWidgets import QGraphicsView , QGraphicsScene
2022from PySide6 .QtGui import (
21- QInputMethodEvent ,
2223 QPen ,
2324 QColor ,
2425 QBrush ,
2930 QBitmap ,
3031)
3132from PySide6 .QtSvgWidgets import QSvgWidget
32- from PIL import Image
3333from src .qt .helpers .file_opener import FileOpenerHelper
34-
35- from src .core .constants import VIDEO_TYPES , AUDIO_TYPES
3634from PIL import Image , ImageDraw
3735from src .core .enums import SettingItems
3836
4139
4240
4341class VideoPlayer (QGraphicsView ):
44- """A simple video player for the TagStudio application ."""
42+ """A basic video player."""
4543
46- resolution = QSize (1280 , 720 )
47- hover_fix_timer = QTimer ()
4844 video_preview = None
4945 play_pause = None
5046 mute_button = None
51- content_visible = False
52- filepath = None
5347
5448 def __init__ (self , driver : "QtDriver" ) -> None :
55- # Set up the base class.
5649 super ().__init__ ()
5750 self .driver = driver
51+ self .resolution = QSize (1280 , 720 )
5852 self .animation = QVariantAnimation (self )
5953 self .animation .valueChanged .connect (
6054 lambda value : self .setTintTransparency (value )
6155 )
56+ self .hover_fix_timer = QTimer ()
6257 self .hover_fix_timer .timeout .connect (lambda : self .checkIfStillHovered ())
6358 self .hover_fix_timer .setSingleShot (True )
59+ self .content_visible = False
60+ self .filepath = None
61+
6462 # Set up the video player.
6563 self .installEventFilter (self )
6664 self .setScene (QGraphicsScene (self ))
@@ -82,6 +80,7 @@ def __init__(self, driver: "QtDriver") -> None:
8280 self .setHorizontalScrollBarPolicy (Qt .ScrollBarPolicy .ScrollBarAlwaysOff )
8381 self .scene ().addItem (self .video_preview )
8482 self .video_preview .setAcceptedMouseButtons (Qt .MouseButton .LeftButton )
83+
8584 # Set up the video tint.
8685 self .video_tint = self .scene ().addRect (
8786 0 ,
@@ -91,44 +90,31 @@ def __init__(self, driver: "QtDriver") -> None:
9190 QPen (QColor (0 , 0 , 0 , 0 )),
9291 QBrush (QColor (0 , 0 , 0 , 0 )),
9392 )
94- # self.video_tint.setParentItem(self.video_preview)
95- # self.album_art = QGraphicsPixmapItem(self.video_preview)
96- # self.scene().addItem(self.album_art)
97- # self.album_art.setPixmap(
98- # QPixmap("./tagstudio/resources/qt/images/thumb_file_default_512.png")
99- # )
100- # self.album_art.setOpacity(0.0)
93+
10194 # Set up the buttons.
102- self .play_pause = QSvgWidget ("./tagstudio/resources/pause.svg" )
95+ self .play_pause = QSvgWidget ()
10396 self .play_pause .setAttribute (Qt .WidgetAttribute .WA_TranslucentBackground , True )
10497 self .play_pause .setMouseTracking (True )
10598 self .play_pause .installEventFilter (self )
10699 self .scene ().addWidget (self .play_pause )
107- self .play_pause .resize (100 , 100 )
100+ self .play_pause .resize (72 , 72 )
108101 self .play_pause .move (
109102 int (self .width () / 2 - self .play_pause .size ().width () / 2 ),
110103 int (self .height () / 2 - self .play_pause .size ().height () / 2 ),
111104 )
112105 self .play_pause .hide ()
113106
114- self .mute_button = QSvgWidget ("./tagstudio/resources/volume_muted.svg" )
107+ self .mute_button = QSvgWidget ()
115108 self .mute_button .setAttribute (Qt .WidgetAttribute .WA_TranslucentBackground , True )
116109 self .mute_button .setMouseTracking (True )
117110 self .mute_button .installEventFilter (self )
118111 self .scene ().addWidget (self .mute_button )
119- self .mute_button .resize (40 , 40 )
112+ self .mute_button .resize (32 , 32 )
120113 self .mute_button .move (
121114 int (self .width () - self .mute_button .size ().width () / 2 ),
122115 int (self .height () - self .mute_button .size ().height () / 2 ),
123116 )
124117 self .mute_button .hide ()
125- # self.fullscreen_button = QSvgWidget('./tagstudio/resources/pause.svg', self)
126- # self.fullscreen_button.setMouseTracking(True)
127- # self.fullscreen_button.installEventFilter(self)
128- # self.scene().addWidget(self.fullscreen_button)
129- # self.fullscreen_button.resize(40, 40)
130- # self.fullscreen_button.move(self.fullscreen_button.size().width()/2, self.height() - self.fullscreen_button.size().height()/2)
131- # self.fullscreen_button.hide()
132118
133119 self .setContextMenuPolicy (Qt .ContextMenuPolicy .ActionsContextMenu )
134120 self .opener = FileOpenerHelper (filepath = self .filepath )
@@ -157,37 +143,32 @@ def toggleAutoplay(self) -> None:
157143 self .driver .settings .sync ()
158144
159145 def checkMediaStatus (self , media_status : QMediaPlayer .MediaStatus ) -> None :
160- # logging.info(media_status)
161146 if media_status == QMediaPlayer .MediaStatus .EndOfMedia :
162- # Switches current video to with video at filepath. Reason for this is because Pyside6 is dumb and can't handle setting a new source and freezes.
147+ # Switches current video to with video at filepath.
148+ # Reason for this is because Pyside6 can't handle setting a new source and freezes.
163149 # Even if I stop the player before switching, it breaks.
164150 # On the plus side, this adds infinite looping for the video preview.
165151 self .player .stop ()
166152 self .player .setSource (QUrl ().fromLocalFile (self .filepath ))
167- # logging.info(f'Set source to {self.filepath}.')
168- # self.video_preview.setSize(self.resolution)
169153 self .player .setPosition (0 )
170- # logging.info(f'Set muted to true.')
171154 if self .autoplay .isChecked ():
172- # logging.info(self.driver.settings.value("autoplay_videos", True, bool))
173155 self .player .play ()
174156 else :
175- # logging.info("Paused")
176157 self .player .pause ()
177158 self .opener .set_filepath (self .filepath )
178159 self .keepControlsInPlace ()
179160 self .updateControls ()
180161
181162 def updateControls (self ) -> None :
182163 if self .player .audioOutput ().isMuted ():
183- self .mute_button .load ("./tagstudio/resources/volume_muted.svg" )
164+ self .mute_button .load (self . driver . rm . volume_mute_icon )
184165 else :
185- self .mute_button .load ("./tagstudio/resources/volume_unmuted.svg" )
166+ self .mute_button .load (self . driver . rm . volume_icon )
186167
187168 if self .player .isPlaying ():
188- self .play_pause .load ("./tagstudio/resources/pause.svg" )
169+ self .play_pause .load (self . driver . rm . pause_icon )
189170 else :
190- self .play_pause .load ("./tagstudio/resources/play.svg" )
171+ self .play_pause .load (self . driver . rm . play_icon )
191172
192173 def wheelEvent (self , event : QWheelEvent ) -> None :
193174 return
@@ -229,8 +210,10 @@ def eventFilter(self, obj: QObject, event: QEvent) -> bool:
229210 return super ().eventFilter (obj , event )
230211
231212 def checkIfStillHovered (self ) -> None :
232- # Yet again, Pyside6 is dumb. I don't know why, but the HoverLeave event is not triggered sometimes and does not hide the controls.
233- # So, this is a workaround. This is called by a QTimer every 10ms to check if the mouse is still in the video preview.
213+ # I don't know why, but the HoverLeave event is not triggered sometimes
214+ # and does not hide the controls.
215+ # So, this is a workaround. This is called by a QTimer every 10ms to check if the mouse
216+ # is still in the video preview.
234217 if not self .video_preview .isUnderMouse ():
235218 self .releaseMouse ()
236219 else :
@@ -240,55 +223,51 @@ def setTintTransparency(self, value) -> None:
240223 self .video_tint .setBrush (QBrush (QColor (0 , 0 , 0 , value )))
241224
242225 def underMouse (self ) -> bool :
243- # logging.info("under mouse")
244226 self .animation .setStartValue (self .video_tint .brush ().color ().alpha ())
245227 self .animation .setEndValue (100 )
246- self .animation .setDuration (500 )
228+ self .animation .setDuration (250 )
247229 self .animation .start ()
248230 self .play_pause .show ()
249231 self .mute_button .show ()
250- # self.fullscreen_button.show()
251232 self .keepControlsInPlace ()
252233 self .updateControls ()
253- # rcontent = self.contentsRect()
254- # self.setSceneRect(0, 0, rcontent.width(), rcontent.height())
234+
255235 return super ().underMouse ()
256236
257237 def releaseMouse (self ) -> None :
258- # logging.info("release mouse")
259238 self .animation .setStartValue (self .video_tint .brush ().color ().alpha ())
260239 self .animation .setEndValue (0 )
261240 self .animation .setDuration (500 )
262241 self .animation .start ()
263242 self .play_pause .hide ()
264243 self .mute_button .hide ()
265- # self.fullscreen_button.hide()
244+
266245 return super ().releaseMouse ()
267246
268247 def resetControlsToDefault (self ) -> None :
269248 # Resets the video controls to their default state.
270- self .play_pause .load ("./tagstudio/resources/pause.svg" )
271- self .mute_button .load ("./tagstudio/resources/volume_muted.svg" )
249+ self .play_pause .load (self . driver . rm . pause_icon )
250+ self .mute_button .load (self . driver . rm . volume_mute_icon )
272251
273252 def pauseToggle (self ) -> None :
274253 if self .player .isPlaying ():
275254 self .player .pause ()
276- self .play_pause .load ("./tagstudio/resources/play.svg" )
255+ self .play_pause .load (self . driver . rm . play_icon )
277256 else :
278257 self .player .play ()
279- self .play_pause .load ("./tagstudio/resources/pause.svg" )
258+ self .play_pause .load (self . driver . rm . pause_icon )
280259
281260 def muteToggle (self ) -> None :
282261 if self .player .audioOutput ().isMuted ():
283262 self .player .audioOutput ().setMuted (False )
284- self .mute_button .load ("./tagstudio/resources/volume_unmuted.svg" )
263+ self .mute_button .load (self . driver . rm . volume_icon )
285264 else :
286265 self .player .audioOutput ().setMuted (True )
287- self .mute_button .load ("./tagstudio/resources/volume_muted.svg" )
266+ self .mute_button .load (self . driver . rm . volume_mute_icon )
288267
289268 def play (self , filepath : str , resolution : QSize ) -> None :
290- # Sets the filepath and sends the current player position to the very end, so that the new video can be played.
291- # self.player.audioOutput().setMuted(True)
269+ # Sets the filepath and sends the current player position to the very end,
270+ # so that the new video can be played.
292271 logging .info (f"Playing { filepath } " )
293272 self .resolution = resolution
294273 self .filepath = filepath
@@ -297,7 +276,6 @@ def play(self, filepath: str, resolution: QSize) -> None:
297276 self .player .play ()
298277 else :
299278 self .checkMediaStatus (QMediaPlayer .MediaStatus .EndOfMedia )
300- # logging.info(f"Successfully stopped.")
301279
302280 def stop (self ) -> None :
303281 self .filepath = None
@@ -310,10 +288,10 @@ def resizeVideo(self, new_size: QSize) -> None:
310288 0 , 0 , self .video_preview .size ().width (), self .video_preview .size ().height ()
311289 )
312290
313- rcontent = self .contentsRect ()
291+ contents = self .contentsRect ()
314292 self .centerOn (self .video_preview )
315293 self .roundCorners ()
316- self .setSceneRect (0 , 0 , rcontent .width (), rcontent .height ())
294+ self .setSceneRect (0 , 0 , contents .width (), contents .height ())
317295 self .keepControlsInPlace ()
318296
319297 def roundCorners (self ) -> None :
@@ -346,7 +324,6 @@ def keepControlsInPlace(self) -> None:
346324 int (self .width () - self .mute_button .size ().width () - 10 ),
347325 int (self .height () - self .mute_button .size ().height () - 10 ),
348326 )
349- # self.fullscreen_button.move(-self.fullscreen_button.size().width()-10, self.height() - self.fullscreen_button.size().height()-10)
350327
351328 def resizeEvent (self , event : QResizeEvent ) -> None :
352329 # Keeps the video preview in the center of the screen.
@@ -358,7 +335,6 @@ def resizeEvent(self, event: QResizeEvent) -> None:
358335 )
359336 )
360337 return
361- # return super().resizeEvent(event)\
362338
363339
364340class VideoPreview (QGraphicsVideoItem ):
@@ -367,7 +343,8 @@ def boundingRect(self):
367343
368344 def paint (self , painter , option , widget ):
369345 # painter.brush().setColor(QColor(0, 0, 0, 255))
370- # You can set any shape you want here. RoundedRect is the standard rectangle with rounded corners
346+ # You can set any shape you want here.
347+ # RoundedRect is the standard rectangle with rounded corners.
371348 # With 2nd and 3rd parameter you can tweak the curve until you get what you expect
372349
373350 super ().paint (painter , option , widget )
0 commit comments