Ok so far it’s working, though I’m a bit nervous on running .clear() at the wrong time (not sure if I can attach an observer to an object) or replace itself (the notification instance .object())
import objc_util
import time
class NotificationObserver:
def __init__(self, name):
self.name = objc_util.ns(name)
self.center = objc_util.ObjCClass("NSNotificationCenter").defaultCenter()
self._observer = None
self._blk = None
self.queue = objc_util.ObjCClass('NSOperationQueue').new()
self.queue.setName_(objc_util.ns('test'))
self.clear()
def clear(self):
self.ni = None
self.ni_name = None
self.ni_obj = None
'''the objc block signature. do not modify'''
def _block(self, _cmd, notification):
try:
self.ni = objc_util.ObjCInstance(notification)
self.ni_name = self.ni.name()
self.ni_obj = self.ni.object()
except Exception as ex:
print(ex)
'''start observing'''
def start(self):
#print(time.asctime() + ' starting')
if self._observer:
raise Exception('observer already started')
self._blk = objc_util.ObjCBlock(self._block, restype=None, argtypes=[objc_util.c_void_p, objc_util.c_void_p])
self._observer = self.center.addObserverForName_object_queue_usingBlock_(self.name, None, self.queue, self._blk)
objc_util.retain_global(self)
def stop(self):
#print(time.asctime() + ' stopping')
if self._observer:
self.center.removeObserver_(self._observer)
self._observer = None
objc_util.release_global(self)
Using it within my script (a portion of it), it does work just as I originally wanted to (thanks again! @JonB)
from NotificationObserver import NotificationObserver
observer_names = {
"AVPlayerItemDidPlayToEndTimeNotification": "itemDidPlay"
}
for on in observer_names:
name = observer_names[on]
setattr(NotificationObserver, name, NotificationObserver(on))
getattr(NotificationObserver, name).start()
def app_active():
return not sa.applicationState() == 2 #1 skip
#return not sa.isSuspended() #1 skip
#return not sa._isResigningActive() #3 skips
def should_do_loop():
if keyboard.is_keyboard() or app_active():
return True
else:
return False
def looper(player):
while v.on_screen:
if not paused and not wait:
#if hasattr(player, "item_load_time") and player.player.rate() == 0.0 and should_do_loop():
pi = player.item
if pi and pi is NotificationObserver.itemDidPlay.ni_obj:
NotificationObserver.itemDidPlay.clear()
player.seek(secs=0)
player.player.play()
player.playCount += 1
if player.layer:
#console.hud_alert("vp.playCount = {}".format(player.playCount), duration=0.5)
pass
elif not inf:
#Audio player has looped -> next item
change_i_by_val(1)
update_i_change()
#console.hud_alert("ap.playCount = {}".format(player.playCount), duration=0.5)
pass
time.sleep(refresh_rate)
else:
time.sleep(refresh_rate_helper)