refactor and fix
This commit is contained in:
parent
dc540e4829
commit
ae547c7de2
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="SqlDialectMappings">
|
|
||||||
<file url="file://$PROJECT_DIR$/src/music_kraken/static_files/new_db.sql" dialect="SQLite" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -19,6 +19,8 @@ if __name__ == "__main__":
|
|||||||
fetch_youtube_playlist = [
|
fetch_youtube_playlist = [
|
||||||
"s: https://yt.artemislena.eu/playlist?list=OLAK5uy_kcUBiDv5ATbl-R20OjNaZ5G28XFanQOmM"
|
"s: https://yt.artemislena.eu/playlist?list=OLAK5uy_kcUBiDv5ATbl-R20OjNaZ5G28XFanQOmM"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
download_youtube_playlist = ["d: https://www.youtube.com/playlist?list=OLAK5uy_lqI_c6aDF9q4DWJ4TBzt1AFQYx_FXfU4E"]
|
||||||
|
|
||||||
youtube_search = [
|
youtube_search = [
|
||||||
"s: #a Zombiez",
|
"s: #a Zombiez",
|
||||||
@ -26,4 +28,4 @@ if __name__ == "__main__":
|
|||||||
"d: 5"
|
"d: 5"
|
||||||
]
|
]
|
||||||
|
|
||||||
music_kraken.cli.download(genre="test", command_list=fetch_youtube_playlist)
|
music_kraken.cli.download(genre="test", command_list=download_youtube_playlist, process_metadata_anyway=True)
|
||||||
|
@ -16,10 +16,16 @@ if __name__ == "__main__":
|
|||||||
help="Sets the logging level to debug."
|
help="Sets the logging level to debug."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'-p', '--force-post-process',
|
||||||
|
action="store_true",
|
||||||
|
help="If a to downloaded thing is skipped due to being found on disc,\nit will still update the metadata accordingly."
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-t', '--test',
|
'-t', '--test',
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="For the sake of testing. Equals: '-v -g test'"
|
help="For the sake of testing. Equals: '-vp -g test'"
|
||||||
)
|
)
|
||||||
|
|
||||||
# general arguments
|
# general arguments
|
||||||
@ -114,5 +120,6 @@ if __name__ == "__main__":
|
|||||||
cli.download(
|
cli.download(
|
||||||
genre=genre,
|
genre=genre,
|
||||||
download_all=arguments.all,
|
download_all=arguments.all,
|
||||||
direct_download_url=arguments.url
|
direct_download_url=arguments.url,
|
||||||
|
process_metadata_anyway=arguments.force_post_process or arguments.test
|
||||||
)
|
)
|
@ -143,7 +143,8 @@ class Downloader:
|
|||||||
exclude_shady: bool = False,
|
exclude_shady: bool = False,
|
||||||
max_displayed_options: int = 10,
|
max_displayed_options: int = 10,
|
||||||
option_digits: int = 3,
|
option_digits: int = 3,
|
||||||
genre: str = None
|
genre: str = None,
|
||||||
|
process_metadata_anyway: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.pages: Pages = Pages(exclude_pages=exclude_pages, exclude_shady=exclude_shady)
|
self.pages: Pages = Pages(exclude_pages=exclude_pages, exclude_shady=exclude_shady)
|
||||||
|
|
||||||
@ -156,6 +157,7 @@ class Downloader:
|
|||||||
self._result_history: List[Results] = []
|
self._result_history: List[Results] = []
|
||||||
|
|
||||||
self.genre = genre or get_genre()
|
self.genre = genre or get_genre()
|
||||||
|
self.process_metadata_anyway = process_metadata_anyway
|
||||||
|
|
||||||
print()
|
print()
|
||||||
print(f"Downloading to: \"{self.genre}\"")
|
print(f"Downloading to: \"{self.genre}\"")
|
||||||
@ -334,7 +336,7 @@ class Downloader:
|
|||||||
_result_map: Dict[DatabaseObject, DownloadResult] = dict()
|
_result_map: Dict[DatabaseObject, DownloadResult] = dict()
|
||||||
|
|
||||||
for database_object in to_download:
|
for database_object in to_download:
|
||||||
r = self.pages.download(music_object=database_object, genre=self.genre, download_all=download_all)
|
r = self.pages.download(music_object=database_object, genre=self.genre, download_all=download_all, process_metadata_anyway=self.process_metadata_anyway)
|
||||||
_result_map[database_object] = r
|
_result_map[database_object] = r
|
||||||
|
|
||||||
for music_object, result in _result_map.items():
|
for music_object, result in _result_map.items():
|
||||||
@ -386,9 +388,10 @@ def download(
|
|||||||
genre: str = None,
|
genre: str = None,
|
||||||
download_all: bool = False,
|
download_all: bool = False,
|
||||||
direct_download_url: str = None,
|
direct_download_url: str = None,
|
||||||
command_list: List[str] = None
|
command_list: List[str] = None,
|
||||||
|
process_metadata_anyway: bool = False,
|
||||||
):
|
):
|
||||||
shell = Downloader(genre=genre)
|
shell = Downloader(genre=genre, process_metadata_anyway=process_metadata_anyway)
|
||||||
|
|
||||||
if command_list is not None:
|
if command_list is not None:
|
||||||
for command in command_list:
|
for command in command_list:
|
||||||
|
@ -74,7 +74,7 @@ class Pages:
|
|||||||
|
|
||||||
return music_object
|
return music_object
|
||||||
|
|
||||||
def download(self, music_object: DatabaseObject, genre: str, download_all: bool = False) -> DownloadResult:
|
def download(self, music_object: DatabaseObject, genre: str, download_all: bool = False, process_metadata_anyway: bool = False) -> DownloadResult:
|
||||||
if not isinstance(music_object, INDEPENDENT_DB_OBJECTS):
|
if not isinstance(music_object, INDEPENDENT_DB_OBJECTS):
|
||||||
return DownloadResult(error_message=f"{type(music_object).__name__} can't be downloaded.")
|
return DownloadResult(error_message=f"{type(music_object).__name__} can't be downloaded.")
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ class Pages:
|
|||||||
audio_pages = self._audio_pages_set.intersection(_page_types)
|
audio_pages = self._audio_pages_set.intersection(_page_types)
|
||||||
|
|
||||||
for download_page in audio_pages:
|
for download_page in audio_pages:
|
||||||
return self._page_instances[download_page].download(music_object=music_object, genre=genre, download_all=download_all)
|
return self._page_instances[download_page].download(music_object=music_object, genre=genre, download_all=download_all, process_metadata_anyway=process_metadata_anyway)
|
||||||
|
|
||||||
return DownloadResult(error_message=f"No audio source has been found for {music_object}.")
|
return DownloadResult(error_message=f"No audio source has been found for {music_object}.")
|
||||||
|
|
||||||
|
@ -16,7 +16,11 @@ class Mapping(Enum):
|
|||||||
TITLE = "TIT2"
|
TITLE = "TIT2"
|
||||||
ISRC = "TSRC"
|
ISRC = "TSRC"
|
||||||
LENGTH = "TLEN" # in milliseconds
|
LENGTH = "TLEN" # in milliseconds
|
||||||
DATE = "TYER"
|
# The 'Date' frame is a numeric string in the DDMM format containing the date for the recording. This field is always four characters long.
|
||||||
|
DATE = "TDAT"
|
||||||
|
# The 'Time' frame is a numeric string in the HHMM format containing the time for the recording. This field is always four characters long.
|
||||||
|
TIME = "TIME"
|
||||||
|
YEAR = "TYER"
|
||||||
TRACKNUMBER = "TRCK"
|
TRACKNUMBER = "TRCK"
|
||||||
TOTALTRACKS = "TRCK" # Stored in the same frame with TRACKNUMBER, separated by '/': e.g. '4/9'.
|
TOTALTRACKS = "TRCK" # Stored in the same frame with TRACKNUMBER, separated by '/': e.g. '4/9'.
|
||||||
TITLESORTORDER = "TSOT"
|
TITLESORTORDER = "TSOT"
|
||||||
@ -298,7 +302,7 @@ class Metadata:
|
|||||||
if id3_dict is not None:
|
if id3_dict is not None:
|
||||||
self.add_metadata_dict(id3_dict)
|
self.add_metadata_dict(id3_dict)
|
||||||
|
|
||||||
def __setitem__(self, frame, value_list: list, override_existing: bool = True):
|
def __setitem__(self, frame: Mapping, value_list: list, override_existing: bool = True):
|
||||||
if type(value_list) != list:
|
if type(value_list) != list:
|
||||||
raise ValueError(f"can only set attribute to list, not {type(value_list)}")
|
raise ValueError(f"can only set attribute to list, not {type(value_list)}")
|
||||||
|
|
||||||
|
@ -295,7 +295,11 @@ class Album(MainObject):
|
|||||||
id3Mapping.COPYRIGHT: [self.copyright],
|
id3Mapping.COPYRIGHT: [self.copyright],
|
||||||
id3Mapping.LANGUAGE: [self.iso_639_2_lang],
|
id3Mapping.LANGUAGE: [self.iso_639_2_lang],
|
||||||
id3Mapping.ALBUM_ARTIST: [a.name for a in self.artist_collection],
|
id3Mapping.ALBUM_ARTIST: [a.name for a in self.artist_collection],
|
||||||
id3Mapping.DATE: [self.date.timestamp],
|
id3Mapping.DATE: [self.date.strftime("%d%m")] if self.date.has_year and self.date.has_month else [],
|
||||||
|
id3Mapping.TIME: [self.date.strftime(("%H%M"))] if self.date.has_hour and self.date.has_minute else [],
|
||||||
|
id3Mapping.YEAR: [str(self.date.year).zfill(4)] if self.date.has_year else [],
|
||||||
|
id3Mapping.RELEASE_DATE: [self.date.timestamp],
|
||||||
|
id3Mapping.ORIGINAL_RELEASE_DATE: [self.date.timestamp],
|
||||||
id3Mapping.ALBUMSORTORDER: [str(self.albumsort)] if self.albumsort is not None else []
|
id3Mapping.ALBUMSORTORDER: [str(self.albumsort)] if self.albumsort is not None else []
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -322,7 +322,7 @@ class Page:
|
|||||||
def fetch_label(self, source: Source, stop_at_level: int = 1) -> Label:
|
def fetch_label(self, source: Source, stop_at_level: int = 1) -> Label:
|
||||||
return Label()
|
return Label()
|
||||||
|
|
||||||
def download(self, music_object: DatabaseObject, genre: str, download_all: bool = False) -> DownloadResult:
|
def download(self, music_object: DatabaseObject, genre: str, download_all: bool = False, process_metadata_anyway: bool = False) -> DownloadResult:
|
||||||
naming_dict: NamingDict = NamingDict({"genre": genre})
|
naming_dict: NamingDict = NamingDict({"genre": genre})
|
||||||
|
|
||||||
def fill_naming_objects(naming_music_object: DatabaseObject):
|
def fill_naming_objects(naming_music_object: DatabaseObject):
|
||||||
@ -340,10 +340,10 @@ class Page:
|
|||||||
|
|
||||||
fill_naming_objects(music_object)
|
fill_naming_objects(music_object)
|
||||||
|
|
||||||
return self._download(music_object, naming_dict, download_all)
|
return self._download(music_object, naming_dict, download_all, process_metadata_anyway=process_metadata_anyway)
|
||||||
|
|
||||||
|
|
||||||
def _download(self, music_object: DatabaseObject, naming_dict: NamingDict, download_all: bool = False, skip_details: bool = False) -> DownloadResult:
|
def _download(self, music_object: DatabaseObject, naming_dict: NamingDict, download_all: bool = False, skip_details: bool = False, process_metadata_anyway: bool = False) -> DownloadResult:
|
||||||
skip_next_details = skip_details
|
skip_next_details = skip_details
|
||||||
|
|
||||||
# Skips all releases, that are defined in shared.ALBUM_TYPE_BLACKLIST, if download_all is False
|
# Skips all releases, that are defined in shared.ALBUM_TYPE_BLACKLIST, if download_all is False
|
||||||
@ -360,7 +360,7 @@ class Page:
|
|||||||
naming_dict.add_object(music_object)
|
naming_dict.add_object(music_object)
|
||||||
|
|
||||||
if isinstance(music_object, Song):
|
if isinstance(music_object, Song):
|
||||||
return self._download_song(music_object, naming_dict)
|
return self._download_song(music_object, naming_dict, process_metadata_anyway=process_metadata_anyway)
|
||||||
|
|
||||||
download_result: DownloadResult = DownloadResult()
|
download_result: DownloadResult = DownloadResult()
|
||||||
|
|
||||||
@ -369,11 +369,17 @@ class Page:
|
|||||||
|
|
||||||
sub_ordered_music_object: DatabaseObject
|
sub_ordered_music_object: DatabaseObject
|
||||||
for sub_ordered_music_object in collection:
|
for sub_ordered_music_object in collection:
|
||||||
download_result.merge(self._download(sub_ordered_music_object, naming_dict.copy(), download_all, skip_details=skip_next_details))
|
download_result.merge(self._download(sub_ordered_music_object, naming_dict.copy(), download_all, skip_details=skip_next_details, process_metadata_anyway=process_metadata_anyway))
|
||||||
|
|
||||||
return download_result
|
return download_result
|
||||||
|
|
||||||
def _download_song(self, song: Song, naming_dict: NamingDict):
|
def _download_song(self, song: Song, naming_dict: NamingDict, process_metadata_anyway: bool = False):
|
||||||
|
if "genre" not in naming_dict and song.genre is not None:
|
||||||
|
naming_dict["genre"] = song.genre
|
||||||
|
|
||||||
|
if song.genre is None:
|
||||||
|
song.genre = naming_dict["genre"]
|
||||||
|
|
||||||
path_parts = Formatter().parse(DOWNLOAD_PATH)
|
path_parts = Formatter().parse(DOWNLOAD_PATH)
|
||||||
file_parts = Formatter().parse(DOWNLOAD_FILE)
|
file_parts = Formatter().parse(DOWNLOAD_FILE)
|
||||||
new_target = Target(
|
new_target = Target(
|
||||||
@ -401,18 +407,21 @@ class Page:
|
|||||||
target: Target
|
target: Target
|
||||||
for target in song.target_collection:
|
for target in song.target_collection:
|
||||||
if target.exists:
|
if target.exists:
|
||||||
|
if process_metadata_anyway:
|
||||||
|
target.copy_content(temp_target)
|
||||||
found_on_disc = True
|
found_on_disc = True
|
||||||
|
|
||||||
r.found_on_disk += 1
|
r.found_on_disk += 1
|
||||||
r.add_target(target)
|
r.add_target(target)
|
||||||
|
|
||||||
if found_on_disc:
|
if found_on_disc and not process_metadata_anyway:
|
||||||
self.LOGGER.info(f"{song.option_string} already exists, thus not downloading again.")
|
self.LOGGER.info(f"{song.option_string} already exists, thus not downloading again.")
|
||||||
return r
|
return r
|
||||||
|
|
||||||
source = sources[0]
|
source = sources[0]
|
||||||
|
|
||||||
r = self.download_song_to_target(source=source, target=temp_target, desc=song.title)
|
if not found_on_disc:
|
||||||
|
r = self.download_song_to_target(source=source, target=temp_target, desc=song.title)
|
||||||
|
|
||||||
|
|
||||||
if not r.is_fatal_error:
|
if not r.is_fatal_error:
|
||||||
|
@ -1,81 +0,0 @@
|
|||||||
CREATE TABLE Song
|
|
||||||
(
|
|
||||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
name TEXT,
|
|
||||||
isrc TEXT,
|
|
||||||
length INT, -- length is in milliseconds (could be wrong)
|
|
||||||
tracksort INT,
|
|
||||||
genre TEXT,
|
|
||||||
album_id BIGINT,
|
|
||||||
FOREIGN KEY(album_id) REFERENCES Album(id)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE Source
|
|
||||||
(
|
|
||||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
type TEXT NOT NULL,
|
|
||||||
src TEXT NOT NULL,
|
|
||||||
url TEXT NOT NULL,
|
|
||||||
certainty INT NOT NULL DEFAULT 0, -- certainty=0 -> it is definitely a valid source
|
|
||||||
valid BOOLEAN NOT NULL DEFAULT 1,
|
|
||||||
song_id BIGINT,
|
|
||||||
FOREIGN KEY(song_id) REFERENCES Song(id)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE Album
|
|
||||||
(
|
|
||||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
title TEXT,
|
|
||||||
label TEXT,
|
|
||||||
album_status TEXT,
|
|
||||||
language TEXT,
|
|
||||||
date TEXT,
|
|
||||||
date_format TEXT,
|
|
||||||
country TEXT,
|
|
||||||
barcode TEXT,
|
|
||||||
albumsort INT,
|
|
||||||
is_split BOOLEAN NOT NULL DEFAULT 0
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE Target
|
|
||||||
(
|
|
||||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
file TEXT,
|
|
||||||
path TEXT,
|
|
||||||
song_id BIGINT UNIQUE,
|
|
||||||
FOREIGN KEY(song_id) REFERENCES Song(id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE Lyrics
|
|
||||||
(
|
|
||||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
text TEXT,
|
|
||||||
language TEXT,
|
|
||||||
song_id BIGINT,
|
|
||||||
FOREIGN KEY(song_id) REFERENCES Song(id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE Artist
|
|
||||||
(
|
|
||||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
name TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE SongArtist
|
|
||||||
(
|
|
||||||
song_id BIGINT NOT NULL,
|
|
||||||
artist_id BIGINT NOT NULL,
|
|
||||||
is_feature BOOLEAN NOT NULL DEFAULT 0,
|
|
||||||
FOREIGN KEY(song_id) REFERENCES Song(id),
|
|
||||||
FOREIGN KEY(artist_id) REFERENCES Artist(id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE AlbumArtist
|
|
||||||
(
|
|
||||||
album_id BIGINT,
|
|
||||||
artist_id BIGINT,
|
|
||||||
FOREIGN KEY(album_id) REFERENCES Album(id),
|
|
||||||
FOREIGN KEY(artist_id) REFERENCES Artist(id)
|
|
||||||
);
|
|
@ -1,144 +0,0 @@
|
|||||||
DROP TABLE IF EXISTS artist;
|
|
||||||
CREATE TABLE artist (
|
|
||||||
id TEXT PRIMARY KEY NOT NULL,
|
|
||||||
mb_id TEXT,
|
|
||||||
name TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS artist_release_group;
|
|
||||||
CREATE TABLE artist_release_group (
|
|
||||||
artist_id TEXT NOT NULL,
|
|
||||||
release_group_id TEXT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS artist_track;
|
|
||||||
CREATE TABLE artist_track (
|
|
||||||
artist_id TEXT NOT NULL,
|
|
||||||
track_id TEXT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS release_group;
|
|
||||||
CREATE TABLE release_group (
|
|
||||||
id TEXT PRIMARY KEY NOT NULL,
|
|
||||||
albumartist TEXT,
|
|
||||||
albumsort INT,
|
|
||||||
musicbrainz_albumtype TEXT,
|
|
||||||
compilation TEXT,
|
|
||||||
album_artist_id TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS release_;
|
|
||||||
CREATE TABLE release_ (
|
|
||||||
id TEXT PRIMARY KEY NOT NULL,
|
|
||||||
release_group_id TEXT NOT NULL,
|
|
||||||
title TEXT,
|
|
||||||
copyright TEXT,
|
|
||||||
album_status TEXT,
|
|
||||||
language TEXT,
|
|
||||||
year TEXT,
|
|
||||||
date TEXT,
|
|
||||||
country TEXT,
|
|
||||||
barcode TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS track;
|
|
||||||
CREATE TABLE track (
|
|
||||||
id TEXT PRIMARY KEY NOT NULL,
|
|
||||||
downloaded BOOLEAN NOT NULL DEFAULT 0,
|
|
||||||
release_id TEXT NOT NULL,
|
|
||||||
mb_id TEXT,
|
|
||||||
track TEXT,
|
|
||||||
length INT,
|
|
||||||
tracknumber TEXT,
|
|
||||||
isrc TEXT,
|
|
||||||
genre TEXT,
|
|
||||||
lyrics TEXT,
|
|
||||||
path TEXT,
|
|
||||||
file TEXT,
|
|
||||||
url TEXT,
|
|
||||||
src TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS lyrics;
|
|
||||||
CREATE TABLE lyrics (
|
|
||||||
track_id TEXT NOT NULL,
|
|
||||||
text TEXT,
|
|
||||||
language TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS target;
|
|
||||||
CREATE TABLE target (
|
|
||||||
track_id TEXT NOT NULL,
|
|
||||||
file TEXT,
|
|
||||||
path TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS source;
|
|
||||||
CREATE TABLE source (
|
|
||||||
track_id TEXT NOT NULL,
|
|
||||||
src TEXT NOT NULL,
|
|
||||||
url TEXT NOT NULL,
|
|
||||||
certainty INT NOT NULL DEFAULT 0, -- certainty=0 -> it is definitly a valid source
|
|
||||||
valid BOOLEAN NOT NULL DEFAULT 1
|
|
||||||
);
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS easy_id3;
|
|
||||||
CREATE TABLE easy_id3 (
|
|
||||||
track_id TEXT NOT NULL,
|
|
||||||
album TEXT,
|
|
||||||
bpm TEXT,
|
|
||||||
compilation TEXT,
|
|
||||||
composer TEXT,
|
|
||||||
copyright TEXT,
|
|
||||||
encodedby TEXT,
|
|
||||||
lyricist TEXT,
|
|
||||||
length TEXT,
|
|
||||||
media TEXT,
|
|
||||||
mood TEXT,
|
|
||||||
grouping TEXT,
|
|
||||||
title TEXT,
|
|
||||||
version TEXT,
|
|
||||||
artist TEXT,
|
|
||||||
albumartist TEXT,
|
|
||||||
conductor TEXT,
|
|
||||||
arranger TEXT,
|
|
||||||
discnumber TEXT,
|
|
||||||
organization TEXT,
|
|
||||||
tracknumber TEXT,
|
|
||||||
author TEXT,
|
|
||||||
albumartistsort TEXT,
|
|
||||||
albumsort TEXT,
|
|
||||||
composersort TEXT,
|
|
||||||
artistsort TEXT,
|
|
||||||
titlesort TEXT,
|
|
||||||
isrc TEXT,
|
|
||||||
discsubtitle TEXT,
|
|
||||||
language TEXT,
|
|
||||||
genre TEXT,
|
|
||||||
date TEXT,
|
|
||||||
originaldate TEXT,
|
|
||||||
performer TEXT,
|
|
||||||
musicbrainz_trackid TEXT,
|
|
||||||
website TEXT,
|
|
||||||
replaygain_gain TEXT,
|
|
||||||
replaygain_peak TEXT,
|
|
||||||
musicbrainz_artistid TEXT,
|
|
||||||
musicbrainz_albumid TEXT,
|
|
||||||
musicbrainz_albumartistid TEXT,
|
|
||||||
musicbrainz_trmid TEXT,
|
|
||||||
musicip_puid TEXT,
|
|
||||||
musicip_fingerprint TEXT,
|
|
||||||
musicbrainz_albumstatus TEXT,
|
|
||||||
musicbrainz_albumtype TEXT,
|
|
||||||
releasecountry TEXT,
|
|
||||||
musicbrainz_discid TEXT,
|
|
||||||
asin TEXT,
|
|
||||||
performer TEXT,
|
|
||||||
barcode TEXT,
|
|
||||||
catalognumber TEXT,
|
|
||||||
musicbrainz_releasetrackid TEXT,
|
|
||||||
musicbrainz_releasegroupid TEXT,
|
|
||||||
musicbrainz_workid TEXT,
|
|
||||||
acoustid_fingerprint TEXT,
|
|
||||||
acoustid_id TEXT
|
|
||||||
);
|
|
Loading…
Reference in New Issue
Block a user