Topics

schedulers and speech status #addon


Venkatesh Potluri
 

Hi,

 

I am trying to add a scheduler to an NVDA addon and am using the sched module in python with the intent of making an event occur after specific intervals of time. To test the use of sched in an addon, here is some test code I am using. Note that I have excluded imports, etc. for brevity.

 

In my GlobalPlugin’s init method:

 

self.scheduler = sched.scheduler(time,sleep)

e1 = self.scheduler.enter(30,1,self.print_event, ('scheduled speak',self.scheduler))

self.scheduler.run()

 

and the self.print_event method:

def print_event(self,text,scheduler):

    self.scheduledEventCount = self.scheduledEventCount+1

    speech.cancelSpeech()

    ui.message(text)

    if self.scheduledEventCount <6:

        e1 = self.scheduler.enter(30,1,self.print_event, ('scheduled speak',self.scheduler))

 

 

This works with NVDA repeating the event for as long as the condition in the print_event satisfies, but makes the screen reader unresponsive.

 

I tried to move the scheduler to a different thread but it seems to no longer work. I don’t see any errors in the NVDA console as well. Here is how I moved it:

In the GlobalPlugin class:

def startAndRunScheduler(self):

    self.scheduler = sched.scheduler(time,sleep)

    e1 = self.scheduler.enter(30,1,self.print_event, ('scheduled speech',self.scheduler))

    self.scheduler.run()

 
in my init method of the global plugin:
def __init__(self):
    super(GlobalPlugin, self).__init__()
#more code
t = threading.Thread(target=self.startAndRunScheduler, daemon=True)

I also tried removing the
daemon=True but had no output.

What is the recommended way to add a scheduler into an addon?

 

On a related note, I am also interested to know if NVDA is speaking. Are there APIs that give information on if NVDA is speaking, and when NVDA is done speaking a particular string?


Thanks!
Best, Venkatesh


Larry Wang
 

NVDA has its own event loop, please use nvda built-in method core.callLater

https://github.com/nvaccess/nvda/blob/0098a31a7fb97919d6e55e8d0b2dd3bf62e8bc70/source/core.py#L629

在 2020/9/19 9:55, Venkatesh Potluri 写道:

Hi,

 

I am trying to add a scheduler to an NVDA addon and am using the sched module in python with the intent of making an event occur after specific intervals of time. To test the use of sched in an addon, here is some test code I am using. Note that I have excluded imports, etc. for brevity.

 

In my GlobalPlugin’s init method:

 

self.scheduler = sched.scheduler(time,sleep)

e1 = self.scheduler.enter(30,1,self.print_event, ('scheduled speak',self.scheduler))

self.scheduler.run()

 

and the self.print_event method:

def print_event(self,text,scheduler):

    self.scheduledEventCount = self.scheduledEventCount+1

    speech.cancelSpeech()

    ui.message(text)

    if self.scheduledEventCount <6:

        e1 = self.scheduler.enter(30,1,self.print_event, ('scheduled speak',self.scheduler))

 

 

This works with NVDA repeating the event for as long as the condition in the print_event satisfies, but makes the screen reader unresponsive.

 

I tried to move the scheduler to a different thread but it seems to no longer work. I don’t see any errors in the NVDA console as well. Here is how I moved it:

In the GlobalPlugin class:

def startAndRunScheduler(self):

    self.scheduler = sched.scheduler(time,sleep)

    e1 = self.scheduler.enter(30,1,self.print_event, ('scheduled speech',self.scheduler))

    self.scheduler.run()

 
in my init method of the global plugin:
def __init__(self):     super(GlobalPlugin, self).__init__() #more code t = threading.Thread(target=self.startAndRunScheduler, daemon=True) I also tried removing the daemon=True but had no output.

What is the recommended way to add a scheduler into an addon?

 

On a related note, I am also interested to know if NVDA is speaking. Are there APIs that give information on if NVDA is speaking, and when NVDA is done speaking a particular string?


Thanks!
Best, Venkatesh


Venkatesh Potluri
 

Thank you for pointing me to this!

The line 632 in the github page says: This function should never be used to execute code that brings up a modal UI as it will cause NVDA's core to block. while I understand that modal UIs shouldn't be displayed as NVDA will block, does this mean that operations that are scheduled using callLater block NVDA? Also, is there a way to cancel events that are scheduled to be called after a delay? I looked through all the methods in core but was not completely sure where the functionality to cancel scheduled events was.

Best, Venkatesh


Larry Wang
 

wx.CallLater is a wrapper around wx.Timer you can just retain return value and call Stop() to cancel it.

https://wxpython.org/Phoenix/docs/html/wx.CallLater.html#wx-calllater

For your second problem here is something useful

https://github.com/nvaccess/nvda/issues/5638#issuecomment-574758834


在 2020/9/19 20:31, Venkatesh Potluri 写道:

Thank you for pointing me to this!

The line 632 in the github page says: This function should never be used to execute code that brings up a modal UI as it will cause NVDA's core to block. while I understand that modal UIs shouldn't be displayed as NVDA will block, does this mean that operations that are scheduled using callLater block NVDA? Also, is there a way to cancel events that are scheduled to be called after a delay? I looked through all the methods in core but was not completely sure where the functionality to cancel scheduled events was.

Best, Venkatesh