Cleanup music sync code
This commit is contained in:
parent
aafba74ccd
commit
e10d92cecb
3 changed files with 456 additions and 352 deletions
|
@ -15,7 +15,7 @@ LOG = getLogger('PLEX.music')
|
||||||
class MusicMixin(object):
|
class MusicMixin(object):
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
"""
|
"""
|
||||||
Open DB connections and cursors
|
Overwrite to use the Kodi music DB instead of the video DB
|
||||||
"""
|
"""
|
||||||
self.plexconn = utils.kodi_sql('plex')
|
self.plexconn = utils.kodi_sql('plex')
|
||||||
self.plexcursor = self.plexconn.cursor()
|
self.plexcursor = self.plexconn.cursor()
|
||||||
|
@ -91,25 +91,14 @@ class MusicMixin(object):
|
||||||
Remove song, orphaned artists and orphaned paths
|
Remove song, orphaned artists and orphaned paths
|
||||||
"""
|
"""
|
||||||
if not path_id:
|
if not path_id:
|
||||||
query = 'SELECT idPath FROM song WHERE idSong = ? LIMIT 1'
|
path_id = self.kodidb.path_id_from_song(kodi_id)
|
||||||
self.kodicursor.execute(query, (kodi_id, ))
|
|
||||||
try:
|
|
||||||
path_id = self.kodicursor.fetchone()[0]
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
self.kodidb.delete_song_from_song_artist(kodi_id)
|
self.kodidb.delete_song_from_song_artist(kodi_id)
|
||||||
self.kodicursor.execute('DELETE FROM song WHERE idSong = ?',
|
self.kodidb.remove_song(kodi_id)
|
||||||
(kodi_id, ))
|
|
||||||
# Check whether we have orphaned path entries
|
# Check whether we have orphaned path entries
|
||||||
query = 'SELECT idPath FROM song WHERE idPath = ? LIMIT 1'
|
if not self.kodidb.path_id_from_song(kodi_id):
|
||||||
self.kodicursor.execute(query, (path_id, ))
|
self.kodidb.remove_path(path_id)
|
||||||
if not self.kodicursor.fetchone():
|
|
||||||
self.kodicursor.execute('DELETE FROM path WHERE idPath = ?',
|
|
||||||
(path_id, ))
|
|
||||||
if v.KODIVERSION < 18:
|
if v.KODIVERSION < 18:
|
||||||
self.kodidb.delete_song_from_song_genre(kodi_id)
|
self.kodidb.remove_albuminfosong(kodi_id)
|
||||||
query = 'DELETE FROM albuminfosong WHERE idAlbumInfoSong = ?'
|
|
||||||
self.kodicursor.execute(query, (kodi_id, ))
|
|
||||||
self.kodidb.delete_artwork(kodi_id, v.KODI_TYPE_SONG)
|
self.kodidb.delete_artwork(kodi_id, v.KODI_TYPE_SONG)
|
||||||
|
|
||||||
def remove_album(self, kodi_id):
|
def remove_album(self, kodi_id):
|
||||||
|
@ -119,26 +108,14 @@ class MusicMixin(object):
|
||||||
self.kodidb.delete_album_from_discography(kodi_id)
|
self.kodidb.delete_album_from_discography(kodi_id)
|
||||||
if v.KODIVERSION < 18:
|
if v.KODIVERSION < 18:
|
||||||
self.kodidb.delete_album_from_album_genre(kodi_id)
|
self.kodidb.delete_album_from_album_genre(kodi_id)
|
||||||
query = 'DELETE FROM albuminfosong WHERE idAlbumInfo = ?'
|
self.kodidb.remove_album(kodi_id)
|
||||||
self.kodicursor.execute(query, (kodi_id, ))
|
|
||||||
self.kodicursor.execute('DELETE FROM album_artist WHERE idAlbum = ?',
|
|
||||||
(kodi_id, ))
|
|
||||||
self.kodicursor.execute('DELETE FROM album WHERE idAlbum = ?',
|
|
||||||
(kodi_id, ))
|
|
||||||
self.kodidb.delete_artwork(kodi_id, v.KODI_TYPE_ALBUM)
|
self.kodidb.delete_artwork(kodi_id, v.KODI_TYPE_ALBUM)
|
||||||
|
|
||||||
def remove_artist(self, kodi_id):
|
def remove_artist(self, kodi_id):
|
||||||
'''
|
'''
|
||||||
Remove an artist and associated songs and albums
|
Remove an artist and associated songs and albums
|
||||||
'''
|
'''
|
||||||
self.kodicursor.execute('DELETE FROM album_artist WHERE idArtist = ?',
|
self.remove_artist(kodi_id)
|
||||||
(kodi_id, ))
|
|
||||||
self.kodicursor.execute('DELETE FROM artist WHERE idArtist = ?',
|
|
||||||
(kodi_id, ))
|
|
||||||
self.kodicursor.execute('DELETE FROM song_artist WHERE idArtist = ?',
|
|
||||||
(kodi_id, ))
|
|
||||||
self.kodicursor.execute('DELETE FROM discography WHERE idArtist = ?',
|
|
||||||
(kodi_id, ))
|
|
||||||
self.kodidb.delete_artwork(kodi_id, v.KODI_TYPE_ARTIST)
|
self.kodidb.delete_artwork(kodi_id, v.KODI_TYPE_ARTIST)
|
||||||
|
|
||||||
|
|
||||||
|
@ -189,23 +166,12 @@ class Artist(MusicMixin, ItemBase):
|
||||||
# artist entries.
|
# artist entries.
|
||||||
kodi_id = self.kodidb.add_artist(api.title(), musicBrainzId)
|
kodi_id = self.kodidb.add_artist(api.title(), musicBrainzId)
|
||||||
# Create the reference in plex table
|
# Create the reference in plex table
|
||||||
query = '''
|
self.kodidb.update_artist(api.list_to_string(api.genre_list()),
|
||||||
UPDATE artist
|
|
||||||
SET strGenres = ?,
|
|
||||||
strBiography = ?,
|
|
||||||
strImage = ?,
|
|
||||||
strFanart = ?,
|
|
||||||
lastScraped = ?
|
|
||||||
WHERE idArtist = ?
|
|
||||||
'''
|
|
||||||
self.kodicursor.execute(
|
|
||||||
query,
|
|
||||||
(api.list_to_string(api.genre_list()),
|
|
||||||
api.plot(),
|
api.plot(),
|
||||||
thumb,
|
thumb,
|
||||||
fanart,
|
fanart,
|
||||||
utils.unix_date_to_kodi(self.last_sync),
|
utils.unix_date_to_kodi(self.last_sync),
|
||||||
kodi_id))
|
kodi_id)
|
||||||
# Update artwork
|
# Update artwork
|
||||||
self.kodidb.modify_artwork(artworks,
|
self.kodidb.modify_artwork(artworks,
|
||||||
kodi_id,
|
kodi_id,
|
||||||
|
@ -265,8 +231,8 @@ class Album(MusicMixin, ItemBase):
|
||||||
break
|
break
|
||||||
name = api.title()
|
name = api.title()
|
||||||
userdata = api.userdata()
|
userdata = api.userdata()
|
||||||
# Not yet implemented by Plex
|
# Not yet implemented by Plex, let's use unique last.fm or gracenote
|
||||||
musicBrainzId = None
|
musicBrainzId = api.guid_html_escaped()
|
||||||
genres = api.genre_list()
|
genres = api.genre_list()
|
||||||
genre = api.list_to_string(genres)
|
genre = api.list_to_string(genres)
|
||||||
# Associate artwork
|
# Associate artwork
|
||||||
|
@ -279,89 +245,68 @@ class Album(MusicMixin, ItemBase):
|
||||||
# UPDATE THE ALBUM #####
|
# UPDATE THE ALBUM #####
|
||||||
if update_item:
|
if update_item:
|
||||||
LOG.info("UPDATE album plex_id: %s - Name: %s", plex_id, name)
|
LOG.info("UPDATE album plex_id: %s - Name: %s", plex_id, name)
|
||||||
|
if v.KODIVERSION >= 18:
|
||||||
|
self.kodidb.update_album(name,
|
||||||
|
musicBrainzId,
|
||||||
|
api.artist_name(),
|
||||||
|
genre,
|
||||||
|
api.year(),
|
||||||
|
compilation,
|
||||||
|
api.plot(),
|
||||||
|
thumb,
|
||||||
|
api.music_studio(),
|
||||||
|
userdata['UserRating'],
|
||||||
|
utils.unix_date_to_kodi(self.last_sync),
|
||||||
|
'album',
|
||||||
|
kodi_id)
|
||||||
|
else:
|
||||||
|
self.kodidb.update_album_17(name,
|
||||||
|
musicBrainzId,
|
||||||
|
api.artist_name(),
|
||||||
|
genre,
|
||||||
|
api.year(),
|
||||||
|
compilation,
|
||||||
|
api.plot(),
|
||||||
|
thumb,
|
||||||
|
api.music_studio(),
|
||||||
|
userdata['UserRating'],
|
||||||
|
utils.unix_date_to_kodi(self.last_sync),
|
||||||
|
'album',
|
||||||
|
kodi_id)
|
||||||
# OR ADD THE ALBUM #####
|
# OR ADD THE ALBUM #####
|
||||||
else:
|
else:
|
||||||
LOG.info("ADD album plex_id: %s - Name: %s", plex_id, name)
|
LOG.info("ADD album plex_id: %s - Name: %s", plex_id, name)
|
||||||
kodi_id = self.kodidb.add_album(name, musicBrainzId)
|
kodi_id = self.kodidb.new_album_id()
|
||||||
# Process the album info
|
|
||||||
if v.KODIVERSION >= 18:
|
if v.KODIVERSION >= 18:
|
||||||
# Kodi Leia
|
self.kodidb.add_album(kodi_id,
|
||||||
query = '''
|
name,
|
||||||
UPDATE album
|
musicBrainzId,
|
||||||
SET strArtistDisp = ?,
|
api.artist_name(),
|
||||||
iYear = ?,
|
|
||||||
strGenres = ?,
|
|
||||||
strReview = ?,
|
|
||||||
strImage = ?,
|
|
||||||
iUserrating = ?,
|
|
||||||
lastScraped = ?,
|
|
||||||
strReleaseType = ?,
|
|
||||||
strLabel = ?,
|
|
||||||
bCompilation = ?
|
|
||||||
WHERE idAlbum = ?
|
|
||||||
'''
|
|
||||||
self.kodicursor.execute(
|
|
||||||
query,
|
|
||||||
(api.artist_name(),
|
|
||||||
api.year(),
|
|
||||||
genre,
|
genre,
|
||||||
|
api.year(),
|
||||||
|
compilation,
|
||||||
api.plot(),
|
api.plot(),
|
||||||
thumb,
|
thumb,
|
||||||
|
api.music_studio(),
|
||||||
userdata['UserRating'],
|
userdata['UserRating'],
|
||||||
utils.unix_date_to_kodi(self.last_sync),
|
utils.unix_date_to_kodi(self.last_sync),
|
||||||
v.KODI_TYPE_ALBUM,
|
'album')
|
||||||
api.music_studio(),
|
|
||||||
compilation,
|
|
||||||
kodi_id))
|
|
||||||
else:
|
else:
|
||||||
# Kodi Krypton
|
self.kodidb.add_album_17(kodi_id,
|
||||||
query = '''
|
name,
|
||||||
UPDATE album
|
musicBrainzId,
|
||||||
SET strArtists = ?,
|
api.artist_name(),
|
||||||
iYear = ?,
|
|
||||||
strGenres = ?,
|
|
||||||
strReview = ?,
|
|
||||||
strImage = ?,
|
|
||||||
iUserrating = ?,
|
|
||||||
lastScraped = ?,
|
|
||||||
strReleaseType = ?,
|
|
||||||
strLabel = ?,
|
|
||||||
bCompilation = ?
|
|
||||||
WHERE idAlbum = ?
|
|
||||||
'''
|
|
||||||
self.kodicursor.execute(
|
|
||||||
query,
|
|
||||||
(api.artist_name(),
|
|
||||||
api.year(),
|
|
||||||
genre,
|
genre,
|
||||||
|
api.year(),
|
||||||
|
compilation,
|
||||||
api.plot(),
|
api.plot(),
|
||||||
thumb,
|
thumb,
|
||||||
|
api.music_studio(),
|
||||||
userdata['UserRating'],
|
userdata['UserRating'],
|
||||||
utils.unix_date_to_kodi(self.last_sync),
|
utils.unix_date_to_kodi(self.last_sync),
|
||||||
v.KODI_TYPE_ALBUM,
|
'album')
|
||||||
api.music_studio(),
|
self.kodidb.add_albumartist(artist_id, kodi_id, api.artist_name())
|
||||||
compilation,
|
self.kodidb.add_discography(artist_id, name, api.year())
|
||||||
kodi_id))
|
|
||||||
# Add artist to album
|
|
||||||
query = '''
|
|
||||||
INSERT OR REPLACE INTO album_artist(
|
|
||||||
idArtist,
|
|
||||||
idAlbum,
|
|
||||||
strArtist)
|
|
||||||
VALUES (?, ?, ?)
|
|
||||||
'''
|
|
||||||
self.kodicursor.execute(query,
|
|
||||||
(artist_id, kodi_id, api.artist_name()))
|
|
||||||
# Update discography
|
|
||||||
query = '''
|
|
||||||
INSERT OR REPLACE INTO discography(
|
|
||||||
idArtist,
|
|
||||||
strAlbum,
|
|
||||||
strYear)
|
|
||||||
VALUES (?, ?, ?)
|
|
||||||
'''
|
|
||||||
self.kodicursor.execute(query,
|
|
||||||
(artist_id, name, api.year()))
|
|
||||||
if v.KODIVERSION < 18:
|
if v.KODIVERSION < 18:
|
||||||
self.kodidb.add_music_genres(kodi_id,
|
self.kodidb.add_music_genres(kodi_id,
|
||||||
genres,
|
genres,
|
||||||
|
@ -410,8 +355,7 @@ class Song(MusicMixin, ItemBase):
|
||||||
kodi_pathid = song['kodi_pathid']
|
kodi_pathid = song['kodi_pathid']
|
||||||
else:
|
else:
|
||||||
update_item = False
|
update_item = False
|
||||||
self.kodicursor.execute('SELECT COALESCE(MAX(idSong),0) FROM song')
|
kodi_id = self.kodidb.add_song_id()
|
||||||
kodi_id = self.kodicursor.fetchone()[0] + 1
|
|
||||||
artist_id = api.grandparent_id()
|
artist_id = api.grandparent_id()
|
||||||
album_id = api.parent_id()
|
album_id = api.parent_id()
|
||||||
|
|
||||||
|
@ -440,19 +384,35 @@ class Song(MusicMixin, ItemBase):
|
||||||
if not album_id:
|
if not album_id:
|
||||||
# No album found, create a single's album
|
# No album found, create a single's album
|
||||||
LOG.info('Creating singles album')
|
LOG.info('Creating singles album')
|
||||||
self.kodicursor.execute(
|
parent_id = self.kodidb.new_album_id()
|
||||||
'SELECT COALESCE(MAX(idAlbum),0) FROM album')
|
if v.KODIVERSION >= 18:
|
||||||
parent_id = self.kodicursor.fetchone()[0] + 1
|
self.kodidb.add_album(kodi_id,
|
||||||
query = '''
|
None,
|
||||||
INSERT INTO album(
|
None,
|
||||||
idAlbum,
|
None,
|
||||||
strGenres,
|
genre,
|
||||||
iYear,
|
api.year(),
|
||||||
strReleaseType)
|
None,
|
||||||
VALUES (?, ?, ?, ?)
|
None,
|
||||||
'''
|
None,
|
||||||
self.kodicursor.execute(query,
|
None,
|
||||||
(parent_id, genre, api.year(), 'single'))
|
None,
|
||||||
|
utils.unix_date_to_kodi(self.last_sync),
|
||||||
|
'single')
|
||||||
|
else:
|
||||||
|
self.kodidb.add_album_17(kodi_id,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
genre,
|
||||||
|
api.year(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
utils.unix_date_to_kodi(self.last_sync),
|
||||||
|
'single')
|
||||||
else:
|
else:
|
||||||
album = self.plexdb.album(album_id)
|
album = self.plexdb.album(album_id)
|
||||||
if not album:
|
if not album:
|
||||||
|
@ -539,31 +499,11 @@ class Song(MusicMixin, ItemBase):
|
||||||
if update_item:
|
if update_item:
|
||||||
LOG.info("UPDATE song plex_id: %s - %s", plex_id, title)
|
LOG.info("UPDATE song plex_id: %s - %s", plex_id, title)
|
||||||
# Use dummy strHash '123' for Kodi
|
# Use dummy strHash '123' for Kodi
|
||||||
query = "UPDATE path SET strPath = ?, strHash = ? WHERE idPath = ?"
|
self.kodidb.update_path(path, kodi_pathid)
|
||||||
self.kodicursor.execute(query, (path, '123', kodi_pathid))
|
|
||||||
# Update the song entry
|
# Update the song entry
|
||||||
if v.KODIVERSION >= 18:
|
if v.KODIVERSION >= 18:
|
||||||
# Kodi Leia
|
# Kodi Leia
|
||||||
query = '''
|
self.kodidb.update_song(parent_id,
|
||||||
UPDATE song
|
|
||||||
SET idAlbum = ?,
|
|
||||||
strArtistDisp = ?,
|
|
||||||
strGenres = ?,
|
|
||||||
strTitle = ?,
|
|
||||||
iTrack = ?,
|
|
||||||
iDuration = ?,
|
|
||||||
iYear = ?,
|
|
||||||
strFilename = ?,
|
|
||||||
iTimesPlayed = ?,
|
|
||||||
lastplayed = ?,
|
|
||||||
rating = ?,
|
|
||||||
comment = ?,
|
|
||||||
mood = ?
|
|
||||||
WHERE idSong = ?
|
|
||||||
'''
|
|
||||||
self.kodicursor.execute(
|
|
||||||
query,
|
|
||||||
(parent_id,
|
|
||||||
artists,
|
artists,
|
||||||
genre,
|
genre,
|
||||||
title,
|
title,
|
||||||
|
@ -576,28 +516,9 @@ class Song(MusicMixin, ItemBase):
|
||||||
userdata['UserRating'],
|
userdata['UserRating'],
|
||||||
comment,
|
comment,
|
||||||
mood,
|
mood,
|
||||||
kodi_id))
|
kodi_id)
|
||||||
else:
|
else:
|
||||||
query = '''
|
self.kodidb.update_song_17(parent_id,
|
||||||
UPDATE song
|
|
||||||
SET idAlbum = ?,
|
|
||||||
strArtists = ?,
|
|
||||||
strGenres = ?,
|
|
||||||
strTitle = ?,
|
|
||||||
iTrack = ?,
|
|
||||||
iDuration = ?,
|
|
||||||
iYear = ?,
|
|
||||||
strFilename = ?,
|
|
||||||
iTimesPlayed = ?,
|
|
||||||
lastplayed = ?,
|
|
||||||
rating = ?,
|
|
||||||
comment = ?,
|
|
||||||
mood = ?
|
|
||||||
WHERE idSong = ?
|
|
||||||
'''
|
|
||||||
self.kodicursor.execute(
|
|
||||||
query,
|
|
||||||
(parent_id,
|
|
||||||
artists,
|
artists,
|
||||||
genre,
|
genre,
|
||||||
title,
|
title,
|
||||||
|
@ -610,40 +531,16 @@ class Song(MusicMixin, ItemBase):
|
||||||
userdata['UserRating'],
|
userdata['UserRating'],
|
||||||
comment,
|
comment,
|
||||||
mood,
|
mood,
|
||||||
kodi_id))
|
kodi_id)
|
||||||
|
|
||||||
# OR ADD THE SONG #####
|
# OR ADD THE SONG #####
|
||||||
else:
|
else:
|
||||||
LOG.info("ADD song plex_id: %s - %s", plex_id, title)
|
LOG.info("ADD song plex_id: %s - %s", plex_id, title)
|
||||||
# Add path
|
# Add path
|
||||||
kodi_pathid = self.kodidb.add_path(path, hash_string="123")
|
kodi_pathid = self.kodidb.add_path(path)
|
||||||
# Create the song entry
|
# Create the song entry
|
||||||
if v.KODIVERSION >= 18:
|
if v.KODIVERSION >= 18:
|
||||||
# Kodi Leia
|
# Kodi Leia
|
||||||
query = '''
|
self.kodidb.add_song(kodi_id,
|
||||||
INSERT INTO song(
|
|
||||||
idSong,
|
|
||||||
idAlbum,
|
|
||||||
idPath,
|
|
||||||
strArtistDisp,
|
|
||||||
strGenres,
|
|
||||||
strTitle,
|
|
||||||
iTrack,
|
|
||||||
iDuration,
|
|
||||||
iYear,
|
|
||||||
strFileName,
|
|
||||||
strMusicBrainzTrackID,
|
|
||||||
iTimesPlayed,
|
|
||||||
lastplayed,
|
|
||||||
rating,
|
|
||||||
iStartOffset,
|
|
||||||
iEndOffset,
|
|
||||||
mood)
|
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
||||||
'''
|
|
||||||
self.kodicursor.execute(
|
|
||||||
query,
|
|
||||||
(kodi_id,
|
|
||||||
parent_id,
|
parent_id,
|
||||||
kodi_pathid,
|
kodi_pathid,
|
||||||
artists,
|
artists,
|
||||||
|
@ -659,32 +556,9 @@ class Song(MusicMixin, ItemBase):
|
||||||
userdata['UserRating'],
|
userdata['UserRating'],
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
mood))
|
mood)
|
||||||
else:
|
else:
|
||||||
query = '''
|
self.kodidb.add_song_17(kodi_id,
|
||||||
INSERT INTO song(
|
|
||||||
idSong,
|
|
||||||
idAlbum,
|
|
||||||
idPath,
|
|
||||||
strArtists,
|
|
||||||
strGenres,
|
|
||||||
strTitle,
|
|
||||||
iTrack,
|
|
||||||
iDuration,
|
|
||||||
iYear,
|
|
||||||
strFileName,
|
|
||||||
strMusicBrainzTrackID,
|
|
||||||
iTimesPlayed,
|
|
||||||
lastplayed,
|
|
||||||
rating,
|
|
||||||
iStartOffset,
|
|
||||||
iEndOffset,
|
|
||||||
mood)
|
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
||||||
'''
|
|
||||||
self.kodicursor.execute(
|
|
||||||
query,
|
|
||||||
(kodi_id,
|
|
||||||
parent_id,
|
parent_id,
|
||||||
kodi_pathid,
|
kodi_pathid,
|
||||||
artists,
|
artists,
|
||||||
|
@ -700,35 +574,18 @@ class Song(MusicMixin, ItemBase):
|
||||||
userdata['UserRating'],
|
userdata['UserRating'],
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
mood))
|
mood)
|
||||||
if v.KODIVERSION < 18:
|
if v.KODIVERSION < 18:
|
||||||
# Link song to album
|
# Link song to album
|
||||||
query = '''
|
self.kodidb.add_albuminfosong(kodi_id,
|
||||||
INSERT OR REPLACE INTO albuminfosong(
|
parent_id,
|
||||||
idAlbumInfoSong,
|
track,
|
||||||
idAlbumInfo,
|
title,
|
||||||
iTrack,
|
userdata['Runtime'])
|
||||||
strTitle,
|
|
||||||
iDuration)
|
|
||||||
VALUES (?, ?, ?, ?, ?)
|
|
||||||
'''
|
|
||||||
self.kodicursor.execute(
|
|
||||||
query,
|
|
||||||
(kodi_id, parent_id, track, title, userdata['Runtime']))
|
|
||||||
# Link song to artists
|
# Link song to artists
|
||||||
artist_name = api.grandparent_title()
|
artist_name = api.grandparent_title()
|
||||||
# Do the actual linking
|
# Do the actual linking
|
||||||
query = '''
|
self.kodidb.add_song_artist(grandparent_id, kodi_id, artist_name)
|
||||||
INSERT OR REPLACE INTO song_artist(
|
|
||||||
idArtist,
|
|
||||||
idSong,
|
|
||||||
idRole,
|
|
||||||
iOrder,
|
|
||||||
strArtist)
|
|
||||||
VALUES (?, ?, ?, ?, ?)
|
|
||||||
'''
|
|
||||||
self.kodicursor.execute(query,
|
|
||||||
(grandparent_id, kodi_id, 1, 0, artist_name))
|
|
||||||
# Add genres
|
# Add genres
|
||||||
if genres:
|
if genres:
|
||||||
self.kodidb.add_music_genres(kodi_id, genres, v.KODI_TYPE_SONG)
|
self.kodidb.add_music_genres(kodi_id, genres, v.KODI_TYPE_SONG)
|
||||||
|
|
|
@ -30,7 +30,7 @@ def kodiid_from_filename(path, kodi_type=None, db_type=None):
|
||||||
if kodi_type == v.KODI_TYPE_SONG or db_type == 'music':
|
if kodi_type == v.KODI_TYPE_SONG or db_type == 'music':
|
||||||
with KodiMusicDB() as kodidb:
|
with KodiMusicDB() as kodidb:
|
||||||
try:
|
try:
|
||||||
kodi_id = kodidb.music_id_from_filename(filename, path)
|
kodi_id = kodidb.song_id_from_filename(filename, path)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
LOG.debug('No Kodi audio db element found for path %s', path)
|
LOG.debug('No Kodi audio db element found for path %s', path)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -4,7 +4,7 @@ from __future__ import absolute_import, division, unicode_literals
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from . import common
|
from . import common
|
||||||
from .. import utils
|
from .. import variables as v
|
||||||
|
|
||||||
LOG = getLogger('PLEX.kodi_db.music')
|
LOG = getLogger('PLEX.kodi_db.music')
|
||||||
|
|
||||||
|
@ -12,16 +12,10 @@ LOG = getLogger('PLEX.kodi_db.music')
|
||||||
class KodiMusicDB(common.KodiDBBase):
|
class KodiMusicDB(common.KodiDBBase):
|
||||||
db_kind = 'music'
|
db_kind = 'music'
|
||||||
|
|
||||||
def __enter__(self):
|
def add_path(self, path):
|
||||||
self.kodiconn = utils.kodi_sql('music')
|
|
||||||
self.cursor = self.kodiconn.cursor()
|
|
||||||
return self
|
|
||||||
|
|
||||||
def add_path(self, path, hash_string=None):
|
|
||||||
"""
|
"""
|
||||||
Add the path (unicode) to the music DB, if it does not exist already.
|
Add the path (unicode) to the music DB, if it does not exist already.
|
||||||
Returns the path id
|
Returns the path id
|
||||||
Set hash_string to something unicode to set the strHash attribute
|
|
||||||
"""
|
"""
|
||||||
# SQL won't return existing paths otherwise
|
# SQL won't return existing paths otherwise
|
||||||
path = '' if path is None else path
|
path = '' if path is None else path
|
||||||
|
@ -36,16 +30,23 @@ class KodiMusicDB(common.KodiDBBase):
|
||||||
INSERT INTO path(idPath, strPath, strHash)
|
INSERT INTO path(idPath, strPath, strHash)
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
''',
|
''',
|
||||||
(pathid, path, hash_string))
|
(pathid, path, '123'))
|
||||||
return pathid
|
return pathid
|
||||||
|
|
||||||
def music_id_from_filename(self, filename, path):
|
def update_path(self, path, kodi_pathid):
|
||||||
|
self.cursor.execute('''
|
||||||
|
UPDATE path
|
||||||
|
SET strPath = ?, strHash = ?
|
||||||
|
WHERE idPath = ?
|
||||||
|
''', (path, '123', kodi_pathid))
|
||||||
|
|
||||||
|
def song_id_from_filename(self, filename, path):
|
||||||
"""
|
"""
|
||||||
Returns the Kodi song_id from the Kodi music database or None if not
|
Returns the Kodi song_id from the Kodi music database or None if not
|
||||||
found OR something went wrong.
|
found OR something went wrong.
|
||||||
"""
|
"""
|
||||||
self.cursor.execute('SELECT idPath FROM path WHERE strPath = ?',
|
self.cursor.execute('SELECT idPath FROM path WHERE strPath = ?',
|
||||||
(path,))
|
(path, ))
|
||||||
path_ids = self.cursor.fetchall()
|
path_ids = self.cursor.fetchall()
|
||||||
if len(path_ids) != 1:
|
if len(path_ids) != 1:
|
||||||
LOG.debug('Found wrong number of path ids: %s for path %s, abort',
|
LOG.debug('Found wrong number of path ids: %s for path %s, abort',
|
||||||
|
@ -63,10 +64,12 @@ class KodiMusicDB(common.KodiDBBase):
|
||||||
"""
|
"""
|
||||||
Deletes son from song_artist table and possibly orphaned roles
|
Deletes son from song_artist table and possibly orphaned roles
|
||||||
"""
|
"""
|
||||||
self.cursor.execute('SELECT idArtist, idRole FROM song_artist WHERE idSong = ? LIMIT 1',
|
self.cursor.execute('''
|
||||||
(song_id, ))
|
SELECT idArtist, idRole FROM song_artist
|
||||||
|
WHERE idSong = ? LIMIT 1
|
||||||
|
''', (song_id, ))
|
||||||
artist = self.cursor.fetchone()
|
artist = self.cursor.fetchone()
|
||||||
if artist is None:
|
if not artist:
|
||||||
# No entry to begin with
|
# No entry to begin with
|
||||||
return
|
return
|
||||||
# Delete the entry
|
# Delete the entry
|
||||||
|
@ -141,27 +144,107 @@ class KodiMusicDB(common.KodiDBBase):
|
||||||
self.cursor.execute('DELETE FROM genre WHERE idGenre = ?',
|
self.cursor.execute('DELETE FROM genre WHERE idGenre = ?',
|
||||||
(genre[0], ))
|
(genre[0], ))
|
||||||
|
|
||||||
def add_album(self, name, musicbrainz):
|
def new_album_id(self):
|
||||||
|
self.cursor.execute('SELECT COALESCE(MAX(idAlbum), 0) FROM album')
|
||||||
|
return self.cursor.fetchone()[0] + 1
|
||||||
|
|
||||||
|
def add_album_17(self, *args):
|
||||||
"""
|
"""
|
||||||
Adds a single album to the DB
|
strReleaseType: 'album' or 'single'
|
||||||
"""
|
"""
|
||||||
self.cursor.execute('SELECT idAlbum FROM album WHERE strMusicBrainzAlbumID = ?',
|
|
||||||
(musicbrainz, ))
|
|
||||||
try:
|
|
||||||
albumid = self.cursor.fetchone()[0]
|
|
||||||
except TypeError:
|
|
||||||
# Create the album
|
|
||||||
self.cursor.execute('SELECT COALESCE(MAX(idAlbum),0) FROM album')
|
|
||||||
albumid = self.cursor.fetchone()[0] + 1
|
|
||||||
self.cursor.execute('''
|
self.cursor.execute('''
|
||||||
INSERT INTO album(
|
INSERT INTO album(
|
||||||
idAlbum,
|
idAlbum,
|
||||||
strAlbum,
|
strAlbum,
|
||||||
strMusicBrainzAlbumID,
|
strMusicBrainzAlbumID,
|
||||||
|
strArtists,
|
||||||
|
strGenres,
|
||||||
|
iYear,
|
||||||
|
bCompilation,
|
||||||
|
strReview,
|
||||||
|
strImage,
|
||||||
|
strLabel,
|
||||||
|
iUserrating,
|
||||||
|
lastScraped,
|
||||||
strReleaseType)
|
strReleaseType)
|
||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
''', (albumid, name, musicbrainz, 'album'))
|
''', (args))
|
||||||
return albumid
|
|
||||||
|
def update_album_17(self, *args):
|
||||||
|
self.cursor.execute('''
|
||||||
|
UPDATE album
|
||||||
|
SET strAlbum = ?,
|
||||||
|
strMusicBrainzAlbumID = ?,
|
||||||
|
strArtists = ?,
|
||||||
|
strGenres = ?,
|
||||||
|
iYear = ?,
|
||||||
|
bCompilation = ?
|
||||||
|
strReview = ?,
|
||||||
|
strImage = ?,
|
||||||
|
strLabel = ?,
|
||||||
|
iUserrating = ?,
|
||||||
|
lastScraped = ?,
|
||||||
|
strReleaseType = ?,
|
||||||
|
WHERE idAlbum = ?
|
||||||
|
''', (args))
|
||||||
|
|
||||||
|
def add_album(self, *args):
|
||||||
|
"""
|
||||||
|
strReleaseType: 'album' or 'single'
|
||||||
|
"""
|
||||||
|
self.cursor.execute('''
|
||||||
|
INSERT INTO album(
|
||||||
|
idAlbum,
|
||||||
|
strAlbum,
|
||||||
|
strMusicBrainzAlbumID,
|
||||||
|
strArtistDisp,
|
||||||
|
strGenres,
|
||||||
|
iYear,
|
||||||
|
bCompilation,
|
||||||
|
strReview,
|
||||||
|
strImage,
|
||||||
|
strLabel,
|
||||||
|
iUserrating,
|
||||||
|
lastScraped,
|
||||||
|
strReleaseType)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
''', (args))
|
||||||
|
|
||||||
|
def update_album(self, *args):
|
||||||
|
self.cursor.execute('''
|
||||||
|
UPDATE album
|
||||||
|
SET strAlbum = ?,
|
||||||
|
strMusicBrainzAlbumID = ?,
|
||||||
|
strArtistDisp = ?,
|
||||||
|
strGenres = ?,
|
||||||
|
iYear = ?,
|
||||||
|
bCompilation = ?
|
||||||
|
strReview = ?,
|
||||||
|
strImage = ?,
|
||||||
|
strLabel = ?,
|
||||||
|
iUserrating = ?,
|
||||||
|
lastScraped = ?,
|
||||||
|
strReleaseType = ?,
|
||||||
|
WHERE idAlbum = ?
|
||||||
|
''', (args))
|
||||||
|
|
||||||
|
def add_albumartist(self, artist_id, kodi_id, artistname):
|
||||||
|
self.cursor.execute('''
|
||||||
|
INSERT OR REPLACE INTO album_artist(
|
||||||
|
idArtist,
|
||||||
|
idAlbum,
|
||||||
|
strArtist)
|
||||||
|
VALUES (?, ?, ?)
|
||||||
|
''', (artist_id, kodi_id, artistname))
|
||||||
|
|
||||||
|
def add_discography(self, artist_id, albumname, year):
|
||||||
|
self.cursor.execute('''
|
||||||
|
INSERT OR REPLACE INTO discography(
|
||||||
|
idArtist,
|
||||||
|
strAlbum,
|
||||||
|
strYear)
|
||||||
|
VALUES (?, ?, ?)
|
||||||
|
''', (artist_id, albumname, year))
|
||||||
|
|
||||||
def add_music_genres(self, kodiid, genres, mediatype):
|
def add_music_genres(self, kodiid, genres, mediatype):
|
||||||
"""
|
"""
|
||||||
|
@ -210,6 +293,102 @@ class KodiMusicDB(common.KodiDBBase):
|
||||||
VALUES (?, ?)
|
VALUES (?, ?)
|
||||||
''', (genreid, kodiid))
|
''', (genreid, kodiid))
|
||||||
|
|
||||||
|
def add_song_id(self):
|
||||||
|
self.cursor.execute('SELECT COALESCE(MAX(idSong),0) FROM song')
|
||||||
|
return self.cursor.fetchone()[0] + 1
|
||||||
|
|
||||||
|
def add_song(self, *args):
|
||||||
|
self.cursor.execute('''
|
||||||
|
INSERT INTO song(
|
||||||
|
idSong,
|
||||||
|
idAlbum,
|
||||||
|
idPath,
|
||||||
|
strArtistDisp,
|
||||||
|
strGenres,
|
||||||
|
strTitle,
|
||||||
|
iTrack,
|
||||||
|
iDuration,
|
||||||
|
iYear,
|
||||||
|
strFileName,
|
||||||
|
strMusicBrainzTrackID,
|
||||||
|
iTimesPlayed,
|
||||||
|
lastplayed,
|
||||||
|
rating,
|
||||||
|
iStartOffset,
|
||||||
|
iEndOffset,
|
||||||
|
mood)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
''', (args))
|
||||||
|
|
||||||
|
def add_song_17(self, *args):
|
||||||
|
self.cursor.execute('''
|
||||||
|
INSERT INTO song(
|
||||||
|
idSong,
|
||||||
|
idAlbum,
|
||||||
|
idPath,
|
||||||
|
strArtists,
|
||||||
|
strGenres,
|
||||||
|
strTitle,
|
||||||
|
iTrack,
|
||||||
|
iDuration,
|
||||||
|
iYear,
|
||||||
|
strFileName,
|
||||||
|
strMusicBrainzTrackID,
|
||||||
|
iTimesPlayed,
|
||||||
|
lastplayed,
|
||||||
|
rating,
|
||||||
|
iStartOffset,
|
||||||
|
iEndOffset,
|
||||||
|
mood)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
''', (args))
|
||||||
|
|
||||||
|
def update_song(self, *args):
|
||||||
|
self.cursor.execute('''
|
||||||
|
UPDATE song
|
||||||
|
SET idAlbum = ?,
|
||||||
|
strArtistDisp = ?,
|
||||||
|
strGenres = ?,
|
||||||
|
strTitle = ?,
|
||||||
|
iTrack = ?,
|
||||||
|
iDuration = ?,
|
||||||
|
iYear = ?,
|
||||||
|
strFilename = ?,
|
||||||
|
iTimesPlayed = ?,
|
||||||
|
lastplayed = ?,
|
||||||
|
rating = ?,
|
||||||
|
comment = ?,
|
||||||
|
mood = ?
|
||||||
|
WHERE idSong = ?
|
||||||
|
''', (args))
|
||||||
|
|
||||||
|
def update_song_17(self, *args):
|
||||||
|
self.cursor.execute('''
|
||||||
|
UPDATE song
|
||||||
|
SET idAlbum = ?,
|
||||||
|
strArtists = ?,
|
||||||
|
strGenres = ?,
|
||||||
|
strTitle = ?,
|
||||||
|
iTrack = ?,
|
||||||
|
iDuration = ?,
|
||||||
|
iYear = ?,
|
||||||
|
strFilename = ?,
|
||||||
|
iTimesPlayed = ?,
|
||||||
|
lastplayed = ?,
|
||||||
|
rating = ?,
|
||||||
|
comment = ?,
|
||||||
|
mood = ?
|
||||||
|
WHERE idSong = ?
|
||||||
|
''', (args))
|
||||||
|
|
||||||
|
def path_id_from_song(self, kodi_id):
|
||||||
|
self.cursor.execute('SELECT idPath FROM song WHERE idSong = ? LIMIT 1',
|
||||||
|
(kodi_id, ))
|
||||||
|
try:
|
||||||
|
return self.cursor.fetchone()[0]
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
def add_artist(self, name, musicbrainz):
|
def add_artist(self, name, musicbrainz):
|
||||||
"""
|
"""
|
||||||
Adds a single artist's name to the db
|
Adds a single artist's name to the db
|
||||||
|
@ -245,3 +424,71 @@ class KodiMusicDB(common.KodiDBBase):
|
||||||
self.cursor.execute('UPDATE artist SET strArtist = ? WHERE idArtist = ?',
|
self.cursor.execute('UPDATE artist SET strArtist = ? WHERE idArtist = ?',
|
||||||
(name, artistid,))
|
(name, artistid,))
|
||||||
return artistid
|
return artistid
|
||||||
|
|
||||||
|
def update_artist(self, *args):
|
||||||
|
self.cursor.execute('''
|
||||||
|
UPDATE artist
|
||||||
|
SET strGenres = ?,
|
||||||
|
strBiography = ?,
|
||||||
|
strImage = ?,
|
||||||
|
strFanart = ?,
|
||||||
|
lastScraped = ?
|
||||||
|
WHERE idArtist = ?
|
||||||
|
''', (args))
|
||||||
|
|
||||||
|
def remove_song(self, kodi_id):
|
||||||
|
self.cursor.execute('DELETE FROM song WHERE idSong = ?', (kodi_id, ))
|
||||||
|
|
||||||
|
def remove_path(self, path_id):
|
||||||
|
self.cursor.execute('DELETE FROM path WHERE idPath = ?', (path_id, ))
|
||||||
|
|
||||||
|
def add_song_artist(self, artist_id, song_id, artist_name):
|
||||||
|
self.cursor.execute('''
|
||||||
|
INSERT OR REPLACE INTO song_artist(
|
||||||
|
idArtist,
|
||||||
|
idSong,
|
||||||
|
idRole,
|
||||||
|
iOrder,
|
||||||
|
strArtist)
|
||||||
|
VALUES (?, ?, ?, ?, ?)
|
||||||
|
''', (artist_id, song_id, 1, 0, artist_name))
|
||||||
|
|
||||||
|
def add_albuminfosong(self, song_id, album_id, track_no, track_title,
|
||||||
|
runtime):
|
||||||
|
"""
|
||||||
|
Kodi 17 only
|
||||||
|
"""
|
||||||
|
self.cursor.execute('''
|
||||||
|
INSERT OR REPLACE INTO albuminfosong(
|
||||||
|
idAlbumInfoSong,
|
||||||
|
idAlbumInfo,
|
||||||
|
iTrack,
|
||||||
|
strTitle,
|
||||||
|
iDuration)
|
||||||
|
VALUES (?, ?, ?, ?, ?)
|
||||||
|
''', (song_id, album_id, track_no, track_title, runtime))
|
||||||
|
|
||||||
|
def remove_albuminfosong(self, kodi_id):
|
||||||
|
"""
|
||||||
|
Kodi 17 only
|
||||||
|
"""
|
||||||
|
self.cursor.execute('DELETE FROM albuminfosong WHERE idAlbumInfoSong = ?',
|
||||||
|
(kodi_id, ))
|
||||||
|
|
||||||
|
def remove_album(self, kodi_id):
|
||||||
|
if v.KODIVERSION < 18:
|
||||||
|
self.cursor.execute('DELETE FROM albuminfosong WHERE idAlbumInfo = ?',
|
||||||
|
(kodi_id, ))
|
||||||
|
self.cursor.execute('DELETE FROM album_artist WHERE idAlbum = ?',
|
||||||
|
(kodi_id, ))
|
||||||
|
self.cursor.execute('DELETE FROM album WHERE idAlbum = ?', (kodi_id, ))
|
||||||
|
|
||||||
|
def remove_artist(self, kodi_id):
|
||||||
|
self.cursor.execute('DELETE FROM album_artist WHERE idArtist = ?',
|
||||||
|
(kodi_id, ))
|
||||||
|
self.cursor.execute('DELETE FROM artist WHERE idArtist = ?',
|
||||||
|
(kodi_id, ))
|
||||||
|
self.cursor.execute('DELETE FROM song_artist WHERE idArtist = ?',
|
||||||
|
(kodi_id, ))
|
||||||
|
self.cursor.execute('DELETE FROM discography WHERE idArtist = ?',
|
||||||
|
(kodi_id, ))
|
||||||
|
|
Loading…
Reference in a new issue