mirror of
https://github.com/bspeice/Melodia
synced 2024-12-25 08:08:13 -05:00
Commit basic scanning support for songs
This commit is contained in:
parent
d31961e029
commit
d057b2f455
@ -41,7 +41,7 @@ class Archive (models.Model):
|
|||||||
#And a reference to the songs in this archive
|
#And a reference to the songs in this archive
|
||||||
songs = models.ManyToManyField(Song)
|
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"
|
"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
|
#This method is implemented since the other scan methods all need to use the same code
|
||||||
#DRY FTW
|
#DRY FTW
|
||||||
@ -64,35 +64,28 @@ class Archive (models.Model):
|
|||||||
|
|
||||||
except ObjectDoesNotExist, e:
|
except ObjectDoesNotExist, e:
|
||||||
#Song needs to be added to database
|
#Song needs to be added to database
|
||||||
print "Adding song: " + filename
|
|
||||||
|
|
||||||
full_url = os.path.join(dirname, filename)
|
full_url = os.path.join(dirname, filename)
|
||||||
new_song = Song(url = full_url)
|
new_song = Song(url = full_url)
|
||||||
|
|
||||||
f = open(full_url)
|
|
||||||
new_song.file_hash = hash(f.read())
|
|
||||||
new_song.populate_metadata()
|
new_song.populate_metadata()
|
||||||
|
|
||||||
new_song.save()
|
new_song.save()
|
||||||
|
|
||||||
self.songs.add(new_song)
|
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."
|
"Scan this archive's root folder and make sure that all songs are in the database."
|
||||||
|
|
||||||
from os.path import isfile
|
from os.path import isfile
|
||||||
|
|
||||||
#Validate existing database results
|
#Validate existing database results
|
||||||
for song in self.songs.all():
|
for song in self.songs.all():
|
||||||
if not isfile(song.song_url):
|
if not isfile(song.url):
|
||||||
song.delete()
|
song.delete()
|
||||||
|
|
||||||
#Scan the root folder, and find if we need to add any new songs
|
#Scan the root folder, and find if we need to add any new songs
|
||||||
self._scan_filesystem
|
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"
|
|
||||||
|
|
||||||
|
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
|
#Overload the regular hash function with whatever Melodia as a whole is using
|
||||||
from Melodia.melodia_settings import HASH_FUNCTION as hash
|
from Melodia.melodia_settings import HASH_FUNCTION as hash
|
||||||
import os.path
|
import os.path
|
||||||
@ -116,3 +109,30 @@ class Archive (models.Model):
|
|||||||
#Make sure to add any new songs as well
|
#Make sure to add any new songs as well
|
||||||
self._scan_filesystem()
|
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)
|
genre = models.CharField(max_length = 64)
|
||||||
bpm = models.IntegerField()
|
bpm = models.IntegerField()
|
||||||
|
|
||||||
|
|
||||||
#File metadata
|
#File metadata
|
||||||
bit_rate = models.IntegerField()
|
bit_rate = models.IntegerField()
|
||||||
duration = models.IntegerField()
|
duration = models.IntegerField()
|
||||||
@ -31,17 +30,52 @@ class Song (models.Model):
|
|||||||
url = models.CharField(max_length = 64)
|
url = models.CharField(max_length = 64)
|
||||||
file_hash = melodia_settings.HASH_RESULT_DB_TYPE
|
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"
|
"Populate the metadata of this song"
|
||||||
#Will eventually use EchoNest to power this. For now, just use defaults.
|
|
||||||
import datetime
|
import datetime
|
||||||
self.title = "_"
|
|
||||||
self.artist = "_"
|
|
||||||
self.album = "_"
|
|
||||||
self.release_date = datetime.datetime.now()
|
|
||||||
self.genre = "_"
|
|
||||||
self.bpm = 0
|
|
||||||
|
|
||||||
self.bit_rate = 0
|
if use_echonest:
|
||||||
self.duration = 0
|
#Code to grab metadata from echonest here
|
||||||
self.echonest_song_id = "_"
|
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())
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user