def write_tags(self): """ Writes tags to the file for this Track. Returns False if unsuccessful, and a Format object from `xl.metadata` otherwise. """ try: f = metadata.get_format(self.get_loc_for_io()) if f is None: return False # not a supported type f.write_tags(self.__tags) # now that we've written the tags to disk, remove any tags that the # user asked to be deleted to_remove = [k for k, v in self.__tags.iteritems() if v is None] for rm in to_remove: self.__tags.pop(rm) return f except IOError: # error writing to the file, probably logger.warning("Could not write tags to file", exc_info=True) return False except Exception: logger.exception("Unknown exception: Could not write tags to file") return False
def read_tags(self, force=True, notify_changed=True): """ Reads tags from the file for this Track. :param force: If not True, then only read the tags if the file has be modified. Returns False if unsuccessful, and a Format object from `xl.metadata` otherwise. """ loc = self.get_loc_for_io() try: f = metadata.get_format(loc) if f is None: self._scan_valid = False return False # not a supported type # Retrieve file specific metadata gloc = Gio.File.new_for_uri(loc) mtime = gloc.query_info( "time::modified", Gio.FileQueryInfoFlags.NONE, None ).get_modification_time() mtime = mtime.tv_sec + (mtime.tv_usec / 100000.0) if not force and self.__tags.get('__modified', 0) >= mtime: return f # Read the tags ntags = f.read_all() ntags['__modified'] = mtime # TODO: this probably breaks on non-local files ntags['__basedir'] = gloc.get_parent().get_path() # remove tags that could be in the file, but are in fact not # in the file. Retain tags in the DB that aren't supported by # the file format. nkeys = set(ntags.keys()) ekeys = {k for k in self.__tags.keys() if not k.startswith('__')} # delete anything that wasn't in the new tags to_del = ekeys - nkeys # but if not others set, only delete supported tags if not f.others: to_del &= set(f.tag_mapping.keys()) for tag in to_del: ntags[tag] = None self.set_tags(notify_changed=notify_changed, **ntags) self._scan_valid = True return f except Exception: self._scan_valid = False logger.exception("Error reading tags for %s", loc) return False
def _get_format_obj(self): f = _CACHER.get(self) if not f: try: f = metadata.get_format(self.get_loc_for_io()) except Exception: # TODO: What exception? return None if not f: return None _CACHER.add(self, f) return f
def read_tags(self): """ Reads tags from the file for this Track. Returns False if unsuccessful, and a Format object from `xl.metadata` otherwise. """ loc = self.get_loc_for_io() try: f = metadata.get_format(loc) if f is None: self._scan_valid = False return False # not a supported type ntags = f.read_all() for k, v in ntags.iteritems(): self.set_tag_raw(k, v) # remove tags that could be in the file, but are in fact not # in the file. Retain tags in the DB that aren't supported by # the file format. nkeys = set(ntags.keys()) ekeys = {k for k in self.__tags.keys() if not k.startswith('__')} # delete anything that wasn't in the new tags to_del = ekeys - nkeys # but if not others set, only delete supported tags if not f.others: to_del &= set(f.tag_mapping.keys()) for tag in to_del: self.set_tag_raw(tag, None) # fill out file specific items gloc = Gio.File.new_for_uri(loc) mtime = gloc.query_info("time::modified", Gio.FileQueryInfoFlags.NONE, None).get_modification_time() mtime = mtime.tv_sec + (mtime.tv_usec / 100000.0) self.set_tag_raw('__modified', mtime) # TODO: this probably breaks on non-local files path = gloc.get_parent().get_path() self.set_tag_raw('__basedir', path) self._dirty = True self._scan_valid = True return f except Exception: self._scan_valid = False logger.exception("Error reading tags for %s", loc) return False
def list_tags_disk(self): """ List all the tags directly from file metadata. Can be slow, use with caution. """ f = _CACHER.get(self) if not f: try: f = metadata.get_format(self.get_loc_for_io()) except Exception: # TODO: What exception? return None if not f: return None _CACHER.add(self, f) return f._get_raw().keys()
def write_tags(self): """ Writes tags to the file for this Track. Returns False if unsuccessful, and a Format object from `xl.metadata` otherwise. """ try: f = metadata.get_format(self.get_loc_for_io()) if f is None: return False # not a supported type f.write_tags(self.__tags) return f except: common.log_exception() return False
def read_tags(self): """ Reads tags from the file for this Track. Returns False if unsuccessful, and a Format object from `xl.metadata` otherwise. """ loc = self.get_loc_for_io() try: f = metadata.get_format(loc) if f is None: self._scan_valid = False return False # not a supported type ntags = f.read_all() for k, v in ntags.iteritems(): self.set_tag_raw(k, v) # remove tags that have been deleted in the file, while # taking into account that the db may have tags not # supported by the file's tag format. if f.others: supported_tags = [ t for t in self.list_tags() \ if not t.startswith("__") ] else: supported_tags = f.tag_mapping.keys() for tag in supported_tags: if tag not in ntags.keys(): self.set_tag_raw(tag, None) # fill out file specific items gloc = Gio.File.new_for_uri(loc) mtime = gloc.query_info("time::modified", Gio.FileQueryInfoFlags.NONE, None).get_modification_time() mtime = mtime.tv_sec + (mtime.tv_usec / 100000.0) self.set_tag_raw('__modified', mtime) # TODO: this probably breaks on non-local files path = gloc.get_parent().get_path() self.set_tag_raw('__basedir', path) self._dirty = True self._scan_valid = True return f except Exception: self._scan_valid = False logger.exception("Error reading tags for %s", loc) return False
def write_tags(self): """ Writes tags to the file for this Track. Returns False if unsuccessful, and a Format object from `xl.metadata` otherwise. """ try: f = metadata.get_format(self.get_loc_for_io()) if f is None: return False # not a supported type f.write_tags(self.__tags) return f except IOError, e: # error writing to the file, probably logger.warning( "Could not write tags to file: %s" % e ) return False
def write_tags(self): """ Writes tags to the file for this Track. Returns False if unsuccessful, and a Format object from `xl.metadata` otherwise. """ try: f = metadata.get_format(self.get_loc_for_io()) if f is None: return False # not a supported type f.write_tags(self.__tags) return f except IOError, e: # error writing to the file, probably logger.warning("Could not write tags to file: %s" % e) return False
def read_tags(self): """ Reads tags from the file for this Track. Returns False if unsuccessful, and a Format object from `xl.metadata` otherwise. """ loc = self.get_loc_for_io() try: f = metadata.get_format(loc) if f is None: self._scan_valid = False return False # not a supported type ntags = f.read_all() for k, v in ntags.iteritems(): self.set_tag_raw(k, v) # remove tags that have been deleted in the file, while # taking into account that the db may have tags not # supported by the file's tag format. if f.others: supported_tags = [ t for t in self.list_tags() \ if not t.startswith("__") ] else: supported_tags = f.tag_mapping.keys() for tag in supported_tags: if tag not in ntags.keys(): self.set_tag_raw(tag, None) # fill out file specific items gloc = Gio.File.new_for_uri(loc) mtime = gloc.query_info("time::modified", Gio.FileQueryInfoFlags.NONE, None).get_modification_time() mtime = mtime.tv_sec + (mtime.tv_usec/100000.0) self.set_tag_raw('__modified', mtime) # TODO: this probably breaks on non-local files path = gloc.get_parent().get_path() self.set_tag_raw('__basedir', path) self._dirty = True self._scan_valid = True return f except Exception: self._scan_valid = False logger.exception("Error reading tags for %s", loc) return False
def get_tag_disk(self, tag): """ Read a tag directly from disk. Can be slow, use with caution. Intended for use with large fields like covers and lyrics that shouldn't be loaded to the in-mem db. """ f = _CACHER.get(self) if not f: try: f = metadata.get_format(self.get_loc_for_io()) except Exception: # TODO: What exception? return None if not f: return None _CACHER.add(self, f) try: return f.read_tags([tag])[tag] except KeyError: return None