Closing the app after `Recorder` playback logs error
Software Versions
- Python: 3.6.9
- OS: Ubuntu 18.04 LTS
- Kivy: 1.11.1
- Kivy installation method: pip
Describe the bug We are using the Recorder class to play back previously recorded input events. The intention is to automatically close the app after the playback has reached its end. However, whatever we do (minimal code to reproduce follows below), the log always ends with the these lines with errors:
[INFO ] [Recorder ] Playing finished.
[INFO ] [Recorder ] Stop playing '/tmp/test.events'
[ERROR ] [Base ] No event listeners have been created
[ERROR ] [Base ] Application will leave
[INFO ] [WindowSDL ] exiting mainloop and closing.
Expected behavior Clean exit of the app without errors.
To Reproduce This code is self-contained and reproduces the issue:
#!/usr/bin/env python3
import kivy
kivy.require('1.11.1')
from kivy.app import App
from kivy.clock import Clock
from kivy.input.recorder import Recorder
from kivy.uix.togglebutton import ToggleButton
class CustomPlayer(Recorder):
def on_play(self, instance, value):
super().on_play(instance, value)
if not value:
# The direct call triggers the error:
# self.window.close()
# The delayed call triggers the error, too. If however ESC is
# pressed before the delay has elapsed, the error does not occur.
Clock.schedule_once(lambda dt: self.window.close(), 3.0)
class MyApp(App):
"""An app with automatic playback of previously recorded input events."""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.player = CustomPlayer(filename="/tmp/test.events")
def build(self):
return ToggleButton(text='Hello')
def on_start(self):
super().on_start()
self.player.play = True
def on_stop(self):
super().on_stop()
self.player.play = False
print("on_stop()")
if __name__ == '__main__':
with open('/tmp/test.events', 'w') as f:
f.write("#RECORDER1.0\n")
f.write("(1.0, 'begin', 1, {'is_touch': True, 'sx': 0.22875, 'sy': 0.12, 'profile': ['pos']})\n")
f.write("(1.0, 'end', 1, {'is_touch': True, 'sx': 0.22875, 'sy': 0.12, 'profile': ['pos']})\n")
MyApp().run()
Code and Logs and screenshots End of log of the above example code:
[INFO ] [Recorder ] Playing finished.
[INFO ] [Recorder ] Stop playing '/tmp/test.events'
[ERROR ] [Base ] No event listeners have been created
[ERROR ] [Base ] Application will leave
[INFO ] [WindowSDL ] exiting mainloop and closing.
Try using App.get_running_app().stop() instead of self.window.close().
Thanks, that works, but seems to call MyApp.on_stop() twice. New log:
[INFO ] [Recorder ] Playing finished.
[INFO ] [Recorder ] Stop playing '/tmp/test.events'
on_stop()
[INFO ] [Base ] Leaving application in progress...
[INFO ] [WindowSDL ] exiting mainloop and closing.
on_stop()
(I left out the final on_stop() line at the bottom of the log in my above message, sorry. It's the same as in the new log. In the new log, the first on_stop() line following the "Stop playing '/tmp/test.events'" is new.)
I wonder if this is the resolution of this issue? Or is there something underlying that should eventually get fixed?
Isn't this a bug?
I think here
# don't loop if we don't have listeners !
if len(self.event_listeners) == 0:
Logger.error('Base: No event listeners have been created')
Logger.error('Base: Application will leave')
self.exit()
return False
the code is missing an not self.quit. and should be the following:
# don't loop if we don't have listeners !
if not self.quit and len(self.event_listeners) == 0:
Logger.error('Base: No event listeners have been created')
Logger.error('Base: Application will leave')
self.exit()
return False