RE: Help to set "UserRating" in a song using script - izprtxqkft - 2023-02-04
ah! i see, so ive come up against this before in umpteenth projects, youre tracking a song but then the song youre tracking changes before youve saved what you need for the last one
try some variation of this
set a "previousSong" variable and a "currentSong" variable
on initial play set currentSong
on saving save for previousSong then at the end of your save set previousSong to the value of currentSong
it gets tricky around the first time you do it because no save has occurred and therefor previousSong is empty
so, when you set currentSong (during initial play) if previousSong is empty also set previousSong to currentSong
and the rest should carry on through, the save function keeping previousSong updated from currentSong
inital play keeping currentSong set
see how this works for you
-------
EDIT:
i suppose theres another way
on initial play:
if songPlaying != currentSong
saveRating(currentSong)
currentSong=songPlaying
a lot simpler than the first, each with merit
RE: Help to set "UserRating" in a song using script - jbinkley60 - 2023-02-04
I concur with @jepsizofye on using two variables to track the song title, if you are trying to detect a change. You might again take a look at my autostop addon in the Kodi repo. Specifically look at the XBMCplayer class in the service.py file (lines 24-53). I set flags based upon playback conditions. The current playing file name could be anther variable. Then look at the playCount function (lines 25-51) in the common.py file. The flags are passed to this function on a periodic basis by the service.py file line 81.
The playCount function is where I assess the current state of playback to increment the playcounter which tracks how long something has been playing (similar to your userrating calculation) or reset to 0 based upon certain conditions. The match = 1, match = 2 etc. statements are simply there for debugging so I can see which conditional statement matched. The result of whether to increment the playcounter is then evaluated in the servie.py file (lines 83-106) on what t do, if anything give the returned value of plcount (i.e. playcount).
Maybe this will help.
Jeff
RE: Help to set "UserRating" in a song using script - sagrath - 2023-02-04
Good morning @jbinkley60 and @jepsizofye !!! (here in brazil is now 09:09 AM)
I will look to your code angin and trying to make. The real problems is:
I'm too noob yet hahahaha.
I can understand the logic, but I'm no so good in python, still learning to program, as this is my first program language (and to be honest, it's very cool!).
and another problem as that english is not my native language, as much as I know a lot of English, I still miss some natural nuances of the language, which helps to make things a little more complex hahahaha!
But i'm not give UP!!!
Brace yourselfs!! The winter is comming!!!
RE: Help to set "UserRating" in a song using script - jbinkley60 - 2023-02-04
(2023-02-04, 14:08)sagrath Wrote: Good morning @jbinkley60 and @jepsizofye !!! (here in brazil is now 09:09 AM)
I will look to your code angin and trying to make. The real problems is:
I'm too noob yet hahahaha.
I can understand the logic, but I'm no so good in python, still learning to program, as this is my first program language (and to be honest, it's very cool!).
and another problem as that english is not my native language, as much as I know a lot of English, I still miss some natural nuances of the language, which helps to make things a little more complex hahahaha!
But i'm not give UP!!!
Brace yourselfs!! The winter is comming!!!
Not to worry, we were all noobs at one time. I too ended up teaching myself Python and learning to program Kodi addons. I learned the most by studying other people's code and struggling through problems. I believe service addons tend to be a bit more difficult due to having to deal with the various events (i.e. Kodi callbacks, event timer lops etc..). Glad you aren't giving up. I am still learning more about Kodi addon programming everyday. I look back and some of my earlier code and chuckle. On occasion I will do some major rewriting. If progress gets too slow or difficult for you on this, I'll take a crack at some coding to get you past some hurdles.
Jeff
RE: Help to set "UserRating" in a song using script - izprtxqkft - 2023-02-04
yea what jeff said
i first learned python because i was translating someone elses python project to PHP to work server side on a webserver that didnt like python
its a grind, takes a lot of trial and error, but in the end as long as you learned something its worth it
RE: Help to set "UserRating" in a song using script - sagrath - 2023-02-05
(2023-02-04, 19:53)jbinkley60 Wrote: I too ended up teaching myself Python and learning to program Kodi addons.
Yeah, I'm in the same way!!!!
(2023-02-04, 20:00)jepsizofye Wrote: its a grind, takes a lot of trial and error, but in the end as long as you learned something its worth it
Yeah yeah!! I'm into this hahahaha
So guys, 13 hours and only a parcial progress (here in Brazil is 21:16 and very hot summer!)
Read, re-read, re-re-re-read documentation and code that @jbinkley60 suggests, lots os trial and error (in meantime I help my wife to cleanup the house), made some modifications (I've learn how to put some settings in addon settings, very cool!) , but cant find a logic to do a simple solution:
Need to find a way to save the new_rating vaue from line 66 or 68 in the skipped song, not in the next song
I manage to identify when the song is skipped, now if you skip the song, a notification you show up with the new song title.
BUT (there's aways a but!)
when the song is skipped, the value of the rating goes to the actual music, not the skipped music:
python:
import xbmc
import xbmcaddon
import json
import time
class Monitor(xbmc.Monitor):
def __init__(self):
self.is_library_song = False
pass
def status_check(self):
# perform monitor status check
pass
def onPlayBackStarted(self):
self.is_library_song = True
# When the song ends, either by user action, or when the song is
# the last in the playlist and the "repeat" function is disabled.
def onPlayBackStopped(self, new_rating, current_time):
if self.is_library_song and current_time > 5:
# Saving the new rating as the song stops.
xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "userrating":%d},"id":1}' % (song_id, new_rating))
xbmc.executebuiltin("Notification(%s, %s)" % (song_title, 'Final Rating: {}'.format(new_rating)))
current_song = ''
self.is_library_song = False
def calculate_rating(self, new_rating):
xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "userrating":%d},"id":1}' % (song_id, new_rating))
if song_rating == 0:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(song_title), 'Final rating 0: {}'.format(new_rating)))
else:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(song_title), 'Final rating P: {}'.format(new_rating)))
current_song =''
monitor = Monitor()
player = xbmc.Player()
calculated_rating = 0
new_rating = 0
current_time = 0
total_time = 0
# Variables to check song skipping
song_title = ''
current_song =''
while not monitor.abortRequested():
try:
while True:
if xbmc.Player().isPlayingAudio():
if not xbmc.getInfoLabel('MusicPlayer.Title') == '':
# Retrieve data from the currently playing song
song_title = xbmc.getInfoLabel('MusicPlayer.Title')
song_rating = xbmc.getInfoLabel('MusicPlayer.UserRating')
song_length = int(xbmc.Player().getTotalTime())
current_time = int(player.getTime())
song_parts = int(song_length / 11)
if song_rating == '':
song_rating = 0
else:
song_rating = int(song_rating)
if current_time > 0:
calculated_rating = int(current_time / song_parts)
if song_rating == 0 or song_rating == '':
new_rating = int(current_time/song_parts)
if song_rating > 0:
new_rating = int((song_rating + calculated_rating) / 2)
if current_song == '':
monitor.onPlayBackStarted()
current_song = song_title
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}')
song_details = json.loads(result)["result"]["item"]
song_id = song_details["id"]
song_time_left = (song_length - current_time)
# Resting only two seconds before the song finish.
if song_time_left <= 2:
monitor.calculate_rating(new_rating)
current_song = xbmc.getInfoLabel('MusicPlayer.Title')
# HERE NEED TO FIND A WAY TO SAVE THE NEW_RATING FROM LINE 66 OR 68
# IN THE SKIPPED SONG, NOT IN THE NEXT SONG
if song_time_left > 2 and current_song != song_title:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(current_song), 'Song Skipped'))
monitor.calculate_rating(new_rating)
current_song = xbmc.getInfoLabel('MusicPlayer.Title')
else:
monitor.onPlayBackStopped(new_rating, current_time)
monitor.status_check()
if monitor.waitForAbort(1):
break
except Exception as e:
xbmc.executebuiltin("Notification(%s, %s)" % ("An error occurred: ", e))
I think that I'm very close to find.
And i think the secret will be in passing the value of current_song to the JsonRPC... or I'm wrong?
RE: Help to set "UserRating" in a song using script - jbinkley60 - 2023-02-05
I think the answer may be to pass song_id (JSON database identifier for the skipped song) and song_title to the monitor.calculate_rating class method on line 95 like so:
python:
monitor.calculate_rating(new_rating, song_id, song_title)
Then modify the class method on lines 28-34 like so:
python:
def calculate_rating(self, new_rating, song_id, song_title):
xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "userrating":%d},"id":1}' % (song_id, new_rating))
if song_rating == 0:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(song_title), 'Final rating 0: {}'.format(new_rating)))
else:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(song_title), 'Final rating P: {}'.format(new_rating)))
current_song =''
This appears to be a scope variable issue I mentioned earlier.
Jeff
RE: Help to set "UserRating" in a song using script - izprtxqkft - 2023-02-05
reading someone elses code isnt very easy so stay with me
line 23 inside the monitor class actually saves the rating for "song_id"
line 80 sets "song_id" that is used on line 23 to save rating for the song
so, your save on 23 is happening after its set on line 80 which is causing it to save to the wrong id
it needs to save the rating for "song_id" before its set on line 80 so you have the rating for the last song
so, see if you can set "song_id" from onPlayBackStarted on line 15 instead
when you do that you can also set last_id
im trying to work out some code for you but ive never used an xbmc monitor so im not sure when onplaybackstarts fires
basically, onplaybackstart can do the 2 variables as suggested
python: def onPlayBackStarted(self):
self.is_library_song = True
#Setting song_id, probably can move the code block up here from lines 50-96 in your while statement
result = xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"Player.GetItem","params":{"playerid":0,"properties":["userrating"]},"id":1}')
song_details = json.loads(result)["result"]["item"]
song_id = song_details["id"]
if last_id!=0 and song_id!=last_id:
xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "userrating":%d},"id":1}' % (last_id, new_rating))
last_id=song_id
then you need to add "last_id=0" on line 45
(obviously thats rough and shouldnt be copy/pasted directly, just showing whats going on in my head)
RE: Help to set "UserRating" in a song using script - sagrath - 2023-02-05
(2023-02-05, 04:07)jepsizofye Wrote: but ive never used an xbmc monitor so im not sure when onplaybackstarts fires
Good morning!!! So, i'm not so familiar too with the monitor thing hahaha, but, I think that is fired when the playback starts, not the song or video itself, when the player starts. and it's fired just once until the player stops. if some song finish and the next one start, onPlayBackStarted() will not fired again, because it's already stared and the player no stopped yet.
for this reason I'm made:
python:
if current_song == '':
monitor.onPlayBackStarted()
current_song = song_title
because current_song it's set empty just when script starts with kodi, and then when playback stared the current song will be the actual song, when playbackstop the current song will be set empty again. When playback starts againg, the loop is restarted.
(2023-02-05, 03:50)jbinkley60 Wrote: This appears to be a scope variable issue I mentioned earlier.
Not yet
: I made some heavy tests here and this is the result:
the songs has this userratings:
Then I play "Reach - Wake Me Up" until it get the rating 2 and skipped. The rating 2 must be saved on "Reach - Wake Me Up" but:
the song reach (irony?) the rating 2:
Song skipped and the the next song playing (noted the orange color on "Soundgarden - Kickstand)
and the result:
The first song did not receive the rating, and the second one changed from 5 to 3. This change it's because the original rating from Kickstand was 5 and the plus 2 divided by 2 is equal to 3.5. then is set 3.
(2023-02-05, 04:07)jepsizofye Wrote: so, see if you can set "song_id" from onPlayBackStarted on line 15 instead
Then I test this suggestion, but as I mentioned in a start this post, onPlayBackStarted() is fired just once, so, if I move xbmc.executeJSONRPC to inside the function "def onPlayBackStarted(self):" the song_id will never be updated.
so... at least I have a very good sleep hahahaha.
And i wanna ask: My code? It's in good shape? The problem with living in a small town in the interior of Brazil is this... I don't know anyone here who knows python.... or who uses kodi....
EDIT:
I added the option to hide notification. Just keep the "Song Skipped". This will be completely remove when (if) the service has been completed:
python:
import xbmc
import xbmcaddon
import json
import time
addon = xbmcaddon.Addon()
addon_name = addon.getAddonInfo('name')
class Monitor(xbmc.Monitor):
def __init__(self):
self.is_library_song = False
pass
def status_check(self):
# perform monitor status check
pass
def onPlayBackStarted(self):
self.is_library_song = True
# When the song ends, either by user action, or when the song is
# the last in the playlist and the "repeat" function is disabled.
def onPlayBackStopped(self, new_rating, current_time):
if self.is_library_song and current_time > 5:
# Saving the new rating as the song stops.
xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "userrating":%d},"id":1}' % (song_id, new_rating))
if show_notification == 'true':
xbmc.executebuiltin("Notification(%s, %s)" % (addon_name, '{} rated to {}'.format(song_title, new_rating)))
current_song = ''
self.is_library_song = False
def calculate_rating(self, new_rating, song_id, song_title, last_id):
if last_id !=0 and song_id != last_id:
xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "userrating":%d},"id":1}' % (song_id, new_rating))
if show_notification == 'true':
if song_rating == 0:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % (addon_name, '{} rated to {}'.format(song_title, new_rating)))
else:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % (addon_name, '{} rated to {}'.format(song_title, new_rating)))
current_song = ''
last_id=song_id
monitor = Monitor()
player = xbmc.Player()
calculated_rating = 0
new_rating = 0
current_time = 0
total_time = 0
# Variables to check song skipping
song_title = ''
current_song = ''
last_id = ''
show_notification = ''
real_show_notification = ''
while not monitor.abortRequested():
try:
while True:
if xbmc.Player().isPlayingAudio():
if addon.getSetting("show_notification") == 'true':
show_notification = 'true'
else:
show_notification = 'false'
if addon.getSetting("real_show_notification") == 'true':
real_show_notification = 'true'
else:
real_show_notification = 'false'
if not xbmc.getInfoLabel('MusicPlayer.Title') == '':
# Retrieve data from the currently playing song
song_title = xbmc.getInfoLabel('MusicPlayer.Title')
song_rating = xbmc.getInfoLabel('MusicPlayer.UserRating')
song_length = int(xbmc.Player().getTotalTime())
current_time = int(player.getTime())
song_parts = int(song_length / 11)
if song_rating == '':
song_rating = 0
else:
song_rating = int(song_rating)
if current_time > 0:
calculated_rating = int(current_time / song_parts)
if song_rating == 0 or song_rating == '':
new_rating = int(current_time/song_parts)
if song_rating > 0:
new_rating = int((song_rating + calculated_rating) / 2)
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}')
song_details = json.loads(result)["result"]["item"]
song_id = song_details["id"]
if current_song == '':
monitor.onPlayBackStarted()
current_song = song_title
song_time_left = (song_length - current_time)
# Resting only two seconds before the song finish.
if song_time_left <= 2:
monitor.calculate_rating(new_rating, song_id, song_title, last_id)
current_song = xbmc.getInfoLabel('MusicPlayer.Title')
# HERE NEED TO FIND A WAY TO SAVE THE NEW_RATING FROM LINE 66 OR 68
# IN THE SKIPPED SONG, NOT IN THE NEXT SONG
if song_time_left > 2 and current_song != song_title:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(current_song), 'Song Skipped'))
monitor.calculate_rating(new_rating, song_id, song_title, last_id)
current_song = xbmc.getInfoLabel('MusicPlayer.Title')
if real_show_notification == 'true':
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % (addon_name, '{} rated to {}'.format(song_title, new_rating)))
else:
monitor.onPlayBackStopped(new_rating, current_time)
monitor.status_check()
if monitor.waitForAbort(1):
break
except Exception as e:
xbmc.executebuiltin("Notification(%s, %s)" % ("An error occurred: ", e))
The Kodi forum has an option to set "spoiler"?. Look at the size of this "walltext" hahahahaah.
RE: Help to set "UserRating" in a song using script - jbinkley60 - 2023-02-05
(2023-02-05, 15:21)sagrath Wrote: And i wanna ask: My code? It's in good shape? The problem with living in a small town in the interior of Brazil is this... I don't know anyone here who knows python.... or who uses kodi....
EDIT:
I added the option to hide notification. Just keep the "Song Skipped". This will be completely remove when (if) the service has been completed:
If you can post your latest code again I will take a crack at a fix when I get time. I have an idea but will need your latest code.
Thanks,
Jeff
RE: Help to set "UserRating" in a song using script - sagrath - 2023-02-05
This is the code before your last suggestiom, that I posted yesterday at 21:00.
It's this one or the one before?
python:
import xbmc
import xbmcaddon
import json
import time
class Monitor(xbmc.Monitor):
def __init__(self):
self.is_library_song = False
pass
def status_check(self):
# perform monitor status check
pass
def onPlayBackStarted(self):
self.is_library_song = True
# When the song ends, either by user action, or when the song is
# the last in the playlist and the "repeat" function is disabled.
def onPlayBackStopped(self, new_rating, current_time):
if self.is_library_song and current_time > 5:
# Saving the new rating as the song stops.
xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "userrating":%d},"id":1}' % (song_id, new_rating))
xbmc.executebuiltin("Notification(%s, %s)" % (song_title, 'Final Rating: {}'.format(new_rating)))
current_song = ''
self.is_library_song = False
def calculate_rating(self, new_rating):
xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "userrating":%d},"id":1}' % (song_id, new_rating))
if song_rating == 0:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(song_title), 'Final rating 0: {}'.format(new_rating)))
else:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(song_title), 'Final rating P: {}'.format(new_rating)))
current_song =''
monitor = Monitor()
player = xbmc.Player()
calculated_rating = 0
new_rating = 0
current_time = 0
total_time = 0
# Variables to check song skipping
song_title = ''
current_song =''
while not monitor.abortRequested():
try:
while True:
if xbmc.Player().isPlayingAudio():
if not xbmc.getInfoLabel('MusicPlayer.Title') == '':
# Retrieve data from the currently playing song
song_title = xbmc.getInfoLabel('MusicPlayer.Title')
song_rating = xbmc.getInfoLabel('MusicPlayer.UserRating')
song_length = int(xbmc.Player().getTotalTime())
current_time = int(player.getTime())
song_parts = int(song_length / 11)
if song_rating == '':
song_rating = 0
else:
song_rating = int(song_rating)
if current_time > 0:
calculated_rating = int(current_time / song_parts)
if song_rating == 0 or song_rating == '':
new_rating = int(current_time/song_parts)
if song_rating > 0:
new_rating = int((song_rating + calculated_rating) / 2)
if current_song == '':
monitor.onPlayBackStarted()
current_song = song_title
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}')
song_details = json.loads(result)["result"]["item"]
song_id = song_details["id"]
song_time_left = (song_length - current_time)
# Resting only two seconds before the song finish.
if song_time_left <= 2:
monitor.calculate_rating(new_rating)
current_song = xbmc.getInfoLabel('MusicPlayer.Title')
# HERE NEED TO FIND A WAY TO SAVE THE NEW_RATING FROM LINE 66 OR 68
# IN THE SKIPPED SONG, NOT IN THE NEXT SONG
if song_time_left > 2 and current_song != song_title:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(current_song), 'Song Skipped'))
monitor.calculate_rating(new_rating)
current_song = xbmc.getInfoLabel('MusicPlayer.Title')
else:
monitor.onPlayBackStopped(new_rating, current_time)
monitor.status_check()
if monitor.waitForAbort(1):
break
except Exception as e:
xbmc.executebuiltin("Notification(%s, %s)" % ("An error occurred: ", e))
RE: Help to set "UserRating" in a song using script - jbinkley60 - 2023-02-06
(2023-02-05, 18:30)sagrath Wrote: This is the code before your last suggestiom, that I posted yesterday at 21:00.
Thanks. I've started looking at this and have a question on how you are testing skipping. Specifically I am interested in how you are queuing up the list of music tracks you are playing ? Are you queuing an albums, doing a play from here, playing a playlist etc ? When you say skipping I presume you mean skipping / fast forwarding to the next item in the list (vs. skipping over an item in the list) or what do you mean by skipping ? My questions will help me reproduce what you are seeing.
Thanks,
Jeff
RE: Help to set "UserRating" in a song using script - sagrath - 2023-02-06
(2023-02-06, 13:20)jbinkley60 Wrote: When you say skipping I presume you mean skipping / fast forwarding to the next item in the list (vs. skipping over an item in the list) or what do you mean by skipping ?
Hello !! Good morning!
OK, let's go! ALL the ways you mentioned:
If the player is playing some music and:
A- The skip-forward key will be pressed (starting the next song in the list).
B- Browse the playlist and select a song.
C- Using context menu on an album, artist or song and select "play".
D- Start a song by pressing "enter" from anywhere, be it a playlist, or list of songs from the album, or from the "music" node.
Anyway, if the player is already playing, when changing the song, all of them count as a jump.
And that's not my choice, it's how Kodi itself handles a skip and a stop.
I did a lot of testing on that part these days.
See this super simplified code, here no calculation is being done, just showing when a song is started, skipped or stopped.
python:
import xbmc
import xbmcaddon
import json
import time
addon = xbmcaddon.Addon()
addon_name = addon.getAddonInfo('name')
class Monitor(xbmc.Monitor):
def __init__(self):
self.is_library_song = False
pass
def status_check(self):
# perform monitor status check
pass
def onPlayBackStarted(self):
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(song_title), 'Song Stared'))
self.is_library_song = True
def onPlayBackStopped(self, current_song):
if self.is_library_song:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(current_song), 'Song Stopped'))
current_song = ''
self.is_library_song = False
monitor = Monitor()
player = xbmc.Player()
current_song = ''
while not monitor.abortRequested():
try:
while True:
if xbmc.Player().isPlayingAudio():
song_title = xbmc.getInfoLabel('MusicPlayer.Title')
if current_song == '':
monitor.onPlayBackStarted()
current_song = xbmc.getInfoLabel('MusicPlayer.Title')
if current_song != song_title:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(current_song), 'Song Skipped'))
current_song = xbmc.getInfoLabel('MusicPlayer.Title')
else:
monitor.onPlayBackStopped(current_song)
monitor.status_check()
if monitor.waitForAbort(1):
break
except Exception as e:
xbmc.executebuiltin("Notification(%s, %s)" % ("An error occurred: ", e))
RE: Help to set "UserRating" in a song using script - jbinkley60 - 2023-02-06
Ok, if this is working the way you want, to detect a song change then all you need to do is match the song_id similar to the song title and when there is a change make sure you update the original song (not the current song_id) with the last calculated value.
Here's an update with some code and comments.
python:
import xbmc
import xbmcaddon
import json
import time
addon = xbmcaddon.Addon()
addon_name = addon.getAddonInfo('name')
class Monitor(xbmc.Monitor):
def __init__(self):
self.is_library_song = False
pass
def status_check(self):
# perform monitor status check
pass
def onPlayBackStarted(self):
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(song_title), 'Song Stared'))
self.is_library_song = True
def onPlayBackStopped(self, current_song):
if self.is_library_song:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(current_song), 'Song Stopped'))
current_song = ''
self.is_library_song = False
monitor = Monitor()
player = xbmc.Player()
current_song = ''
current_id = 0 # Add to match current song tracking
song_id = 0 # Add to match original song tracking
while not monitor.abortRequested():
try:
while True:
if xbmc.Player().isPlayingAudio():
song_title = xbmc.getInfoLabel('MusicPlayer.Title')
if current_song == '':
monitor.onPlayBackStarted()
current_song = xbmc.getInfoLabel('MusicPlayer.Title')
song_id = xbmc.getInfoLabel('MusicPlayer.DBID') # Get database Id of song
if current_song != song_title:
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(current_song), 'Song Skipped'))
current_song = xbmc.getInfoLabel('MusicPlayer.Title')
# Add line here to do skip calculation on song_id
current_id = xbmc.getInfoLabel('MusicPlayer.DBID') # Get database Id of new song
else:
monitor.onPlayBackStopped(current_song)
# Add line here to do final calculation on current_id
current_id = song_id = 0
monitor.status_check()
if monitor.waitForAbort(1):
break
except Exception as e:
xbmc.executebuiltin("Notification(%s, %s)" % ("An error occurred: ", e))
If the stripped down code isn't doing the proper detection of skips the way you want then I can look at it.
Thanks,
Jeff
RE: Help to set "UserRating" in a song using script - sagrath - 2023-02-06
(2023-02-06, 18:51)jbinkley60 Wrote: Here's an update with some code and comments.
YES!!!!!!!!!!!!!!!! yesyesyesyes!!!!!!!!!!!
THATS IT!!!!!!!!!!!!!!! @jbinkley60 you are a GENIOUS!!!!!!!!!!!!
It is working EXACTLY as I envisioned. The music starts, the calculations are executed and are only applied when the music changes or stops (either by user intervention or "naturally" when reaching the end).
And your last suggestion made me see where I was going wrong:
In the other codes, the song data was constantly being consulted, so the values were saved in the wrong song. With your suggestion I realized that the data should be consulted only once, and only be consulted again if the music changes. (actually I had thought about it before, but at some point I forgot lol).
Anyway: Here is the final code. now I'm going to apply the tweaks to hide the notifications and also to disable the addon (for those who don't want to "rank" their songs at some point).
python:
import xbmc
import xbmcaddon
import json
import time
addon = xbmcaddon.Addon()
addon_name = addon.getAddonInfo('name')
class Monitor(xbmc.Monitor):
def __init__(self):
self.is_library_song = False
pass
def status_check(self):
# perform monitor status check
pass
def onPlayBackStarted(self):
# Music Library music is set to "True"
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(song_title), 'Song Stared'))
self.is_library_song = True
def onPlayBackStopped(self, current_song, song_id, new_rating):
# The song stops, the UserRating of the song is saved, then song ID is set to "0",
# and currentMusic to "empty" again. Library music is set to "False"
if self.is_library_song:
xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "userrating":%d},"id":1}' % (song_id, new_rating))
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(current_song), 'Rated as: {}'.format(new_rating)))
current_song = ''
song_id = 0
self.is_library_song = False
monitor = Monitor()
player = xbmc.Player()
current_song = ''
new_rating = 0
current_id = 0 # Add to match current song tracking
song_id = 0 # Add to match original song tracking
while not monitor.abortRequested():
try:
while True:
if xbmc.Player().isPlayingAudio():
# Retrieve Song Data from the player
song_title = xbmc.getInfoLabel('MusicPlayer.Title')
song_rating = xbmc.getInfoLabel('MusicPlayer.UserRating')
song_length = int(xbmc.Player().getTotalTime())
current_time = int(player.getTime())
song_parts = int(song_length / 11)
song_time_left = (song_length - current_time)
# To to ensure UserRating is at least "0"
if song_rating == '':
song_rating = 0
else:
song_rating = int(song_rating)
# To avoid error "divided by zero"
if current_time > 0:
calculated_rating = int(current_time / song_parts)
if song_rating == 0 or song_rating == '':
new_rating = int(current_time/song_parts)
if song_rating > 0:
new_rating = int((song_rating + calculated_rating) / 2)
if current_song == '':
monitor.onPlayBackStarted()
# Retrieve Song Data as player start:
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}')
song_details = json.loads(result)["result"]["item"]
song_id = song_details["id"]
# Set current song from player:
current_song = xbmc.getInfoLabel('MusicPlayer.Title')
# If song has changed, first will save current data in previous song,
# The will retrieve data for the new song:
if current_song != song_title:
# Save Song Data in previous song:
xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"AudioLibrary.SetSongDetails","params":{"songid": %d, "userrating":%d},"id":1}' % (song_id, new_rating))
xbmc.executebuiltin("Notification(%s, %s, time=2000)" % ('{}'.format(current_song), 'Rated as: {}'.format(new_rating)))
# Retrieve Song Data from new 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}')
song_details = json.loads(result)["result"]["item"]
song_id = song_details["id"]
# Set new current song from player:
current_song = xbmc.getInfoLabel('MusicPlayer.Title')
else:
# For use when the user stops playback.
monitor.onPlayBackStopped(current_song, song_id, new_rating)
monitor.status_check()
if monitor.waitForAbort(1):
break
except Exception as e:
xbmc.executebuiltin("Notification(%s, %s)" % ("An error occurred: ", e))
Thanks too @jepsizofye pelo seu tempo! (edit: hahahah I type this in portuguese, it says "for your time")
You both help me to not give up in my first "Addon"
PS. This is not over yet, after including the settings, I'm planning to include a "album rating" in this code. Where the Album Rating will be calculated by averaging the notes of the songs. What you think?
|