[solved] Please, explained about xbmc.Player() callbacks
#1
Hello!

I founded on this forum the thread where was the example of working with xbmc.Player() callbacks. So, after calling xbmc.Player().play, there is cycle with sleep. And only with this cycle the callbacks sometimes called.

After java and c# it is absolutely unlogic and I don't understand why player callbacks don't work without it.

Maybe there are some realization features, but I cannot develop my addon without this knowledges.

Can anybody explain this?

Thanks for help.

P.S. Similar situation is with onInit function of Window. It's never calling.
Reply
#2
(2017-09-21, 13:26)Rameron Wrote: Hello!

I founded on this forum the thread where was the example of working with xbmc.Player() callbacks. So, after calling xbmc.Player().play, there is cycle with sleep. And only with this cycle the callbacks sometimes called.

After java and c# it is absolutely unlogic and I don't understand why player callbacks don't work without it.

This has nothing do do with programming languages, especially considering the fact that Kodi Python API is in fact written in C++. Those are implementation specifics of Player class that do not depend on programming language at all. Any language would work the same.

Quote:Can anybody explain this?

A Python program (or C# or Java for that matter) is executed instruction by instruction, and after the last instruction in the current scope the runtime environment (a Python virtual machine, .NET CLR or whatever) garbage-collects all objects created within this scope (ideally). If an object has been created in the global (module) scope, it will be garbage-collected after the the last instruction in current script is completed. And after that the runtime environment itself is shut down. As far as I know, Python, Java and C# have similar concepts of scopes and object lifetime, so, as I said, this has nothing to do with the specific language.

The matter is that all methods of Player class are non-blocking, meaning that after each call the control is returned to the calling Python scripts which continue its execution until the last instruction:
Code:
import xbmc


class MyPlayer(xbmc.Player):
    def onPlayBackStopped(self):
        xbmc.log('Playback stopped')


player = MyPlayer()
player.play('/foo/bar.mp4')  # Non-blocking call that returns immedialtely.
# After play() execution is continued and after the last line the current script will end
# and player instance will be garbage-collected so onPlayBackStopped will never be called.

Since Player class does not have any event loop on its own, you need to implement your own loop that prevents the current Python script from exiting and keeps the player instance alive, preventing it from being garbage-collected by the runtime environment (a Python virtual machine in this case).

Hopefully, this will make things more clear for you.
Reply
#3
(2017-09-21, 15:31)Roman_V_M Wrote:
Code:
import xbmc


class MyPlayer(xbmc.Player):
    def onPlayBackStopped(self):
        xbmc.log('Playback stopped')


player = MyPlayer()
player.play('/foo/bar.mp4')  # Non-blocking call that returns immedialtely.
# After play() execution is continued and after the last line the current script will end
# and player instance will be garbage-collected so onPlayBackStopped will never be called.

But I don't use local variable for Player instance.
Code:
import xbmc
import xbmcgui

class VideosWindow(xbmcgui.Window):
    mediaPlayer = None
    
    def __init__(self):
        self.mediaPlayer = xbmc.Player()
        self.playTestVideo()
        
    def playTestVideo(self):
        self.mediaPlayer.play('/foo/bar.mp4')

What's wrong?
Reply
#4
(2017-09-21, 15:43)Rameron Wrote: What's wrong?

Show you full code. But generally the concept of object lifetime applies to class properties as well and they exist as long as their class instance is alive. If your VideosWindow instance does not enter its event loop (xbmcgui.Window class does have its event loop implemented in doModal() method), it will be garbage-collected with all its properties all the same after the VideosWindow instance goes out of scope.
Code:
import xbmc
import xbmcgui

class VideosWindow(xbmcgui.Window):
    mediaPlayer = None
    
    def __init__(self):
        self.mediaPlayer = xbmc.Player()
        self.playTestVideo()
        
    def playTestVideo(self):
        self.mediaPlayer.play('/foo/bar.mp4')

my_window = ViedeosWindow()
my_window.doModal()  # This call is blocking and your my_window instance with all its properties will live until you press BACK or ESC.
# If you close your window, my_widow instance with all its properties will be garbage-collected after it goes out of scope.
Reply
#5
(2017-09-21, 16:04)Roman_V_M Wrote: Show you full code. But generally the concept of object lifetime applies to class properties as well and they exist as long as their class instance is alive. If your VideosWindow instance does not enter its event loop (xbmcgui.Window class does have its event loop implemented in doModal() method), it will be garbage-collected with all its properties all the same after the VideosWindow instance goes out of scope.

I can not show you the whole code, since there are already about 1800 lines, but yes - I'm calling doModal for the window with video from the main window and the video window from this moment exists. And after running the video from this window and press on the backspace, there is a return to my video window in the same form, this window all this time exists and is not overloaded.

For this reason it is surprising for me that the player's calls do not work.
Reply
#6
(2017-09-22, 08:20)Rameron Wrote: I can not show you the whole code, since there are already about 1800 lines, but yes - I'm calling doModal for the window with video from the main window and the video window from this moment exists. And after running the video from this window and press on the backspace, there is a return to my video window in the same form, this window all this time exists and is not overloaded.

For this reason it is surprising for me that the player's calls do not work.

You can post a link to your Github/Gitlab/Bitbucket/whatever repo. As I said in PM, without full code it will be crystal ball reading, and it's better to check actual player instance lifetime under a debugger. I can suggest mine: https://github.com/romanvm/kodi.web-pdb Smile
Reply
#7
(2017-09-22, 09:34)Roman_V_M Wrote: You can post a link to your Github/Gitlab/Bitbucket/whatever repo. As I said in PM, without full code it will be crystal ball reading, and it's better to check actual player instance lifetime under a debugger. I can suggest mine: https://github.com/romanvm/kodi.web-pdb Smile

Wow, thanks for debugger! I've already changed the functionality of the add-on to avoid working with the player's calls.

I hope that I will deal with the problem.
Reply
#8
I solved my problem.

And I'm idiot.

It was my fail and my player class inherits xbmcgui.Window instead xbmc.Player. Of course, after fixing this "small" mistake my code started to work correctly.

Sorry..
Reply

Logout Mark Read Team Forum Stats Members Help
[solved] Please, explained about xbmc.Player() callbacks0