mirror of
				https://github.com/bspeice/Melodia
				synced 2025-10-25 22:40:42 -04:00 
			
		
		
		
	Commit basic scanning support for songs
This commit is contained in:
		| @ -41,7 +41,7 @@ class Archive (models.Model): | ||||
| 	#And a reference to the songs in this archive | ||||
| 	songs       = models.ManyToManyField(Song) | ||||
|  | ||||
| 	def _scan_filesystem(self): | ||||
| 	def _scan_filesystem(self, progress_callback = lambda x: None): | ||||
| 		"Scan the archive's root filesystem and add any new songs" | ||||
| 		#This method is implemented since the other scan methods all need to use the same code | ||||
| 		#DRY FTW | ||||
| @ -64,35 +64,28 @@ class Archive (models.Model): | ||||
|  | ||||
| 					except ObjectDoesNotExist, e: | ||||
| 						#Song needs to be added to database | ||||
| 						print "Adding song: " + filename | ||||
|  | ||||
| 						full_url = os.path.join(dirname, filename) | ||||
| 						new_song = Song(url = full_url) | ||||
|  | ||||
| 						f                  = open(full_url) | ||||
| 						new_song.file_hash = hash(f.read()) | ||||
| 						new_song.populate_metadata() | ||||
|  | ||||
| 						new_song.save() | ||||
| 						 | ||||
| 						self.songs.add(new_song) | ||||
|  | ||||
| 	def scan(self): | ||||
| 	def quick_scan(self): | ||||
| 		"Scan this archive's root folder and make sure that	all songs are in the database." | ||||
|  | ||||
| 		from os.path import isfile | ||||
|  | ||||
| 		#Validate existing database results | ||||
| 		for song in self.songs.all(): | ||||
| 			if not isfile(song.song_url): | ||||
| 			if not isfile(song.url): | ||||
| 				song.delete() | ||||
|  | ||||
| 		#Scan the root folder, and find if we need to add any new songs | ||||
| 		self._scan_filesystem | ||||
|  | ||||
| 	def deep_scan(self): | ||||
| 		"Scan this archive's root folder and make sure that	all songs are in the database, and update metadata as necessary" | ||||
| 		self._scan_filesystem() | ||||
|  | ||||
| 	def scan(self): | ||||
| 		"Scan this archive's root folder and make sure any local metadata are correct." | ||||
| 		#Overload the regular hash function with whatever Melodia as a whole is using | ||||
| 		from Melodia.melodia_settings import HASH_FUNCTION as hash | ||||
| 		import os.path | ||||
| @ -116,3 +109,30 @@ class Archive (models.Model): | ||||
| 		#Make sure to add any new songs as well | ||||
| 		self._scan_filesystem() | ||||
|  | ||||
|  | ||||
| 	def deep_scan(self): | ||||
| 		"Scan this archive's root folder and make sure that	all songs are in the database, and use EchoNest to update metadata as necessary" | ||||
|  | ||||
| 		#Overload the regular hash function with whatever Melodia as a whole is using | ||||
| 		from Melodia.melodia_settings import HASH_FUNCTION as hash | ||||
| 		import os.path | ||||
|  | ||||
| 		for song in self.songs.all(): | ||||
|  | ||||
| 			if not os.path.isfile(song.song_url): | ||||
| 				song.delete() | ||||
| 				continue | ||||
|  | ||||
| 			#The song exists, check that the hash is the same | ||||
| 			db_hash = song.file_hash | ||||
| 			 | ||||
| 			f         = open(song_url) | ||||
| 			file_hash = hash(f.read()) | ||||
|  | ||||
| 			if file_hash != db_hash: | ||||
| 				#Something about the song has changed, rescan the metadata | ||||
| 				song.populate_metadata(use_echonest = True) | ||||
|  | ||||
| 		#Make sure to add any new songs as well | ||||
| 		self._scan_filesystem() | ||||
|  | ||||
|  | ||||
| @ -23,7 +23,6 @@ class Song (models.Model): | ||||
| 	genre        = models.CharField(max_length = 64) | ||||
| 	bpm          = models.IntegerField() | ||||
|  | ||||
|  | ||||
| 	#File metadata | ||||
| 	bit_rate         = models.IntegerField() | ||||
| 	duration         = models.IntegerField() | ||||
| @ -31,17 +30,52 @@ class Song (models.Model): | ||||
| 	url              = models.CharField(max_length = 64) | ||||
| 	file_hash        = melodia_settings.HASH_RESULT_DB_TYPE | ||||
|  | ||||
| 	def populate_metadata(self): | ||||
| 	def populate_metadata(self, use_echonest = False, use_musicbrainz = False): | ||||
| 		"Populate the metadata of this song" | ||||
| 		#Will eventually use EchoNest to power this. For now, just use defaults. | ||||
| 		import datetime | ||||
| 		self.title        = "_" | ||||
| 		self.artist       = "_" | ||||
| 		self.album        = "_" | ||||
| 		self.release_date = datetime.datetime.now() | ||||
| 		self.genre        = "_" | ||||
| 		self.bpm          = 0 | ||||
|  | ||||
| 		self.bit_rate         = 0 | ||||
| 		self.duration         = 0 | ||||
| 		self.echonest_song_id = "_" | ||||
| 		if use_echonest: | ||||
| 			#Code to grab metadata from echonest here | ||||
| 			pass | ||||
|  | ||||
| 		else: | ||||
| 			#Grab metadata for the database using what is in the track. | ||||
| 			from Melodia.resources import add_resource_dir | ||||
| 			add_resource_dir() | ||||
|  | ||||
| 			import audiotools | ||||
|  | ||||
| 			try: | ||||
| 				track                 = audiotools.open(self.url) | ||||
| 				track_metadata        = track.get_metadata() | ||||
|  | ||||
| 				self.title            = track_metadata.track_name             or '<UNAVAILABLE>' | ||||
| 				self.artist           = track_metadata.artist_name            or '<UNAVAILABLE>' | ||||
| 				self.album            = track_metadata.album_name             or '<UNAVAILABLE>' | ||||
| 				self.release_date     = datetime.date(int(track_metadata.year or 1), 1, 1) | ||||
| 				self.bpm              = -1 | ||||
|  | ||||
| 				self.bit_rate         = track.bits_per_sample()               or '<UNAVAILABLE>' | ||||
| 				self.duration         = int(track.seconds_length())             or '<UNAVAILABLE>' | ||||
| 				self.echonest_song_id = '' | ||||
|  | ||||
| 			except audiotools.UnsupportedFile, e: | ||||
| 				#Couldn't grab the local data | ||||
| 				#doesn't support the file, or because reading from it caused an error | ||||
| 				self.title            = "<UNAVAILABLE>" | ||||
| 				self.artist           = "<UNAVAILABLE>" | ||||
| 				self.album            = "<UNAVAILABLE>" | ||||
| 				self.release_date     = datetime.datetime.now() | ||||
| 				self.bpm              = -1 | ||||
|  | ||||
| 				self.bit_rate         = -1 | ||||
| 				self.duration         = -1 | ||||
| 				self.echonest_song_id = '' | ||||
|  | ||||
| 		#Hash check is run regardless of what metadata method is used | ||||
| 		if self.file_hash == None: | ||||
| 			#Only get the hash if we really must, it's an expensive operation... | ||||
| 			from Melodia.melodia_settings import HASH_FUNCTION as hash | ||||
| 			f              = open(self.url, 'rb') | ||||
| 			self.file_hash = hash(f.read()) | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Bradlee Speice
					Bradlee Speice