From 884cff6c5549f051b19b7b4ea131d784076f2d13 Mon Sep 17 00:00:00 2001 From: Thomas Mello Date: Wed, 9 Oct 2024 19:48:22 +0300 Subject: [PATCH 1/2] feat: add notification support --- FluidFrames.RIFE.py | 11 +++++++++++ requirements.txt | 1 + 2 files changed, 12 insertions(+) diff --git a/FluidFrames.RIFE.py b/FluidFrames.RIFE.py index ff04a24..a1bcacc 100644 --- a/FluidFrames.RIFE.py +++ b/FluidFrames.RIFE.py @@ -99,6 +99,7 @@ set_appearance_mode, set_default_color_theme ) +from notifypy import Notify if sys.stdout is None: sys.stdout = open(os_devnull, "w") if sys.stderr is None: sys.stderr = open(os_devnull, "w") @@ -1320,6 +1321,9 @@ def frame_generation_orchestrator( selected_keep_frames ) + # Show notification when the entire queue is empty + show_notification("FluidFrames", "All video interpolation jobs are complete!") + write_process_status(processing_queue, f"{COMPLETED_STATUS}") except Exception as exception: @@ -1538,6 +1542,13 @@ def open_output_path_action() -> None: else: selected_output_path.set(asked_selected_output_path) +# GUI notification function +def show_notification(title: str, message: str) -> None: + notification = Notify() + notification.title = title + notification.message = message + + notification.send() # GUI select from menus functions --------------------------- diff --git a/requirements.txt b/requirements.txt index 7e6e9a2..20af50a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,7 @@ onnxruntime-directml==1.17.3 #GUI customtkinter +notify-py #UTILS numpy==1.26.4 From b3ef459f14a886180a1c70d83c65b290c6beb54b Mon Sep 17 00:00:00 2001 From: Thomas Mello Date: Thu, 10 Oct 2024 04:21:50 +0300 Subject: [PATCH 2/2] feat: add notification setting to user prefs --- FluidFrames.RIFE.py | 74 ++++++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 21 deletions(-) diff --git a/FluidFrames.RIFE.py b/FluidFrames.RIFE.py index a1bcacc..e05ff5c 100644 --- a/FluidFrames.RIFE.py +++ b/FluidFrames.RIFE.py @@ -85,6 +85,7 @@ # GUI imports from tkinter import StringVar from tkinter import DISABLED +from tkinter import BooleanVar from customtkinter import ( CTk, CTkButton, @@ -95,6 +96,7 @@ CTkOptionMenu, CTkScrollableFrame, CTkToplevel, + CTkCheckBox, filedialog, set_appearance_mode, set_default_color_theme @@ -140,15 +142,16 @@ def find_by_relative_path(relative_path: str) -> str: print(f"[{app_name}] Preference file exist") with open(USER_PREFERENCE_PATH, "r") as json_file: json_data = json_load(json_file) - default_AI_model = json_data["default_AI_model"] - default_generation_option = json_data["default_generation_option"] - default_gpu = json_data["default_gpu"] - default_image_extension = json_data["default_image_extension"] - default_video_extension = json_data["default_video_extension"] - default_keep_frames = json_data["default_keep_frames"] - default_output_path = json_data["default_output_path"] - default_resize_factor = json_data["default_resize_factor"] - default_cpu_number = json_data["default_cpu_number"] + default_AI_model = json_data["default_AI_model"] + default_generation_option = json_data["default_generation_option"] + default_gpu = json_data["default_gpu"] + default_image_extension = json_data["default_image_extension"] + default_video_extension = json_data["default_video_extension"] + default_keep_frames = json_data["default_keep_frames"] + default_output_path = json_data["default_output_path"] + default_resize_factor = json_data["default_resize_factor"] + default_cpu_number = json_data["default_cpu_number"] + default_notify_on_complete = json_data.get("default_notify_on_complete", False) else: print(f"[{app_name}] Preference file does not exist, using default coded value") default_AI_model = AI_models_list[0] @@ -160,6 +163,7 @@ def find_by_relative_path(relative_path: str) -> str: default_output_path = OUTPUT_PATH_CODED default_resize_factor = str(50) default_cpu_number = str(4) + default_notify_on_complete = False COMPLETED_STATUS = "Completed" @@ -753,6 +757,18 @@ def create_text_box(textvariable: StringVar) -> CTkEntry: border_color = "#404040", ) +def create_notify_checkbox(boolvariable: BooleanVar) -> CTkCheckBox: + return CTkCheckBox( + master=window, + text="Notify on complete", + variable=boolvariable, + onvalue=True, + offvalue=False, + text_color="#C0C0C0", + fg_color="#000000", + border_color="#404040" + ) + def create_text_box_output_path(textvariable: StringVar) -> CTkEntry: return CTkEntry( master = window, @@ -1184,7 +1200,8 @@ def generate_button_command() -> None: selected_video_extension, resize_factor, cpu_number, - selected_keep_frames + selected_keep_frames, + notify_on_complete ) ) process_frame_generation_orchestrator.start() @@ -1291,7 +1308,8 @@ def frame_generation_orchestrator( selected_video_extension: str, resize_factor: int, cpu_number: int, - selected_keep_frames: bool + selected_keep_frames: bool, + selected_notify: bool ) -> None: frame_gen_factor, slowmotion = check_frame_generation_option(selected_generation_option) @@ -1322,7 +1340,8 @@ def frame_generation_orchestrator( ) # Show notification when the entire queue is empty - show_notification("FluidFrames", "All video interpolation jobs are complete!") + if selected_notify: + show_notification("FluidFrames", "All video interpolation jobs are complete!") write_process_status(processing_queue, f"{COMPLETED_STATUS}") @@ -1437,6 +1456,7 @@ def user_input_checks() -> None: global selected_image_extension global resize_factor global cpu_number + global notify_on_complete is_ready = True @@ -1473,6 +1493,8 @@ def user_input_checks() -> None: is_ready = False else: cpu_number = int(cpu_number) + # notify on complete ------------------------------------------ + notify_on_complete = selected_notify.get() return is_ready @@ -1944,6 +1966,9 @@ def place_generation_button(): ) generation_button.place(relx = column2_x, rely = row4_y, anchor = "center") +def place_notify_checkbox(): + notify_checkbox = create_notify_checkbox(selected_notify) + notify_checkbox.place(relx = column1_x, rely = row4_y, anchor = "center") # Main functions --------------------------- @@ -1961,6 +1986,7 @@ def on_app_close(): global selected_video_extension global resize_factor global cpu_number + global notify_on_complete AI_model_to_save = f"{selected_AI_model}" generation_option_to_save = f"{selected_generation_option}" @@ -1970,15 +1996,16 @@ def on_app_close(): video_extension_to_save = f"{selected_video_extension}" user_preference = { - "default_AI_model": AI_model_to_save, - "default_generation_option": generation_option_to_save, - "default_gpu": gpu_to_save, - "default_image_extension": image_extension_to_save, - "default_video_extension": video_extension_to_save, - "default_keep_frames": keep_frames_to_save, - "default_output_path": selected_output_path.get(), - "default_resize_factor": str(selected_resize_factor.get()), - "default_cpu_number": str(selected_cpu_number.get()), + "default_AI_model": AI_model_to_save, + "default_generation_option": generation_option_to_save, + "default_gpu": gpu_to_save, + "default_image_extension": image_extension_to_save, + "default_video_extension": video_extension_to_save, + "default_keep_frames": keep_frames_to_save, + "default_output_path": selected_output_path.get(), + "default_resize_factor": str(selected_resize_factor.get()), + "default_cpu_number": str(selected_cpu_number.get()), + "default_notify_on_complete": notify_on_complete, } user_preference_json = json_dumps(user_preference) with open(USER_PREFERENCE_PATH, "w") as preference_file: @@ -2009,6 +2036,7 @@ def __init__(self, window): place_gpu_menu() place_keep_frames_menu() place_cpu_textbox() + place_notify_checkbox() place_image_output_menu() place_video_extension_menu() @@ -2032,6 +2060,7 @@ def __init__(self, window): selected_output_path = StringVar() selected_resize_factor = StringVar() selected_cpu_number = StringVar() + selected_notify = BooleanVar(value=False) global selected_file_list global selected_AI_model @@ -2042,6 +2071,7 @@ def __init__(self, window): global cpu_number global selected_image_extension global selected_video_extension + global notify_on_complete selected_file_list = [] @@ -2056,6 +2086,8 @@ def __init__(self, window): selected_resize_factor.set(default_resize_factor) selected_cpu_number.set(default_cpu_number) selected_output_path.set(default_output_path) + selected_notify.set(default_notify_on_complete) + notify_on_complete = selected_notify.get() info_message.set("Hi :)") selected_resize_factor.trace_add('write', update_file_widget)