Skip to content

Commit

Permalink
issue #110
Browse files Browse the repository at this point in the history
Implement logic to close the program when the player window is closed
  • Loading branch information
pozitronik committed Feb 29, 2024
1 parent 217946f commit 3caf4ca
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 23 deletions.
13 changes: 8 additions & 5 deletions sinner/gui/GUIForm.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
from threading import Thread
from tkinter import filedialog, LEFT, Button, Frame, BOTH, StringVar, NW, X, Event, Scale, TOP, HORIZONTAL, CENTER, Menu, CASCADE, COMMAND, RADIOBUTTON, CHECKBUTTON, SEPARATOR, BooleanVar, RIDGE, BOTTOM
from tkinter.ttk import Spinbox
from typing import List, Callable
from typing import List

from customtkinter import CTk
from psutil import WINDOWS

from sinner.models.Event import Event as SinnerEvent
from sinner.Status import Status
from sinner.gui.GUIModel import GUIModel
from sinner.gui.controls.FramePlayer.BaseFramePlayer import RotateMode
Expand All @@ -18,7 +19,7 @@
from sinner.gui.controls.TextBox import TextBox
from sinner.gui.controls.ThumbnailWidget import ThumbnailWidget
from sinner.models.Config import Config
from sinner.utilities import is_int, get_app_dir, get_type_extensions, is_image, is_dir, get_directory_file_list
from sinner.utilities import is_int, get_app_dir, get_type_extensions, is_image, is_dir, get_directory_file_list, halt
from sinner.validators.AttributeLoader import Rules


Expand All @@ -41,7 +42,8 @@ class GUIForm(Status):
geometry: str
state: str # currently ignored, see issue #100
sources_library: List[str]
_on_window_close_callback: Callable[[], None] | None = None

_event_player_window_closed: SinnerEvent # the event when the player window is closed (forwarded via GUIModel)

def rules(self) -> Rules:
return [
Expand Down Expand Up @@ -113,10 +115,11 @@ def __init__(self, parameters: Namespace):
self.GUIWindow.title('sinner controls')
self.GUIWindow.minsize(500, 130)
self.GUIWindow.protocol('WM_DELETE_WINDOW', lambda: on_player_window_close())
self._event_player_window_closed = SinnerEvent(on_set_callback=lambda: on_player_window_close())

def on_player_window_close() -> None:
self.GUIModel.player_stop(wait=True)
quit()
halt()

self.GUIWindow.bind("<Configure>", lambda event: on_player_window_configure(event))

Expand All @@ -132,7 +135,7 @@ def on_player_window_configure(event: Event) -> None: # type: ignore[type-arg]
self.ProgressBars = ProgressBarManager(self.GUIWindow)
self.StatusBar = StatusBar(self.GUIWindow, borderwidth=1, relief=RIDGE, items={"Target resolution": "", "Render size": ""})

self.GUIModel = GUIModel(parameters, pb_control=self.ProgressBars, status_callback=lambda name, value: self.StatusBar.item(name, value))
self.GUIModel = GUIModel(parameters, pb_control=self.ProgressBars, status_callback=lambda name, value: self.StatusBar.item(name, value), on_close_event=self._event_player_window_closed)

def on_player_window_key_release(event: Event) -> None: # type: ignore[type-arg]
if event.keycode == 37: # left arrow
Expand Down
5 changes: 3 additions & 2 deletions sinner/gui/GUIModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,16 @@ def rules(self) -> Rules:
}
]

def __init__(self, parameters: Namespace, pb_control: ProgressBarManager, status_callback: Callable[[str, str], Any]):
def __init__(self, parameters: Namespace, pb_control: ProgressBarManager, status_callback: Callable[[str, str], Any], on_close_event: Event | None = None):
self.parameters = parameters
super().__init__(parameters)
self._processors = {}
if self.bootstrap_processors:
self._processors = self.processors

self.TimeLine = FrameTimeLine(source_name=self._source_path, target_name=self._target_path, temp_dir=self.temp_dir, end_frame=self.frame_handler.fc)
self.Player = PygameFramePlayer(width=self.frame_handler.resolution[0], height=self.frame_handler.resolution[1], caption='sinner player')
self.Player = PygameFramePlayer(width=self.frame_handler.resolution[0], height=self.frame_handler.resolution[1], caption='sinner player', on_close_event=on_close_event)

if self._enable_sound:
self.AudioPlayer = PygameAudioBackend(parameters=self.parameters, media_path=self._target_path)
self.ProgressBarsManager = pb_control
Expand Down
31 changes: 15 additions & 16 deletions sinner/gui/controls/FramePlayer/PygameFramePlayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,26 @@
from sinner.models.Event import Event
from sinner.typing import Frame
from sinner.utilities import get_app_dir
from pygame.event import Event as PygameEvent


class PygameFramePlayer(BaseFramePlayer):
screen: Surface
width: int
height: int
caption: str
on_close_event: Event | None

_visible: bool = False
_events_thread: threading.Thread
_event_handlers: dict[int, Callable[[pygame.event], None]] = {}
_event_processing: Event # the flag to control start/stop event_handling thread
_event_handlers: dict[int, Callable[[PygameEvent], None]] = {}
_event_processing: Event # the flag to control start/stop event_handling thread

def __init__(self, width: int, height: int, caption: str = 'PlayerControl'):
def __init__(self, width: int, height: int, caption: str = 'PlayerControl', on_close_event: Event | None = None):
self.width = width
self.height = height
self.caption = caption
self.on_close_event = on_close_event
pygame.init()
self._event_processing: Event = Event()
self._events_thread = threading.Thread(target=self._handle_events, name="_handle_events")
Expand All @@ -40,22 +43,18 @@ def __init__(self, width: int, height: int, caption: str = 'PlayerControl'):

self.add_handler(pygame.QUIT, lambda event: self._event_processing.clear())
self.add_handler(pygame.WINDOWRESIZED, lambda event: self.show_frame())

# self.add_handler(pygame.WINDOWEXPOSED, lambda: print("Window exposed"))
# self.add_handler(pygame.VIDEOEXPOSE, lambda: print("VIDEO exposed"))
# self.add_handler(pygame.VIDEORESIZE, lambda: print("VIDEO resized"))
#
# self.add_handler(pygame.WINDOWSIZECHANGED, lambda: print("Window size changed"))
# self.add_handler(pygame.WINDOWDISPLAYCHANGED, lambda: print("Window display changed"))
# self.add_handler(pygame.WINDOWRESTORED, lambda: print("Window restored"))
# self.add_handler(pygame.WINDOWMOVED, lambda: print("Window moved"))
# self.add_handler(pygame.WINDOWMAXIMIZED, lambda: print("Window maximized"))
# self.add_handler(pygame.WINDOWMINIMIZED, lambda: print("Window minimized"))
# self.add_handler(pygame.WINDOWCLOSE, lambda: print("Window closed"))
self.add_handler(pygame.WINDOWCLOSE, lambda event: self.close())

self._event_processing.set()

def add_handler(self, event_type: int, handler: Callable[[pygame.event], None]) -> None:
def close(self) -> None:
self._event_processing.clear() # stop handlers
# self.screen = None
pygame.quit()
if self.on_close_event:
self.on_close_event.set()

def add_handler(self, event_type: int, handler: Callable[[PygameEvent], None]) -> None:
self._event_handlers[event_type] = handler
self._reload_event_handlers()

Expand Down

0 comments on commit 3caf4ca

Please sign in to comment.