def config_settings_new_theme(request): """The settings view for creating a new xml api user """ # get form debug = LaudioDebugger() if request.method == 'POST': theme_form = ThemeForm(request.POST, request.FILES) if theme_form.is_valid(): try: theme_form.install_theme(request.FILES['theme']) except (tarfile.CompressionError, tarfile.ReadError, TypeError), msg: debug.log('Theme Upload', msg) return HttpResponseRedirect(reverse('player:config_settings')) ctx = { 'theme_form': theme_form } return csrf_render(request, 'config/settings_new_theme.html', ctx)
def config_settings_delete_theme(request, themename): """The settings view for deleting a user Keyword arguments: userid -- The id of the user """ if request.method == 'POST': # todo unlink theme if themename != 'default': themes_dir = os.path.join(settings.MEDIA_ROOT, 'themes/') theme_path = os.path.join(themes_dir, themename) shutil.rmtree(theme_path) else: debug = LaudioDebugger() debug.log('Theme Deletion', 'Can not delete default theme') return HttpResponseRedirect(reverse('player:config_settings')) else: ctx = { 'themename': themename } return csrf_render(request, 'config/settings_delete_theme.html', ctx)
def __init__(self, musicDir=LaudioConfig(settings.LAUDIO_CFG).collectionPath): """ Instances some attributes and sets the music directory Keyword arguments: musicDir -- the directory where musiccollection lies; the string has to end with a slash because we save the relative path if not given, the collectionpath from the settings is used """ self.musicDir = musicDir self.scanned = 0 self.added = 0 self.modified = 0 self.broken = [] self.noRights = [] self._debugger = LaudioDebugger() self.scanLog = ScanProgressor()
def __init__(self, path): """Generates the javascript from templates Keyword arguments: path -- The path to the song """ self.path = path self.modified = False self.added = False self.date = 0 self.artist = '' self.title = '' self.album = '' self.genre = '' self.length = 0 self.bitrate = 0 self.tracknumber = 0 self.size = os.path.getsize(self.path) self.lastModified = datetime.datetime.fromtimestamp( os.stat(path).st_mtime ) self._debugger = LaudioDebugger()
class MusicScanner(object): """ Class for scanning the files in your collection Usage: scanner = MusicScanner(path) # path is optional scanner.scan() """ def __init__(self, musicDir=LaudioConfig(settings.LAUDIO_CFG).collectionPath): """ Instances some attributes and sets the music directory Keyword arguments: musicDir -- the directory where musiccollection lies; the string has to end with a slash because we save the relative path if not given, the collectionpath from the settings is used """ self.musicDir = musicDir self.scanned = 0 self.added = 0 self.modified = 0 self.broken = [] self.noRights = [] self._debugger = LaudioDebugger() self.scanLog = ScanProgressor() def scan(self): """ Scans a directory recursively for ogg files """ # scan all files fileList = [] for root, directories, files in os.walk(self.musicDir): for name in files: if name.lower().endswith('.ogg') or name.lower().endswith('.oga') \ or name.lower().endswith('mp3'): fileList.append( os.path.join( root, name ) ) # add a new scan entry num_files = len(fileList) self.scanLog.setTotal(num_files) self._debugger.log('Music Scanner', 'Begin scan of %i songs' % num_files) # now add the files to the db for name in fileList: # ogg vorbis if name.lower().endswith('.ogg') or name.lower().endswith('.oga'): try: self._addSong( VorbisSong(name) ) except mutagen.oggvorbis.OggVorbisHeaderError: self.broken.append(name) # mp3 if name.lower().endswith('.mp3'): self._addSong( MP3Song(name) ) self._debugger.log('Music Scanner', 'Finished scan') # reset count after finish self.scanLog.reset() def _addSong(self, musicFile): """ Add a song to the database. Keyword arguments: musicFile -- The song object """ self.scanLog.updateScannedTracks() try: musicFile.save() if musicFile.modified: self.modified += 1 if musicFile.added: self.added += 1 except IOError: self.noRights.append(musicFile.path) def rmNonExist(self): """Removes tracks from the database which are not on the drive any more""" self._debugger.log('Music Scanner', 'Removing non existent songs from database') songs = Song.objects.all() for song in songs: if not os.path.exists(song.path): song.delete() self._debugger.log('Music Scanner', 'Removed %s from db: file does \ not exist any more' % song.path) def reset(self): """Removes all scanned entries from the db """ # TODO: delete via raw sql self._debugger.log('Music Scanner', 'Resetting Database') # Song.objects.all().delete() causes database errors for item in Song.objects.all(): item.delete() for item in Artist.objects.all(): item.delete() for item in Genre.objects.all(): item.delete() for item in Album.objects.all(): item.delete() for item in Playlist.objects.all(): item.delete() self._debugger.log('Music Scanner', 'Resetted Database')
class Song(object): """ This is a baseclass for songs which provides methods to save and update a song in the database. This class is abstract and should not be instantiated by itself Usage: # we have to use an inherited class, for instance CodecClass song = CodecClass("/path/to/file.codec") song.save() """ # static vars for debug purposes added = 0 modified = 0 def __init__(self, path): """Generates the javascript from templates Keyword arguments: path -- The path to the song """ self.path = path self.modified = False self.added = False self.date = 0 self.artist = '' self.title = '' self.album = '' self.genre = '' self.length = 0 self.bitrate = 0 self.tracknumber = 0 self.size = os.path.getsize(self.path) self.lastModified = datetime.datetime.fromtimestamp( os.stat(path).st_mtime ) self._debugger = LaudioDebugger() def __setattr__(self, name, value): """Setter""" # check and correct weird dates if name == 'date': if isinstance(value, str): regex = r'^(\d{1,4})-?.*' year = re.search(regex, value) try: if year: value = int( year.group(1) ) except ValueError: value = '' # handle empty titles elif name == 'title' and value == '': value = os.path.basename(self.path) object.__setattr__(self, name, value) def getModel(self): """ Checks if the song exists in the database. To do this, the path in the database is compared to the path of the song object. If the two paths match, then the song model which we have to use is returned, otherwise false """ try: song = SongModel.objects.get(path=self.path) return song except SongModel.DoesNotExist: return SongModel() def isModified(self, song): """ Returns true if the timestamp from the file is newer than the Database entry Keyword arguments song -- The database instance of a song. If song is not given a new song will be created and saved in the database """ return song.lastmodified != self.lastModified def save(self): """ Saves the values of the object into the database """ # get the database model of the song modi = True song = self.getModel() if not song.lastmodified: modi = False song.lastmodified = 0 # only save to database if song is modified if self.isModified(song): # debug if modi: self.modfied = True self._debugger.log("Music Scanner", "modified %s" % self.path) else: self.added = True self._debugger.log("Music Scanner", "added %s" % self.path) # Get artist if artist is already in the database and do the same # for album and genre try: artist = ArtistModel.objects.get(name=self.artist) except ArtistModel.DoesNotExist: artist = ArtistModel() artist.name = self.artist artist.save() try: album = AlbumModel.objects.get(name=self.album) except AlbumModel.DoesNotExist: album = AlbumModel() album.name = self.album album.date = self.date album.save() try: genre = GenreModel.objects.get(name=self.genre) except GenreModel.DoesNotExist: genre = GenreModel() genre.name = self.genre genre.save() for attr in ('title', 'tracknumber', 'codec', 'bitrate', 'length', 'path', 'size'): setattr( song, attr, getattr(self, attr) ) song.lastmodified = self.lastModified song.artist = artist song.album = album song.genre = genre song.save()