community icon indicating copy to clipboard operation
community copied to clipboard

Closing the app after `Recorder` playback logs error

Open carstenfuchs opened this issue 5 years ago • 3 comments

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.

carstenfuchs avatar Sep 20 '20 08:09 carstenfuchs

Try using App.get_running_app().stop() instead of self.window.close().

pythonic64 avatar Oct 02 '20 14:10 pythonic64

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?

carstenfuchs avatar Oct 08 '20 08:10 carstenfuchs

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

ziriax avatar Oct 17 '24 15:10 ziriax