Ok!! Some progress!!
I confess that I "stole" part of the codes of the various scripts that I have in my main Kodi, but I swear it was for a good cause.
But it helped me to create a better, more "Pythonic" framework.
I was able to build this structure:
Code:
import xbmc
import xbmcaddon
class Monitor(xbmc.Monitor):
def __init__(self):
self.is_library_song = False
def onPlayBackStarted(self):
self.is_library_song = True
xbmc.executebuiltin('Notification(Music Started, OK)')
def onPlayBackEnded(self):
if self.is_library_song:
xbmc.executebuiltin('Notification(Music Ended, OK)')
self.is_library_song = False
def onPlayBackStopped(self):
if self.is_library_song:
xbmc.executebuiltin('Notification(Music Stopped, OK)')
self.is_library_song = False
monitor = Monitor()
player = xbmc.Player()
while not monitor.abortRequested():
if xbmc.Player().isPlayingAudio():
# Song has Started
monitor.onPlayBackStarted()
else:
# Song has Stopped
monitor.onPlayBackStopped()
# Song has Ended
monitor.onPlayBackEnded()
xbmc.sleep(1000)
I made a whole class for the three commands: Start, Ended and Stopped. And within the While, the Calls for commands. And from there I got to this script:
Code:
import xbmc
import xbmcaddon
import json
class Monitor(xbmc.Monitor):
def __init__(self):
self.is_library_song = False
def onPlayBackStarted(self):
self.is_library_song = True
xbmc.executebuiltin('Notification(Music Started, OK)')
def onPlayBackEnded(self):
if self.is_library_song:
xbmc.executebuiltin('Notification(Music Ended, OK)')
self.is_library_song = False
def onPlayBackStopped(self):
if self.is_library_song:
# calculate the rating as the music is played
calculated_rating = int(current_time/song_parts)
# Check if the music is stopped before 5 seconds
if current_time > 5:
# If song has an original "zero" rating, the new rating will be the pure calculated rating
if song_rating == 0:
xbmc.executebuiltin("Notification(%s, %s)" % ("New 0 Rating", calculated_rating))
# If song already been rated, the new rating will be the original rating, plus the new rating and divided by 2.
elif song_rating != 0:
new_rating = (song_rating + calculated_rating) / 2
xbmc.executebuiltin("Notification(%s, %s)" % ("New Rating", new_rating))
self.is_library_song = False
# If the music is stopped before 5 seconds, no rating is calculated.
else:
xbmc.executebuiltin("Notification(%s, %s)" % ("Song Stopped", "{} is the rating".format(song_rating)))
self.is_library_song = False
monitor = Monitor()
player = xbmc.Player()
while not monitor.abortRequested():
if xbmc.Player().isPlayingAudio():
# Retrieve the currently playing song
xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"JSONRPC.Introspect","id":1}')
result = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "Player.GetItem", "params":{"playerid":0, "properties": ["userrating"]}, "id":1}')
# Extract the song ID, rating
song_details = json.loads(result)["result"]["item"]
song_id = song_details["id"]
song_rating = song_details["userrating"]
# get all the needed times info from the song
song = player.getMusicInfoTag()
song_title = song.getTitle()
song_length = song.getDuration()
song_parts = int(song_length / 11)
current_time = player.getTime()
# Song has Started
monitor.onPlayBackStarted()
else:
# Song has Stopped
monitor.onPlayBackStopped()
# Song has Ended
monitor.onPlayBackEnded()
xbmc.sleep(1000)
The code works just fine,
(almost) the way I envisioned it.
The music starts, and if it is stopped before 5 seconds, there will be no note update. after 5 seconds, the evaluation will happen after the user stops it.
I say "almost" because there is still no way to identify when the song ends without the player stopping (and thus starting the next one in the playlist or when it skips to the next or previous one), and the evaluation takes place.
Any guidance?
By the way:
What is the difference between
"onPlayBackStopped" and
"onPlayBackEnded"? At first I thought that Stopped would stop when the user pressed the stop button, and Ended when the song ended by itself, but in both cases only the
def onPlayBackStopped(self): is executed. I got confused.