mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-03 20:13:02 +00:00
try hashmap trackstore
This commit is contained in:
+3
-3
@@ -129,7 +129,7 @@ class TrackTable(Base):
|
|||||||
title: Mapped[str] = mapped_column(String())
|
title: Mapped[str] = mapped_column(String())
|
||||||
track: Mapped[int] = mapped_column(Integer())
|
track: Mapped[int] = mapped_column(Integer())
|
||||||
trackhash: Mapped[str] = mapped_column(String(), index=True)
|
trackhash: Mapped[str] = mapped_column(String(), index=True)
|
||||||
is_favorite: Mapped[Optional[bool]] = mapped_column(Boolean())
|
# is_favorite: Mapped[Optional[bool]] = mapped_column(Boolean())
|
||||||
lastplayed: Mapped[int] = mapped_column(Integer(), default=0)
|
lastplayed: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
playcount: Mapped[int] = mapped_column(Integer(), default=0)
|
playcount: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
playduration: Mapped[int] = mapped_column(Integer(), default=0)
|
playduration: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
@@ -270,7 +270,7 @@ class AlbumTable(Base):
|
|||||||
og_title: Mapped[str] = mapped_column(String())
|
og_title: Mapped[str] = mapped_column(String())
|
||||||
title: Mapped[str] = mapped_column(String())
|
title: Mapped[str] = mapped_column(String())
|
||||||
trackcount: Mapped[int] = mapped_column(Integer())
|
trackcount: Mapped[int] = mapped_column(Integer())
|
||||||
is_favorite: Mapped[Optional[bool]] = mapped_column(Boolean())
|
# is_favorite: Mapped[Optional[bool]] = mapped_column(Boolean())
|
||||||
lastplayed: Mapped[int] = mapped_column(Integer(), default=0)
|
lastplayed: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
playcount: Mapped[int] = mapped_column(Integer(), default=0)
|
playcount: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
playduration: Mapped[int] = mapped_column(Integer(), default=0)
|
playduration: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
@@ -360,7 +360,7 @@ class ArtistTable(Base):
|
|||||||
genres: Mapped[str] = mapped_column(JSON())
|
genres: Mapped[str] = mapped_column(JSON())
|
||||||
name: Mapped[str] = mapped_column(String(), index=True)
|
name: Mapped[str] = mapped_column(String(), index=True)
|
||||||
trackcount: Mapped[int] = mapped_column(Integer())
|
trackcount: Mapped[int] = mapped_column(Integer())
|
||||||
is_favorite: Mapped[Optional[bool]] = mapped_column(Boolean())
|
# is_favorite: Mapped[Optional[bool]] = mapped_column(Boolean())
|
||||||
lastplayed: Mapped[int] = mapped_column(Integer(), default=0)
|
lastplayed: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
playcount: Mapped[int] = mapped_column(Integer(), default=0)
|
playcount: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
playduration: Mapped[int] = mapped_column(Integer(), default=0)
|
playduration: Mapped[int] = mapped_column(Integer(), default=0)
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ class GetFilesAndDirs:
|
|||||||
|
|
||||||
tracks = []
|
tracks = []
|
||||||
if files:
|
if files:
|
||||||
tracks = TrackDB.get_tracks_by_filepaths(files)
|
tracks = list(FolderStore.get_tracks_by_filepaths(files))
|
||||||
|
|
||||||
folders = []
|
folders = []
|
||||||
if not self.tracks_only:
|
if not self.tracks_only:
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ class Album:
|
|||||||
og_title: str
|
og_title: str
|
||||||
title: str
|
title: str
|
||||||
trackcount: int
|
trackcount: int
|
||||||
is_favorite: bool
|
# is_favorite: bool
|
||||||
lastplayed: int
|
lastplayed: int
|
||||||
playcount: int
|
playcount: int
|
||||||
playduration: int
|
playduration: int
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class Artist:
|
|||||||
genrehashes: list[str]
|
genrehashes: list[str]
|
||||||
name: str
|
name: str
|
||||||
trackcount: int
|
trackcount: int
|
||||||
is_favorite: bool
|
# is_favorite: bool
|
||||||
lastplayed: int
|
lastplayed: int
|
||||||
playcount: int
|
playcount: int
|
||||||
playduration: int
|
playduration: int
|
||||||
|
|||||||
+8
-7
@@ -1,4 +1,6 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
|
from app.utils.auth import get_current_userid
|
||||||
|
|
||||||
|
|
||||||
@dataclass(slots=True)
|
@dataclass(slots=True)
|
||||||
@@ -33,10 +35,14 @@ class Track:
|
|||||||
playcount: int
|
playcount: int
|
||||||
playduration: int
|
playduration: int
|
||||||
|
|
||||||
is_favorite: bool = False
|
|
||||||
_pos: int = 0
|
_pos: int = 0
|
||||||
_ati: str = ""
|
_ati: str = ""
|
||||||
image: str = ""
|
image: str = ""
|
||||||
|
fav_userids: set = field(default_factory=set)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_favorite(self):
|
||||||
|
return get_current_userid() in self.fav_userids
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
self.image = self.albumhash + ".webp"
|
self.image = self.albumhash + ".webp"
|
||||||
@@ -66,16 +72,11 @@ class Track:
|
|||||||
# image: str = ""
|
# image: str = ""
|
||||||
# artist_hashes: str = ""
|
# artist_hashes: str = ""
|
||||||
|
|
||||||
# fav_userids: list = field(default_factory=list)
|
|
||||||
# """
|
# """
|
||||||
# A string of user ids separated by commas.
|
# A string of user ids separated by commas.
|
||||||
# """
|
# """
|
||||||
# # is_favorite: bool = False
|
# # is_favorite: bool = False
|
||||||
|
|
||||||
# @property
|
|
||||||
# def is_favorite(self):
|
|
||||||
# return current_user["id"] in self.fav_userids
|
|
||||||
|
|
||||||
# # temporary attributes
|
# # temporary attributes
|
||||||
# _pos: int = 0 # for sorting tracks by disc and track number
|
# _pos: int = 0 # for sorting tracks by disc and track number
|
||||||
# _ati: str = (
|
# _ati: str = (
|
||||||
|
|||||||
@@ -46,4 +46,5 @@ def load_into_mem():
|
|||||||
# TrackStore.load_all_tracks(instance_key)
|
# TrackStore.load_all_tracks(instance_key)
|
||||||
# AlbumStore.load_albums(instance_key)
|
# AlbumStore.load_albums(instance_key)
|
||||||
# ArtistStore.load_artists(instance_key)
|
# ArtistStore.load_artists(instance_key)
|
||||||
|
TrackStore.load_all_tracks(get_random_str())
|
||||||
FolderStore.load_filepaths()
|
FolderStore.load_filepaths()
|
||||||
@@ -2,6 +2,7 @@ from sortedcontainers import SortedSet
|
|||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
|
||||||
from app.db.libdata import TrackTable
|
from app.db.libdata import TrackTable
|
||||||
|
from app.store.tracks import TrackStore
|
||||||
|
|
||||||
|
|
||||||
class FolderStore:
|
class FolderStore:
|
||||||
@@ -13,6 +14,10 @@ class FolderStore:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
filepaths: SortedSet = SortedSet()
|
filepaths: SortedSet = SortedSet()
|
||||||
|
map: dict[str, str] = {}
|
||||||
|
"""
|
||||||
|
The map above is a dictionary that maps the folder path to the track hash, which can be used to fetch the track from the track store (a dict of track hashes to track objects).
|
||||||
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_filepaths(cls):
|
def load_filepaths(cls):
|
||||||
@@ -26,7 +31,18 @@ class FolderStore:
|
|||||||
tracks = TrackTable.get_all()
|
tracks = TrackTable.get_all()
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
cls.filepaths.add(track.filepath)
|
cls.filepaths.add(track.filepath)
|
||||||
|
cls.map[track.filepath] = track.trackhash
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_tracks_by_filepaths(cls, filepaths: list[str]):
|
||||||
|
for filepath in filepaths:
|
||||||
|
trackhash = cls.map.get(filepath)
|
||||||
|
|
||||||
|
if trackhash:
|
||||||
|
track = TrackStore.trackhashmap.get(trackhash)
|
||||||
|
|
||||||
|
if track:
|
||||||
|
yield [t for t in track.tracks if t.filepath == filepath][0]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def count_tracks_containing_paths(cls, paths: list[str]):
|
def count_tracks_containing_paths(cls, paths: list[str]):
|
||||||
|
|||||||
+232
-68
@@ -1,18 +1,99 @@
|
|||||||
# from tqdm import tqdm
|
# from tqdm import tqdm
|
||||||
|
|
||||||
|
import itertools
|
||||||
|
import sys
|
||||||
|
from typing import Callable
|
||||||
from flask_jwt_extended import current_user
|
from flask_jwt_extended import current_user
|
||||||
|
from app.db.libdata import TrackTable
|
||||||
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
|
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
|
||||||
from app.db.sqlite.tracks import SQLiteTrackMethods as trackdb
|
|
||||||
|
# from app.db.sqlite.tracks import SQLiteTrackMethods as trackdb
|
||||||
|
from app.db.userdata import FavoritesTable
|
||||||
from app.models import Track
|
from app.models import Track
|
||||||
from app.utils.bisection import use_bisection
|
|
||||||
from app.utils.customlist import CustomList
|
|
||||||
from app.utils.remove_duplicates import remove_duplicates
|
from app.utils.remove_duplicates import remove_duplicates
|
||||||
|
|
||||||
TRACKS_LOAD_KEY = ""
|
TRACKS_LOAD_KEY = ""
|
||||||
|
|
||||||
|
|
||||||
|
class TrackGroup:
|
||||||
|
"""
|
||||||
|
Tracks grouped under the same trackhash.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, tracks: list[Track]):
|
||||||
|
self.tracks = tracks
|
||||||
|
|
||||||
|
def append(self, track: Track):
|
||||||
|
"""
|
||||||
|
Adds a track to the group.
|
||||||
|
"""
|
||||||
|
self.tracks.append(track)
|
||||||
|
|
||||||
|
def remove(self, track: Track):
|
||||||
|
"""
|
||||||
|
Removes a track from the group.
|
||||||
|
"""
|
||||||
|
self.tracks.remove(track)
|
||||||
|
|
||||||
|
def set_fav_userids(self, userids: set[int]):
|
||||||
|
"""
|
||||||
|
Sets the favorite userids.
|
||||||
|
"""
|
||||||
|
for track in self.tracks:
|
||||||
|
track.fav_userids = userids
|
||||||
|
|
||||||
|
def get_best(self):
|
||||||
|
"""
|
||||||
|
Returns the track with higest bitrate.
|
||||||
|
"""
|
||||||
|
return max(self.tracks, key=lambda x: x.bitrate)
|
||||||
|
|
||||||
|
def toggle_favorite(self, remove: bool = False):
|
||||||
|
"""
|
||||||
|
Adds a track to the favorites.
|
||||||
|
"""
|
||||||
|
|
||||||
|
userids = set(self.tracks[0].fav_userids)
|
||||||
|
|
||||||
|
if remove:
|
||||||
|
userids.remove(current_user["id"])
|
||||||
|
else:
|
||||||
|
userids.add(current_user["id"])
|
||||||
|
|
||||||
|
for track in self.tracks:
|
||||||
|
track.fav_userids = userids
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.tracks)
|
||||||
|
|
||||||
|
|
||||||
|
class classproperty(property):
|
||||||
|
"""
|
||||||
|
A class property decorator.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __get__(self, owner_self, owner_cls):
|
||||||
|
return self.fget(owner_cls)
|
||||||
|
|
||||||
|
|
||||||
class TrackStore:
|
class TrackStore:
|
||||||
tracks: list[Track] = CustomList()
|
# {'trackhash': Track[]}
|
||||||
|
trackhashmap: dict[str, TrackGroup] = dict()
|
||||||
|
|
||||||
|
@classproperty
|
||||||
|
def tracks(cls) -> list[Track]:
|
||||||
|
return cls.get_flat_list()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_flat_list(cls):
|
||||||
|
"""
|
||||||
|
Returns a flat list of all tracks.
|
||||||
|
"""
|
||||||
|
return list(
|
||||||
|
itertools.chain.from_iterable(
|
||||||
|
[group.tracks for group in cls.trackhashmap.values()]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_all_tracks(cls, instance_key: str):
|
def load_all_tracks(cls, instance_key: str):
|
||||||
@@ -24,32 +105,60 @@ class TrackStore:
|
|||||||
global TRACKS_LOAD_KEY
|
global TRACKS_LOAD_KEY
|
||||||
TRACKS_LOAD_KEY = instance_key
|
TRACKS_LOAD_KEY = instance_key
|
||||||
|
|
||||||
cls.tracks = CustomList(trackdb.get_all_tracks())
|
cls.trackhashmap = dict()
|
||||||
|
tracks = TrackTable.get_all()
|
||||||
|
|
||||||
favs = favdb.get_fav_tracks()
|
# INFO: Load all tracks into the dict store
|
||||||
|
for track in tracks:
|
||||||
records = dict()
|
|
||||||
|
|
||||||
for fav in favs:
|
|
||||||
r = records.setdefault(fav[1], set())
|
|
||||||
r.add(fav[4])
|
|
||||||
|
|
||||||
for track in cls.tracks:
|
|
||||||
if instance_key != TRACKS_LOAD_KEY:
|
if instance_key != TRACKS_LOAD_KEY:
|
||||||
return
|
return
|
||||||
|
|
||||||
userids = records.get(track.trackhash, set())
|
exists = cls.trackhashmap.get(track.trackhash, None)
|
||||||
track.fav_userids = list(userids)
|
if not exists:
|
||||||
|
cls.trackhashmap[track.trackhash] = TrackGroup([track])
|
||||||
|
else:
|
||||||
|
cls.trackhashmap[track.trackhash].append(track)
|
||||||
|
|
||||||
print("Done!")
|
# favs = favdb.get_fav_tracks()
|
||||||
|
favs = FavoritesTable.get_all()
|
||||||
|
records: dict[str, set[int]] = dict()
|
||||||
|
|
||||||
|
# convert records: {trackhash: {userid, userid, ...}}
|
||||||
|
for fav in favs:
|
||||||
|
if fav.hash not in records:
|
||||||
|
# if trackhash not in dict, add it
|
||||||
|
# and set the value to a set containing the userid
|
||||||
|
records[fav.hash] = {fav.userid}
|
||||||
|
|
||||||
|
# if trackhash is in dict, add the userid to the set
|
||||||
|
records[fav.hash].add(fav.userid)
|
||||||
|
|
||||||
|
for record in records:
|
||||||
|
if instance_key != TRACKS_LOAD_KEY:
|
||||||
|
return
|
||||||
|
|
||||||
|
group = cls.trackhashmap.get(record, None)
|
||||||
|
|
||||||
|
if not group:
|
||||||
|
continue
|
||||||
|
|
||||||
|
group.set_fav_userids(records.get(record, set()))
|
||||||
|
|
||||||
|
# print("Done!")
|
||||||
|
# print(cls.trackhashmap.get("0d6b22c19c").tracks[0].fav_userids)
|
||||||
|
# sys.exit(0)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add_track(cls, track: Track):
|
def add_track(cls, track: Track):
|
||||||
"""
|
"""
|
||||||
Adds a single track to the store.
|
Adds a single track to the store.
|
||||||
"""
|
"""
|
||||||
|
group = cls.trackhashmap.get(track.trackhash, None)
|
||||||
|
|
||||||
cls.tracks.append(track)
|
if group:
|
||||||
|
return group.append(track)
|
||||||
|
|
||||||
|
cls.trackhashmap[track.trackhash] = TrackGroup([track])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add_tracks(cls, tracks: list[Track]):
|
def add_tracks(cls, tracks: list[Track]):
|
||||||
@@ -57,17 +166,21 @@ class TrackStore:
|
|||||||
Adds multiple tracks to the store.
|
Adds multiple tracks to the store.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cls.tracks.extend(tracks)
|
for track in tracks:
|
||||||
|
cls.add_track(track)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remove_track_obj(cls, track: Track):
|
def remove_track(cls, track: Track):
|
||||||
"""
|
"""
|
||||||
Removes a single track from the store.
|
Removes a single track from the store.
|
||||||
"""
|
"""
|
||||||
try:
|
group = cls.trackhashmap.get(track.trackhash, None)
|
||||||
cls.tracks.remove(track)
|
|
||||||
except ValueError:
|
if group:
|
||||||
pass
|
group.remove(track)
|
||||||
|
|
||||||
|
if len(group) == 0:
|
||||||
|
del cls.trackhashmap[track.trackhash]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remove_track_by_filepath(cls, filepath: str):
|
def remove_track_by_filepath(cls, filepath: str):
|
||||||
@@ -75,10 +188,7 @@ class TrackStore:
|
|||||||
Removes a track from the store by its filepath.
|
Removes a track from the store by its filepath.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for track in cls.tracks:
|
return cls.remove_tracks_by_filepaths({filepath})
|
||||||
if track.filepath == filepath:
|
|
||||||
cls.remove_track_obj(track)
|
|
||||||
break
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remove_tracks_by_filepaths(cls, filepaths: set[str]):
|
def remove_tracks_by_filepaths(cls, filepaths: set[str]):
|
||||||
@@ -86,47 +196,47 @@ class TrackStore:
|
|||||||
Removes multiple tracks from the store by their filepaths.
|
Removes multiple tracks from the store by their filepaths.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for track in cls.tracks:
|
filecount = len(filepaths)
|
||||||
if track.filepath in filepaths:
|
|
||||||
cls.remove_track_obj(track)
|
for trackhash in cls.trackhashmap:
|
||||||
|
group = cls.trackhashmap[trackhash]
|
||||||
|
|
||||||
|
for track in group.tracks:
|
||||||
|
if track.filepath in filepaths:
|
||||||
|
group.remove(track)
|
||||||
|
|
||||||
|
if len(group) == 0:
|
||||||
|
del cls.trackhashmap[trackhash]
|
||||||
|
|
||||||
|
filecount -= 1
|
||||||
|
|
||||||
|
if filecount == 0:
|
||||||
|
break
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def count_tracks_by_trackhash(cls, trackhash: str) -> int:
|
def count_tracks_by_trackhash(cls, trackhash: str) -> int:
|
||||||
"""
|
"""
|
||||||
Counts the number of tracks with a specific trackhash.
|
Counts the number of tracks with a specific trackhash.
|
||||||
"""
|
"""
|
||||||
return sum(1 for track in cls.tracks if track.trackhash == trackhash)
|
return len(cls.trackhashmap.get(trackhash, []))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def make_track_fav(cls, trackhash: str):
|
def toggle_favorite(cls, trackhash: str, remove: bool = False):
|
||||||
"""
|
"""
|
||||||
Adds a track to the favorites.
|
Adds a track to the favorites.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for track in cls.tracks:
|
group = cls.trackhashmap.get(trackhash)
|
||||||
if track.trackhash == trackhash:
|
|
||||||
if current_user["id"] not in track.fav_userids:
|
if group:
|
||||||
track.fav_userids.append(current_user["id"])
|
group.toggle_favorite(remove=remove)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remove_track_from_fav(cls, trackhash: str):
|
def remove_track_from_fav(cls, trackhash: str):
|
||||||
"""
|
"""
|
||||||
Removes a track from the favorites.
|
Removes a track from the favorites.
|
||||||
"""
|
"""
|
||||||
|
return cls.toggle_favorite(trackhash, remove=True)
|
||||||
for track in cls.tracks:
|
|
||||||
if track.trackhash == trackhash:
|
|
||||||
if current_user["id"] in track.fav_userids:
|
|
||||||
track.fav_userids.remove(current_user["id"])
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def append_track_artists(
|
|
||||||
cls, albumhash: str, artists: list[str], new_album_title: str
|
|
||||||
):
|
|
||||||
tracks = cls.get_tracks_by_albumhash(albumhash)
|
|
||||||
|
|
||||||
for track in tracks:
|
|
||||||
track.add_artists(artists, new_album_title)
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# ================== GETTERS =====================
|
# ================== GETTERS =====================
|
||||||
@@ -138,16 +248,16 @@ class TrackStore:
|
|||||||
Returns a list of tracks by their hashes.
|
Returns a list of tracks by their hashes.
|
||||||
"""
|
"""
|
||||||
hash_set = set(trackhashes)
|
hash_set = set(trackhashes)
|
||||||
set_len = len(hash_set)
|
|
||||||
|
|
||||||
tracks = []
|
tracks: list[Track] = []
|
||||||
for track in cls.tracks:
|
|
||||||
if track.trackhash in hash_set:
|
for trackhash in hash_set:
|
||||||
|
group = cls.trackhashmap.get(trackhash, None)
|
||||||
|
|
||||||
|
if group:
|
||||||
|
track = group.get_best()
|
||||||
tracks.append(track)
|
tracks.append(track)
|
||||||
|
|
||||||
if len(tracks) == set_len:
|
|
||||||
break
|
|
||||||
|
|
||||||
# sort the tracks in the order of the given trackhashes
|
# sort the tracks in the order of the given trackhashes
|
||||||
tracks.sort(key=lambda t: trackhashes.index(t.trackhash))
|
tracks.sort(key=lambda t: trackhashes.index(t.trackhash))
|
||||||
return tracks
|
return tracks
|
||||||
@@ -156,32 +266,86 @@ class TrackStore:
|
|||||||
def get_tracks_by_filepaths(cls, paths: list[str]) -> list[Track]:
|
def get_tracks_by_filepaths(cls, paths: list[str]) -> list[Track]:
|
||||||
"""
|
"""
|
||||||
Returns all tracks matching the given paths.
|
Returns all tracks matching the given paths.
|
||||||
|
|
||||||
|
⛔⛔⛔⛔⛔⛔⛔⛔⛔⛔⛔⛔⛔⛔⛔⛔⛔⛔⛔⛔⛔⛔
|
||||||
"""
|
"""
|
||||||
tracks = sorted(cls.tracks, key=lambda x: x.filepath)
|
# tracks = sorted(cls.trackhashmap, key=lambda x: x.filepath)
|
||||||
tracks = use_bisection(tracks, "filepath", paths)
|
# tracks = use_bisection(tracks, "filepath", paths)
|
||||||
return [track for track in tracks if track is not None]
|
# return [track for track in tracks if track is not None]
|
||||||
|
# return cls.find_tracks_by(key="filepath", value=paths)
|
||||||
|
|
||||||
|
tracks: list[Track] = []
|
||||||
|
|
||||||
|
for trackhash in cls.trackhashmap:
|
||||||
|
group = cls.trackhashmap.get(trackhash)
|
||||||
|
|
||||||
|
if not group:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for track in group.tracks:
|
||||||
|
if track.filepath in paths:
|
||||||
|
tracks.append(track)
|
||||||
|
|
||||||
|
return tracks
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def find_tracks_by(
|
||||||
|
cls,
|
||||||
|
key: str,
|
||||||
|
value: str,
|
||||||
|
predicate: Callable = lambda prop_value, value: prop_value == value,
|
||||||
|
including_duplicates: bool = False,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Find all tracks by a specific key.
|
||||||
|
"""
|
||||||
|
tracks: list[Track] = []
|
||||||
|
|
||||||
|
for trackhash in cls.trackhashmap:
|
||||||
|
group = cls.trackhashmap.get(trackhash, None)
|
||||||
|
|
||||||
|
if not group:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for track in group.tracks:
|
||||||
|
prop_value = getattr(track, key)
|
||||||
|
if predicate(prop_value, value):
|
||||||
|
tracks.append(track)
|
||||||
|
|
||||||
|
if including_duplicates:
|
||||||
|
return tracks
|
||||||
|
|
||||||
|
return remove_duplicates(tracks)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_tracks_by_albumhash(cls, album_hash: str) -> list[Track]:
|
def get_tracks_by_albumhash(cls, album_hash: str) -> list[Track]:
|
||||||
"""
|
"""
|
||||||
Returns all tracks matching the given album hash.
|
Returns all tracks matching the given album hash.
|
||||||
"""
|
"""
|
||||||
tracks = [t for t in cls.tracks if t.albumhash == album_hash]
|
return cls.find_tracks_by(key="albumhash", value=album_hash)
|
||||||
return remove_duplicates(tracks, is_album_tracks=True)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_tracks_by_artisthash(cls, artisthash: str):
|
def get_tracks_by_artisthash(cls, artisthash: str):
|
||||||
"""
|
"""
|
||||||
Returns all tracks matching the given artist. Duplicate tracks are removed.
|
Returns all tracks matching the given artist. Duplicate tracks are removed.
|
||||||
"""
|
"""
|
||||||
tracks = [t for t in cls.tracks if artisthash in t.artist_hashes]
|
predicate = lambda artisthashes, artisthash: artisthash in artisthashes
|
||||||
tracks = remove_duplicates(tracks)
|
return cls.find_tracks_by(
|
||||||
tracks.sort(key=lambda x: x.last_mod)
|
key="artist_hashes", value=artisthash, predicate=predicate
|
||||||
return tracks
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_tracks_in_path(cls, path: str):
|
def get_tracks_in_path(cls, path: str):
|
||||||
"""
|
"""
|
||||||
Returns all tracks in the given path.
|
Returns all tracks in the given path.
|
||||||
"""
|
"""
|
||||||
return (t for t in cls.tracks if t.folder.startswith(path))
|
predicate: Callable[[str, str], bool] = (
|
||||||
|
lambda track_folder, path: track_folder.startswith(path)
|
||||||
|
)
|
||||||
|
|
||||||
|
return cls.find_tracks_by(
|
||||||
|
key="folder",
|
||||||
|
value=path,
|
||||||
|
predicate=predicate,
|
||||||
|
including_duplicates=True,
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user