map01bf@625: #!/usr/bin/env python map01bf@625: # encoding: utf-8 map01bf@625: """ map01bf@625: pyadb.py map01bf@625: map01bf@625: public access and class structure for python audioDb api bindings. map01bf@625: map01bf@625: Created by Benjamin Fields on 2009-09-22. map01bf@625: Copyright (c) 2009 Goldsmith University of London. map01bf@625: """ map01bf@625: map01bf@625: import sys map01bf@625: import os, os.path map01bf@625: import unittest map01bf@625: import _pyadb map01bf@625: map01bf@625: ADB_HEADER_FLAG_L2NORM = 0x1#annoyingly I can't find a means map01bf@625: ADB_HEADER_FLAG_POWER = 0x4#around defining these flag definitions map01bf@625: ADB_HEADER_FLAG_TIMES = 0x20#as they aren't even exported to the map01bf@625: ADB_HEADER_FLAG_REFERENCES = 0x40#api, so this is the only way to get them. map01bf@625: map01bf@625: class Usage(Exception): map01bf@625: def __init__(self, msg): map01bf@625: self.msg = msg map01bf@625: map01bf@625: class Pyadb: map01bf@625: map01bf@625: def __init__(self, path, mode='w'): map01bf@625: self.path = path map01bf@625: if not (mode=='w' or mode =='r'): map01bf@625: raise(ValueError, "if specified, mode must be either\'r\' or \'w\'.") map01bf@625: if os.path.exists(path): map01bf@625: self._db = _pyadb._pyadb_open(path, mode) map01bf@625: else: map01bf@625: self._db = _pyadb._pyadb_create(path,0,0,0) map01bf@625: self._updateDBAttributes() map01bf@625: return map01bf@625: map01bf@625: def insert(self, featFile=None, powerFile=None, timesFile=None, featData=None, powerData=None, timesData=None, key=None): map01bf@625: """Insert features into database. Can be done with data provided directly or by giving a path to a binary fftExtract style feature file. If power and/or timing is engaged in the database header, it must be provided (via the same means as the feature) or a Usage exception will be raised. Power files should be of the same binary type as features. Times files should be the ascii number length of time in seconds from the begining of the file to segment start, one per line.\n---Note that direct data insertion is not yet implemented.---""" map01bf@625: #While python normally advocates leaping before looking, these check are nessecary as map01bf@625: #it is very difficult to assertain why the insertion failed once it has been called. map01bf@625: if (self.hasPower and (((featFile) and powerFile==None) or ((featData) and powerData==None))): map01bf@625: raise(Usage, "The db you are attempting an insert on (%s) expects power and you either\ map01bf@625: haven't provided any or have done so in the wrong format."%self.path) map01bf@625: if (self.hasTimes and (((timesFile) and timesFile==None) or ((timesData) and timesData==None))): map01bf@625: raise(Usage, "The db you are attempting an insert on (%s) expects times and you either\ map01bf@625: haven't provided any or have done so in the wrong format."%self.path) map01bf@625: args = {"db":self._db} map01bf@625: if featFile: map01bf@625: args["features"] = featFile map01bf@625: elif featData: map01bf@625: args["features"] = featData map01bf@625: else: map01bf@625: raise(Usage, "Must provide some feature data!") map01bf@625: if self.hasPower: map01bf@625: if featFile: map01bf@625: args["power"]=powerFile map01bf@625: elif featData: map01bf@625: pass map01bf@625: if self.hasTimes: map01bf@625: if featFile: map01bf@625: args["times"]=timesFile map01bf@625: elif timesData: map01bf@625: pass map01bf@625: if key: map01bf@625: args["key"]=str(key) map01bf@625: if featFile: map01bf@625: if not _pyadb._pyadb_insertFromFile(**args): map01bf@625: raise(RuntimeError, "Insertion failed for an unknown reason.") map01bf@625: else: map01bf@625: self._updateDBAttributes() map01bf@625: return map01bf@625: elif featData: map01bf@625: raise(NotImplementedError, "direct data insertion not yet implemented") map01bf@625: map01bf@625: map01bf@625: ###internal methods### map01bf@625: def _updateDBAttributes(self): map01bf@625: '''run _pyadb_status to fill/update the database level flags and info''' map01bf@625: rawFlags = long(0) map01bf@625: (self.numFiles, map01bf@625: self.dims, map01bf@625: self.dudCount, map01bf@625: self.nullCount, map01bf@625: rawFlags, map01bf@625: self.length, map01bf@625: self.data_region_size) = _pyadb._pyadb_status(self._db) map01bf@625: self.l2Normed = bool(rawFlags & ADB_HEADER_FLAG_L2NORM) map01bf@625: self.hasPower = bool(rawFlags & ADB_HEADER_FLAG_POWER) map01bf@625: self.hasTimes = bool(rawFlags & ADB_HEADER_FLAG_TIMES) map01bf@625: self.usesRefs = bool(rawFlags & ADB_HEADER_FLAG_REFERENCES) map01bf@625: return map01bf@625: map01bf@625: map01bf@625: map01bf@625: map01bf@625: class Result: map01bf@625: def __init__(self): map01bf@625: pass map01bf@625: map01bf@625: class untitledTests(unittest.TestCase): map01bf@625: def setUp(self): map01bf@625: pass map01bf@625: map01bf@625: map01bf@625: if __name__ == '__main__': map01bf@625: unittest.main()