1 Commits
Author SHA1 Message Date
chrisgoringe 1602dbe2c6 Merge pull request #162 from chrisgoringe/1.9.2
1.9.2
2026-09-29 12:32:59 +10:00
4 changed files with 74 additions and 83 deletions
+1 -5
View File
@@ -332,11 +332,7 @@ class MaskImageFilter(FilterNodeBase, io.ComfyNode):
(time.monotonic()-started_waiting_at < 5)): time.sleep(1)
if (mask_file==last_mask_file):
try:
mask = mask if mask is not None else cls.load_mask(urls[0]['filename']+" [temp]")
except Exception as e:
print(f"{e} - setting mask to None")
mask = None
mask = mask if mask is not None else cls.load_mask(urls[0]['filename']+" [temp]")
elif (mask_file is not None):
mask = cls.load_mask(mask_file)
+4 -4
View File
@@ -1,7 +1,7 @@
import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
import { create, sound_maker } from "./utils.js";
import { create } from "./utils.js";
import { popup, remove_preview } from "./popup.js";
import { graph_id_to_tab } from "./graph_map.js";
import { Log } from "./log.js";
@@ -35,9 +35,10 @@ app.registerExtension({
},
{
id: "Image Filter.UI.Sound Timeout",
name: "Reminder sound every x seconds. 0 or negative for never.",
name: "Reminder sound every x seconds",
type: "int",
defaultValue: 30
defaultValue: 30,
onChange: popup.setup_sound_throttle.bind(popup)
},
{
@@ -96,7 +97,6 @@ app.registerExtension({
{'rel':'stylesheet', 'type':'text/css', 'href': new URL("./zoomed.css", import.meta.url).href } )
api.addEventListener("execution_interrupted", popup.send_cancel.bind(popup));
api.addEventListener("cg-image-filter-images",popup.handle_message.bind(popup));
api.addEventListener("execution_interrupted", sound_maker.on_execution_ended.bind(sound_maker));
},
async beforeRegisterNodeDef(nodeType) {
if (nodeType.comfyClass == "Pick from List") {
+44 -5
View File
@@ -1,9 +1,9 @@
import { app } from "../../scripts/app.js";
import { app, ComfyApp } from "../../scripts/app.js";
import { api } from "../../scripts/api.js"
import { mask_editor_listen_for_cancel, mask_editor_showing, hide_mask_editor, press_maskeditor_cancel, press_maskeditor_save, new_editor, open_maskeditor } from "./mask_utils.js";
import { Log } from "./log.js";
import { create, sound_maker } from "./utils.js";
import { create, CallbackThrottle } from "./utils.js";
import { FloatingWindow } from "./floating_window.js";
import { graph_id_to_tab } from "./graph_map.js";
@@ -29,7 +29,8 @@ const State = Object.freeze({
ZOOMED : 5,
})
const default_audio_folder = 'extensions/cg-image-filter/audio/'
const default_audio_file = 'ding.mp3';
const stored_texts = {}
@@ -97,12 +98,20 @@ class Popup extends HTMLElement {
document.addEventListener("keydown", this.on_key_down.bind(this))
document.addEventListener("keypress", this.on_key_press.bind(this))
document.addEventListener("click", ()=>this.sound_maker.reset('click'))
this.text_edit.addEventListener('input', ()=>this.sound_maker.reset('text edit'))
document.body.appendChild(this)
this.last_response_sent = 0
this.state = State.INACTIVE
this.hidden_by_toggle = false
this.render()
this.setup_sound_throttle()
}
setup_sound_throttle() {
const t = app.ui.settings.getSettingValue("Image Filter.UI.Sound Timeout")
this.sound_maker = new CallbackThrottle( this.maybe_play_sound.bind(this), t )
}
unique_id() { return `${app.graph.id}:${this.node?.id}` }
@@ -187,6 +196,7 @@ class Popup extends HTMLElement {
*graph_id (string)
(*) are added
*/
this.sound_maker.unreset("send response")
if (Date.now()-this.last_response_sent < 1000) {
Log.message_out(msg, "(throttled)")
@@ -246,6 +256,30 @@ class Popup extends HTMLElement {
this.render()
}
async maybe_play_sound() {
if (app.ui.settings.getSettingValue("Image Filter.UI.Play Sound")) {
if (this.audiopath) {
if (await this.play_sound(default_audio_folder + this.audiopath) ||
await this.play_sound(this.audiopath)) return
}
this.play_sound(default_audio_folder + default_audio_file)
}
}
async play_sound(path) {
if (!path) return false
try {
const resp = await fetch(path);
if (!resp.ok) return false
const blob = await resp.blob();
const blobUrl = URL.createObjectURL(new Blob([blob], { type: 'audio/mpeg' }));
const audio = new Audio(blobUrl);
await audio.play();
return true
} catch (e) {
return false
}
}
handle_message(message) {
Log.message_in(message)
@@ -264,6 +298,7 @@ class Popup extends HTMLElement {
}
on_new_node(nd) {
this.sound_maker.unreset('on new node')
this.node = nd
const fp = this.floater_position()
if (fp) this.floating_window.move_to(fp.x, fp.y, true)
@@ -310,7 +345,7 @@ class Popup extends HTMLElement {
const the_node = this.find_node(uid)
const graph_id = message.detail.graph_id
sound_maker.on_message(detail)
if (detail.audiopath) this.audiopath = detail.audiopath
if (graph_id != app.graph.id) {
this._flash_tab(graph_id)
@@ -323,6 +358,7 @@ class Popup extends HTMLElement {
if (this.node!=the_node) this.on_new_node(the_node)
if (detail.tick) {
this.sound_maker.request('tick')
this.counter_text.innerText = `${detail.tick}s`
if (this.state==State.INACTIVE) this.request_reset()
return
@@ -344,6 +380,7 @@ class Popup extends HTMLElement {
this.state = State.TINY
this.saved_message = message
this.tiny_image.src = get_full_url(message.detail.urls[message.detail.urls.length-1])
this.sound_maker.request('tiny')
return `Deferring message and showing small window`
}
@@ -352,6 +389,8 @@ class Popup extends HTMLElement {
this.n_extras = detail.extras ? message.detail.extras.length : 0
this.extras_row.innerHTML = ''
for (let i=0; i<this.n_extras; i++) { create('input', 'extra', this.extras_row, {value:detail.extras[i]}) }
if (!using_saved && !this.autosend()) this.sound_maker.request('open')
if (detail.maskedit) this.handle_maskedit(detail)
else if (detail.urls) this.handle_urls(detail)
+25 -69
View File
@@ -8,82 +8,38 @@ export function create( tag, clss, parent, properties ) {
return nd;
}
const default_audio_folder = 'extensions/cg-image-filter/audio/'
const default_audio_file = 'ding.mp3';
export class AudioHandler {
constructor() {
this.audiopath = default_audio_folder + default_audio_file
this.last_uid = undefined
this.next_allowed = Date.now()
export class CallbackThrottle {
constructor(callback, min_period) {
this.callback = callback
this.millisecs = min_period*1000
this.unreset()
}
on_message(detail) {
if (detail.audiopath) this.audiopath = detail.audiopath
const uid = app.runningNodeId
if (this.last_uid != uid) {
this.next_allowed = Date.now()
this.last_uid = uid
}
const ntw = this._need_to_wait()
this._log(`_request - need to wait ${ntw}`)
if (ntw <= 0) {
this._maybe_play_sound()
this._apply_delay()
}
}
on_execution_ended() {
this._log("Clear uid on execution ended")
this.last_uid = undefined
}
on_activity() { this._apply_delay() }
async _maybe_play_sound() {
if (app.ui.settings.getSettingValue("Image Filter.UI.Play Sound")) {
await this._try_to_play_sound(this.audiopath) ||
await this._try_to_play_sound(default_audio_folder + this.audiopath) ||
await this._try_to_play_sound(default_audio_folder + default_audio_file)
}
}
async _try_to_play_sound(path) {
if (!path) return false
try {
const resp = await fetch(path);
if (!resp.ok) return false
const blob = await resp.blob();
const blobUrl = URL.createObjectURL(new Blob([blob], { type: 'audio/mpeg' }));
const audio = new Audio(blobUrl);
await audio.play();
this.audiopath = path
return true
} catch (e) {
return false
}
}
_log(m) {
log(m) {
if ((app.ui.settings.getSettingValue("Image Filter.Z.Detailed Logging"))) console.log(m)
}
_apply_delay() {
var delay = app.ui.settings.getSettingValue("Image Filter.UI.Sound Timeout")
if (delay<=0) delay = 9999999
this.next_allowed = Date.now() + delay*1000
this._log(`_apply_delay - need to wait ${this._need_to_wait()}`)
reset(msg) {
this.next_allowed = Date.now() + this.millisecs
if (msg) this.log(`reset ${msg} - need to wait ${this.need_to_wait()}`)
}
_need_to_wait() {
return this.next_allowed - Date.now()
unreset(msg) {
this.next_allowed = Date.now()
if (msg) this.log(`unreset ${msg} - need to wait ${this.need_to_wait()}`)
}
}
need_to_wait() {
const ntw = this.next_allowed - Date.now()
return (ntw>0) ? ntw : 0
}
export const sound_maker = new AudioHandler()
document.addEventListener("click", ()=>sound_maker.on_activity.bind(sound_maker))
document.addEventListener("keypress", ()=>sound_maker.on_activity.bind(sound_maker))
request(msg) {
if (msg) this.log(`request ${msg} - need to wait ${this.need_to_wait()}`)
if (this.need_to_wait() <= 0) {
if (msg) this.log(`Callback ${msg}`)
this.callback()
this.reset('after callback')
}
}
}