Help to set "UserRating" in a song using script
#16
sagrath Wrote:It still broken... unfortunaly. The more strange is the rating tag work very well... bet the userrating no....

Ok. I'll look at it more when I get time and try to reproduce / fix. I know how to do it easily with direct database calls but Team Kodi frowns on that method.


Jeff
Running Kodi with the Mezzmo Kodi addon.  The easy way to share your media. | Service.autostop , CBC Sports and Mezzmo Kodi addon author
Reply
#17
(2023-01-26, 01:54)jbinkley60 Wrote:
sagrath Wrote:It still broken... unfortunaly. The more strange is the rating tag work very well... bet the userrating no....

Ok. I'll look at it more when I get time and try to reproduce / fix. I know how to do it easily with direct database calls but Team Kodi frowns on that method.


Jeff

Edit:

So my good friend @jbinkley60 , I've just realise that is no need to use the If statement "if player.onPlayBackEnded()... blablabla"
I've just realise now, because I'm in home and testing the script in my regular kodi, with a lot of songs (before I was using im my work pc) and just try these:

Code:

import xbmc
import xbmcaddon
import json

ADDON = xbmcaddon.Addon()
ADDON_PATH = ADDON.getAddonInfo('path')

monitor = xbmc.Monitor()
player = xbmc.Player()

plflag = calculated_rating = 0

while not monitor.abortRequested():    
    time_parts = 1    
    if player.isPlaying():
        # Get the properties of the currently playing item
        result = xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"Player.GetProperties","params":{"playerid":0, "properties":["type"]},"id":1}')
        media_type = json.loads(result)["result"]["type"]

        # Check if the media type is "audio"
        if media_type == "audio":
            plflag = 1
            # get all the needed times info from the song
            song = player.getMusicInfoTag()        
            song_length = song.getDuration()        
            time_parts = song_length / 11        
            current_time = player.getTime()
            
            # calculate the rating as the music is played
            calculated_rating = int(current_time/time_parts)
           
            # 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":["rating"]},"id":1}')
            song_details = json.loads(result)["result"]["item"]
            
            # Extract the song ID and rating
            song_id = song_details["id"]
            song_rating = song_details["rating"]
           
           if song_rating == 0:
                new_rating = calculated_rating
                xbmc.executebuiltin("Notification(%s, %s)" % ("Calculated Rating", new_rating))
                xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "rating":%f},"id":1}' % (song_id, new_rating))
            else:
                new_rating = int((song_rating + calculated_rating) / 2)
                new_rating = calculated_rating
                xbmc.executebuiltin("Notification(%s, %s)" % ("Calculated Rating", new_rating))
                xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "rating":%f},"id":1}' % (song_id, new_rating))
            
            #This notification is only to "see" the script working <-- THIS ONE WORKING
            xbmc.executebuiltin("Notification(%s, %s)" % ("Calculated Rating", new_rating))
            xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "rating":%f},"id":1}' % (song_id, new_rating))
   
monitor.waitForAbort(time_parts)

Although the option to update userrating is not working, I took advantage of updating the rating is working, and tested it that way. As you can see, I put a simple use of If to calculate the rating, and to my surprise, when I skipped a song and started the new one, the count restarted, and the new song started to update the rating. This also happened when the song ended and the next one started without my intervention. That is, the songs will have their rating updated in a simpler way.

I'm still struggling here trying to update userrating.

But anyway, your help is being of great value.

Thanks
Reply
#18
(2023-01-26, 02:00)sagrath Wrote: I'm still struggling here trying to update userrating.

I think I looked at this too long today and missed the obvious.  Try this change:

Original:

xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "userrating":%f},"id":1}' % (song_id, rating))


Modified:

xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "userrating":%d},"id":1}' % (song_id, rating))


You were trying to pass userrating with a %f which tells Python to pass it as a float vs. %d which is a decimal / integer.  %f is needed for rating, since that is a float type variable.

I think this will fix it.


Thanks,

Jeff
Running Kodi with the Mezzmo Kodi addon.  The easy way to share your media. | Service.autostop , CBC Sports and Mezzmo Kodi addon author
Reply
#19
(2023-01-26, 03:45)jbinkley60 Wrote: You were trying to pass userrating with a %f which tells Python to pass it as a float vs. %d which is a decimal / integer.  %f is needed for rating, since that is a float type variable.

That's it!!! it's working!!!

Now I'm going to make it more reliable. I will do more tests!! Thank you very much!!!!!
Reply
#20
(2023-01-26, 13:04)sagrath Wrote: That's it!!! it's working!!!

Now I'm going to make it more reliable. I will do more tests!! Thank you very much!!!!!

Good to hear.  I was bouncing yesterday between this and completing a major update for one of my addons and missed the obvious.


Thanks,

Jeff
Running Kodi with the Mezzmo Kodi addon.  The easy way to share your media. | Service.autostop , CBC Sports and Mezzmo Kodi addon author
Reply
#21
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.
Reply
#22
(Yesterday, 20:18)sagrath Wrote: 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.

You need to add a third state to library_song = False if you want to detect a true playback ended vs.  playback stopped or a different variable that is true and false.  Right now both set a single variable to False.  In my pause vs. play detector I have two variables (set to 0/1 or true /false)which equate to isPlaying or isPaused.  Thus I can look at both variables to determine the true state of playback..  Look at this code and you see paflag and plflag .  This addon detects paused, playing etc. 


Jeff
Running Kodi with the Mezzmo Kodi addon.  The easy way to share your media. | Service.autostop , CBC Sports and Mezzmo Kodi addon author
Reply



Logout Mark Read Team Forum Stats Members Help
Help to set "UserRating" in a song using script0
This forum uses Lukasz Tkacz MyBB addons.