Files
billwuhao-ComfyUI_AudioTools/minimal_pause_node.py
T
2025-04-26 11:51:12 +08:00

109 lines
4.0 KiB
Python

import uuid
from pathlib import Path
from aiohttp import web
import folder_paths
from server import PromptServer
from comfy_execution.graph import ExecutionBlocker
TEMP_SUBFOLDER = "minimal-pause-signals"
class AlwaysEqualProxy(str):
def __eq__(self, _):
return True
def __ne__(self, _):
return False
any_type = AlwaysEqualProxy("*")
# --- Helper to get signal file path ---
def get_signal_file_path(node_id: str) -> Path:
"""Gets the path for this node's signal file."""
temp_dir = Path(folder_paths.get_temp_directory())
signal_dir = temp_dir / TEMP_SUBFOLDER
signal_dir.mkdir(parents=True, exist_ok=True)
# File existence signals "continue"
return signal_dir / f"continue_{node_id}.signal"
# --- HTTP Route ---
if hasattr(PromptServer, 'instance') and PromptServer.instance is not None:
routes = PromptServer.instance.routes
@routes.post('/minimal_pause/signal_continue')
async def signal_continue_handler(request: web.Request) -> web.Response:
"""Creates the signal file to allow the node to continue."""
try:
# No JSON needed, just check for node_id in query or form data? Let's use JSON.
if request.content_type != 'application/json':
return web.json_response({"status": "error", "message": "Invalid content type"}, status=400)
data = await request.json()
node_id = data.get('node_id')
if not node_id:
return web.json_response({"status": "error", "message": "node_id missing"}, status=400)
signal_file = get_signal_file_path(node_id)
try:
# Create an empty file to signal continuation
signal_file.touch(exist_ok=True) # Create if doesn't exist, update timestamp if does
return web.json_response({"status": "ok", "message": "Continue signal sent."})
except IOError as e:
return web.json_response({"status": "error", "message": f"Failed to create signal file: {e}"}, status=500)
except Exception as e:
return web.json_response({"status": "error", "message": "Internal server error"}, status=500)
class MinimalPauseNode:
"""A node that simply pauses workflow execution until continued via UI."""
# Force execution so the file check always runs
@classmethod
def IS_CHANGED(cls, *args, **kwargs):
return str(uuid.uuid4())
@classmethod
def INPUT_TYPES(cls):
# Takes any input type just to allow connection, but doesn't use it
return {
"required": {
"any": (any_type, {}), # Use Comfy's AnyType wildcard
},
"hidden": {
"prompt": "PROMPT",
"extra_pnginfo": "EXTRA_PNGINFO",
"unique_id": "UNIQUE_ID",
},
}
# Returns the same type it received
RETURN_TYPES = (any_type,)
RETURN_NAMES = ("any",)
FUNCTION = "pause_or_continue"
CATEGORY = "🎤MW/MW-Audio-Tools" # Simple category
OUTPUT_NODE = True # Passes data through
def pause_or_continue(self, any, unique_id: str, prompt=None, extra_pnginfo=None, **kwargs):
node_id = unique_id
signal_file = get_signal_file_path(node_id)
if signal_file.exists():
# Signal file exists - User clicked Continue
try:
signal_file.unlink() # Delete the signal file to reset for next time
except OSError as e:
print(f"Failed to delete signal file: {e}")
# Return the any data
return {"result": (any,)}
else:
# Send message to UI to enable the button
if hasattr(PromptServer, 'instance') and PromptServer.instance is not None:
PromptServer.instance.send_sync("minimal_pause_enable_button", { "node_id": node_id })
# Return ExecutionBlocker for the any output
return {"result": (ExecutionBlocker(None),)}