How to check if a modal timer is running

Hello,

In some of my add-ons I use a modal timer to read an input device or a socket. Fine, but is there a way to know if a modal timer is still “running” ? In some rare cases I noticed that the modal timer was interrupted and would need to check that with some code.

May be by accessing the return string (‘PASS_THROUGH’ , ‘RUNNING_MODAL’ or ‘CANCELLED’) of the various functions of the modal timer class ? But I don’t know how to do this.

Hi,

had a play around with this a while back. Basically you can use the same sort of method as the modal timer template which changes the 3d view bg colour… visually pretty obvious when it has stopped.

I also found you could do this… in this case I’ve tacked the timer onto the operator class and added a class method to return it. You can also set up your own class and make the timer an attribute of the class or an instance.

I’ve used the driver_namespace as it’s a simple way to get output to the console.


import bpy


class ModalTimerOperator(bpy.types.Operator):
    """Operator which runs its self from a timer"""
    bl_idname = "wm.modal_timer_operator"
    bl_label = "Modal Timer Operator"

    _timer = None

    @classmethod
    def running(cls, context):
        return (cls._timer)
    
    def modal(self, context, event):
        if event.type in {'RIGHTMOUSE', 'ESC'}:
            self.cancel(context)
            return {'CANCELLED'}

        if event.type == 'TIMER':
            # change theme color, silly!
            color = context.user_preferences.themes[0].view_3d.space.gradients.high_gradient
            color.s = 1.0
            color.h += 0.01

        return {'PASS_THROUGH'}

    def execute(self, context):
        print(type(self))
        wm = context.window_manager
        type(self)._timer = wm.event_timer_add(0.1, context.window)
        wm.modal_handler_add(self)
        return {'RUNNING_MODAL'}

    def cancel(self, context):
        wm = context.window_manager
        wm.event_timer_remove(type(self)._timer)


def register():
    bpy.app.driver_namespace['mto'] = ModalTimerOperator
    bpy.utils.register_class(ModalTimerOperator)


def unregister():
    bpy.utils.unregister_class(ModalTimerOperator)


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.wm.modal_timer_operator()


Console output. t.time_duration resets to 0 when the modal operator is stopped.


>>> c = bpy.app.driver_namespace['mto']
>>> t = c.running(C)
>>> t.time_duration
229.5037384033203

>>> t.time_duration
231.70159912109375

>>> t.time_duration
233.20436096191406

>>> t.time_duration
0.0