indexer.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import time
  2. import vlc
  3. from path import Path
  4. from core import logging_
  5. from core.exceptions import NotSupportedFile
  6. from core.file_utilities import is_media_file_ext, hash_file
  7. from core.logging_ import Logger
  8. from core.models import Track
  9. from core.repositories import MusicFolderRepository, TrackRepository
  10. logger = Logger.get()
  11. class Indexation:
  12. def __init__(self):
  13. self.started = False
  14. self.music_folder_repo = MusicFolderRepository()
  15. self.track_repo = TrackRepository()
  16. self.music_folders = []
  17. self.index = {}
  18. self.processed = set()
  19. self.t0 = time.time()
  20. def index_file(self, music_folder, filename, force_update=False):
  21. filename = Path(filename)
  22. if not filename.exists():
  23. raise FileNotFoundError(f"File not found: {filename}")
  24. if not is_media_file_ext(filename.ext):
  25. raise NotSupportedFile(f"File's extension {filename.ext} is not supported")
  26. vlc_media = vlc.Media(filename)
  27. vlc_media.parse()
  28. track_infos = vlc_media.get_tracks_info()
  29. track_hash = hash_file(filename)
  30. if track_hash in self.processed:
  31. print(" ... file already indexed, ignore: ", filename)
  32. return
  33. if self.index and track_hash in self.index:
  34. track = self.index[track_hash]
  35. else:
  36. track = next(iter(self.track_repo.get_by('hash', track_hash)), None) or Track()
  37. if track.id and not force_update:
  38. return track
  39. track.profile_id = 0
  40. track.music_folder_id = music_folder.id
  41. track.title = vlc_media.get_meta(vlc.Meta.Title)
  42. track.format = filename.ext
  43. track.artist = vlc_media.get_meta(vlc.Meta.AlbumArtist) or vlc_media.get_meta(vlc.Meta.Artist)
  44. track.album = vlc_media.get_meta(vlc.Meta.Album)
  45. track.track_num = vlc_media.get_meta(vlc.Meta.TrackNumber)
  46. # track.year = vlc_media.get_meta(vlc.Meta.Date)
  47. # track.duration = vlc_media.get_meta(vlc.Meta.Date)
  48. # track.size = 0
  49. track.note = ""
  50. track.status = Track.STATUS_FOUND
  51. track.path = filename
  52. track.hash = track_hash
  53. if track.id is not None:
  54. self.track_repo.update(track)
  55. logger.debug('Index - updated: %s' % filename)
  56. else:
  57. self.track_repo.create(track)
  58. logger.debug('Index - created: %s' % filename)
  59. self.track_repo.commit()
  60. return track
  61. def index_all(self, filter_music_folder_id=None, force_update=False):
  62. self.index = {t.hash: t for t in self.track_repo.get_all()}
  63. self.processed = set()
  64. self.t0 = time.time()
  65. self.started = True
  66. if filter_music_folder_id:
  67. music_folders = [self.music_folder_repo.get_by_id(filter_music_folder_id)]
  68. else:
  69. music_folders = self.music_folder_repo.get_all()
  70. # add and update tracks
  71. for music_folder in music_folders:
  72. music_folder_path = Path(music_folder.path)
  73. for filename in music_folder_path.walkfiles():
  74. if not is_media_file_ext(filename.ext):
  75. continue
  76. track = self.index_file(music_folder, filename, force_update=force_update)
  77. self.processed.add(track.hash)
  78. # mark missings
  79. for hash_, track in self.index.items():
  80. if hash_ in self.processed:
  81. continue
  82. track.status = Track.STATUS_UNAVAILABLE
  83. self.track_repo.update(track, True)
  84. logger.debug('Index - marked as unavailable: %s' % track.path)
  85. class Indexer:
  86. @staticmethod
  87. def index_file(music_folder, path, force_update=False):
  88. indexation = Indexation()
  89. indexation.index_file(music_folder, path, force_update=force_update)
  90. @staticmethod
  91. def index_folder(music_folder, force_update=False):
  92. logger.debug('** Start indexation on folder %s' % music_folder.id)
  93. indexation = Indexation()
  94. indexation.index_all(filter_music_folder_id=music_folder.id, force_update=force_update)
  95. @staticmethod
  96. def index_all(force_update=False):
  97. logger.debug('** Start complete indexation')
  98. indexation = Indexation()
  99. indexation.index_all(force_update=force_update)
  100. if __name__ == '__main__':
  101. Indexer.index_all()