mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-11-10 04:06:11 +00:00
add support for embedded covertart in music files
fix typo in music tags code
This commit is contained in:
parent
eab0b7d3d9
commit
3421bf88e1
4 changed files with 31 additions and 15 deletions
|
@ -20,7 +20,7 @@
|
||||||
<item>
|
<item>
|
||||||
<label>30401</label>
|
<label>30401</label>
|
||||||
<description>Settings for the Emby Server</description>
|
<description>Settings for the Emby Server</description>
|
||||||
<visible>[!IsEmpty(ListItem.DBID) + !IsEmpty(ListItem.DBTYPE)] | !IsEmpty(ListItem.Property(embyid))</visible>
|
<visible>[!IsEmpty(ListItem.DBID) + !StringCompare(ListItem.DBID,-1)] | !IsEmpty(ListItem.Property(embyid))</visible>
|
||||||
</item>
|
</item>
|
||||||
</extension>
|
</extension>
|
||||||
<extension point="xbmc.addon.metadata">
|
<extension point="xbmc.addon.metadata">
|
||||||
|
|
|
@ -272,7 +272,6 @@
|
||||||
<string id="30406">Remove from Emby favorites</string>
|
<string id="30406">Remove from Emby favorites</string>
|
||||||
<string id="30407">Set custom song rating</string>
|
<string id="30407">Set custom song rating</string>
|
||||||
<string id="30408">Emby addon settings</string>
|
<string id="30408">Emby addon settings</string>
|
||||||
<string id="30409">Delete item from the server</string>
|
<string id="30409">Delete item from the server</string>
|
||||||
|
|
||||||
|
|
||||||
</strings>
|
</strings>
|
||||||
|
|
|
@ -1954,7 +1954,7 @@ class Music(Items):
|
||||||
|
|
||||||
#if enabled, try to get the rating and comment value from the file itself
|
#if enabled, try to get the rating and comment value from the file itself
|
||||||
if not self.directstream:
|
if not self.directstream:
|
||||||
rating, comment = self.getSongRatingAndComment(itemid, rating, API)
|
rating, comment, hasEmbeddedCover = self.getSongTagsFromFile(itemid, rating, API)
|
||||||
|
|
||||||
##### GET THE FILE AND PATH #####
|
##### GET THE FILE AND PATH #####
|
||||||
if self.directstream:
|
if self.directstream:
|
||||||
|
@ -2158,7 +2158,10 @@ class Music(Items):
|
||||||
# Add genres
|
# Add genres
|
||||||
kodi_db.addMusicGenres(songid, genres, "song")
|
kodi_db.addMusicGenres(songid, genres, "song")
|
||||||
# Update artwork
|
# Update artwork
|
||||||
artwork.addArtwork(artwork.getAllArtwork(item, parentInfo=True), songid, "song", kodicursor)
|
allart = artwork.getAllArtwork(item, parentInfo=True)
|
||||||
|
if hasEmbeddedCover:
|
||||||
|
allart["Primary"] = "image://music@" + artwork.single_urlencode( playurl )
|
||||||
|
artwork.addArtwork(allart, songid, "song", kodicursor)
|
||||||
|
|
||||||
def updateUserdata(self, item):
|
def updateUserdata(self, item):
|
||||||
# This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
|
# This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
|
||||||
|
@ -2188,7 +2191,7 @@ class Music(Items):
|
||||||
# Process playstates
|
# Process playstates
|
||||||
playcount = userdata['PlayCount']
|
playcount = userdata['PlayCount']
|
||||||
dateplayed = userdata['LastPlayedDate']
|
dateplayed = userdata['LastPlayedDate']
|
||||||
rating, comment = self.getSongRatingAndComment(itemid, rating, API)
|
rating, comment, hasEmbeddedCover = self.getSongTagsFromFile(itemid, rating, API)
|
||||||
|
|
||||||
query = "UPDATE song SET iTimesPlayed = ?, lastplayed = ?, rating = ? WHERE idSong = ?"
|
query = "UPDATE song SET iTimesPlayed = ?, lastplayed = ?, rating = ? WHERE idSong = ?"
|
||||||
kodicursor.execute(query, (playcount, dateplayed, rating, kodiid))
|
kodicursor.execute(query, (playcount, dateplayed, rating, kodiid))
|
||||||
|
@ -2200,7 +2203,7 @@ class Music(Items):
|
||||||
|
|
||||||
emby_db.updateReference(itemid, checksum)
|
emby_db.updateReference(itemid, checksum)
|
||||||
|
|
||||||
def getSongRatingAndComment(self, embyid, emby_rating, API):
|
def getSongTagsFromFile(self, embyid, emby_rating, API):
|
||||||
|
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
|
|
||||||
|
@ -2211,7 +2214,7 @@ class Music(Items):
|
||||||
|
|
||||||
#get file rating and comment tag from file itself.
|
#get file rating and comment tag from file itself.
|
||||||
#TODO: should we make this an optional setting if it impacts sync speed too much ?
|
#TODO: should we make this an optional setting if it impacts sync speed too much ?
|
||||||
file_rating, comment = musicutils.getSongTags(filename)
|
file_rating, comment, hasEmbeddedCover = musicutils.getSongTags(filename)
|
||||||
|
|
||||||
emby_dbitem = self.emby_db.getItem_byId(embyid)
|
emby_dbitem = self.emby_db.getItem_byId(embyid)
|
||||||
try:
|
try:
|
||||||
|
@ -2232,7 +2235,7 @@ class Music(Items):
|
||||||
elif file_rating is None and not currentvalue:
|
elif file_rating is None and not currentvalue:
|
||||||
return (emby_rating, comment)
|
return (emby_rating, comment)
|
||||||
|
|
||||||
self.logMsg("getSongRatingAndComment --> embyid: %s - emby_rating: %s - file_rating: %s - current rating in kodidb: %s" %(embyid, emby_rating, file_rating, currentvalue))
|
self.logMsg("getSongTagsFromFile --> embyid: %s - emby_rating: %s - file_rating: %s - current rating in kodidb: %s" %(embyid, emby_rating, file_rating, currentvalue))
|
||||||
|
|
||||||
updateFileRating = False
|
updateFileRating = False
|
||||||
updateEmbyRating = False
|
updateEmbyRating = False
|
||||||
|
@ -2281,7 +2284,7 @@ class Music(Items):
|
||||||
like, favourite, deletelike = musicutils.getEmbyRatingFromKodiRating(rating)
|
like, favourite, deletelike = musicutils.getEmbyRatingFromKodiRating(rating)
|
||||||
API.updateUserRating(embyid, like, favourite, deletelike)
|
API.updateUserRating(embyid, like, favourite, deletelike)
|
||||||
|
|
||||||
return (rating, comment)
|
return (rating, comment, hasEmbeddedCover)
|
||||||
|
|
||||||
def remove(self, itemid):
|
def remove(self, itemid):
|
||||||
# Remove kodiid, fileid, pathid, emby reference
|
# Remove kodiid, fileid, pathid, emby reference
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
import os
|
import os
|
||||||
import xbmc, xbmcaddon, xbmcvfs
|
import xbmc, xbmcaddon, xbmcvfs
|
||||||
import utils
|
import utils
|
||||||
from mutagen.flac import FLAC
|
from mutagen.flac import FLAC, Picture
|
||||||
from mutagen.id3 import ID3
|
from mutagen.id3 import ID3
|
||||||
from mutagen import id3
|
from mutagen import id3
|
||||||
|
import base64
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
|
@ -28,7 +29,7 @@ def getRealFileName(filename):
|
||||||
if os.path.supports_unicode_filenames:
|
if os.path.supports_unicode_filenames:
|
||||||
checkfile = filename
|
checkfile = filename
|
||||||
else:
|
else:
|
||||||
checkfile = file.encode("utf-8")
|
checkfile = filename.encode("utf-8")
|
||||||
|
|
||||||
# determine if our python module is able to access the file directly...
|
# determine if our python module is able to access the file directly...
|
||||||
if os.path.exists(checkfile):
|
if os.path.exists(checkfile):
|
||||||
|
@ -65,21 +66,34 @@ def getSongTags(file):
|
||||||
# Get the actual ID3 tags for music songs as the server is lacking that info
|
# Get the actual ID3 tags for music songs as the server is lacking that info
|
||||||
rating = 0
|
rating = 0
|
||||||
comment = ""
|
comment = ""
|
||||||
|
hasEmbeddedCover = False
|
||||||
|
|
||||||
isTemp,filename = getRealFileName(file)
|
isTemp,filename = getRealFileName(file)
|
||||||
logMsg( "getting song ID3 tags for " + filename)
|
logMsg( "getting song ID3 tags for " + filename,0)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
###### FLAC FILES #############
|
||||||
if filename.lower().endswith(".flac"):
|
if filename.lower().endswith(".flac"):
|
||||||
audio = FLAC(filename)
|
audio = FLAC(filename)
|
||||||
if audio.get("comment"):
|
if audio.get("comment"):
|
||||||
comment = audio.get("comment")[0]
|
comment = audio.get("comment")[0]
|
||||||
|
for pic in audio.pictures:
|
||||||
|
if pic.type == 3 and pic.data:
|
||||||
|
#the file has an embedded cover
|
||||||
|
hasEmbeddedCover = True
|
||||||
if audio.get("rating"):
|
if audio.get("rating"):
|
||||||
rating = float(audio.get("rating")[0])
|
rating = float(audio.get("rating")[0])
|
||||||
#flac rating is 0-100 and needs to be converted to 0-5 range
|
#flac rating is 0-100 and needs to be converted to 0-5 range
|
||||||
if rating > 5: rating = (rating / 100) * 5
|
if rating > 5: rating = (rating / 100) * 5
|
||||||
|
|
||||||
|
###### MP3 FILES #############
|
||||||
elif filename.lower().endswith(".mp3"):
|
elif filename.lower().endswith(".mp3"):
|
||||||
audio = ID3(filename)
|
audio = ID3(filename)
|
||||||
|
|
||||||
|
if audio.get("APIC:Front Cover"):
|
||||||
|
if audio.get("APIC:Front Cover").data:
|
||||||
|
hasEmbeddedCover = True
|
||||||
|
|
||||||
if audio.get("comment"):
|
if audio.get("comment"):
|
||||||
comment = audio.get("comment")[0]
|
comment = audio.get("comment")[0]
|
||||||
if audio.get("POPM:Windows Media Player 9 Series"):
|
if audio.get("POPM:Windows Media Player 9 Series"):
|
||||||
|
@ -96,12 +110,12 @@ def getSongTags(file):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
#file in use ?
|
#file in use ?
|
||||||
logMsg("Exception in getSongTags %s" %e,0)
|
logMsg("Exception in getSongTags %s" %e,0)
|
||||||
return (None,"")
|
rating = None
|
||||||
|
|
||||||
#remove tempfile if needed....
|
#remove tempfile if needed....
|
||||||
if isTemp: xbmcvfs.delete(filename)
|
if isTemp: xbmcvfs.delete(filename)
|
||||||
|
|
||||||
return (rating, comment)
|
return (rating, comment, hasEmbeddedCover)
|
||||||
|
|
||||||
def updateRatingToFile(rating, file):
|
def updateRatingToFile(rating, file):
|
||||||
#update the rating from Emby to the file
|
#update the rating from Emby to the file
|
||||||
|
|
Loading…
Reference in a new issue