Chris@148: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@148: 
Chris@148: /*
Chris@148:     Sonic Visualiser
Chris@148:     An audio file viewer and annotation editor.
Chris@148:     Centre for Digital Music, Queen Mary, University of London.
Chris@537:     This file copyright 2006-2009 Chris Cannam and QMUL.
Chris@148:     
Chris@148:     This program is free software; you can redistribute it and/or
Chris@148:     modify it under the terms of the GNU General Public License as
Chris@148:     published by the Free Software Foundation; either version 2 of the
Chris@148:     License, or (at your option) any later version.  See the file
Chris@148:     COPYING included with this distribution for more information.
Chris@148: */
Chris@148: 
Chris@148: #ifndef _MATRIX_FILE_CACHE_H_
Chris@148: #define _MATRIX_FILE_CACHE_H_
Chris@148: 
Chris@148: #include "base/ResizeableBitset.h"
Chris@148: 
Chris@148: #include "FileReadThread.h"
Chris@148: 
Chris@148: #include <sys/types.h>
Chris@148: #include <QString>
Chris@148: #include <QMutex>
Chris@148: #include <map>
Chris@148: 
Chris@148: class MatrixFile : public QObject
Chris@148: {
Chris@148:     Q_OBJECT
Chris@148: 
Chris@148: public:
Chris@537:     enum Mode { ReadOnly, WriteOnly };
Chris@148: 
Chris@148:     /**
Chris@148:      * Construct a MatrixFile object reading from and/or writing to
Chris@148:      * the matrix file with the given base name in the application's
Chris@148:      * temporary directory.
Chris@148:      *
Chris@148:      * If mode is ReadOnly, the file must exist and be readable.
Chris@148:      *
Chris@537:      * If mode is WriteOnly, the file must not exist.
Chris@148:      *
Chris@148:      * cellSize specifies the size in bytes of the object type stored
Chris@148:      * in the matrix.  For example, use cellSize = sizeof(float) for a
Chris@148:      * matrix of floats.  The MatrixFile object doesn't care about the
Chris@148:      * objects themselves, it just deals with raw data of a given size.
Chris@148:      *
Chris@537:      * width and height specify the dimensions of the file.  These
Chris@537:      * cannot be changed after construction.
Chris@537:      *
Chris@537:      * MatrixFiles are reference counted by name.  When the last
Chris@537:      * MatrixFile with a given name is destroyed, the file is removed.
Chris@537:      * These are temporary files; the normal usage is to have one
Chris@537:      * MatrixFile of WriteOnly type creating the file and then
Chris@537:      * persisting until all readers are complete.
Chris@537:      *
Chris@537:      * MatrixFile has no built-in cache and is not thread-safe.  Use a
Chris@537:      * separate MatrixFile in each thread.
Chris@148:      */
Chris@929:     MatrixFile(QString fileBase, Mode mode, int cellSize,
Chris@929:                int width, int height);
Chris@148:     virtual ~MatrixFile();
Chris@148: 
Chris@148:     Mode getMode() const { return m_mode; }
Chris@148: 
Chris@929:     int getWidth() const { return m_width; }
Chris@929:     int getHeight() const { return m_height; }
Chris@929:     int getCellSize() const { return m_cellSize; }
Chris@550: 
Chris@550:     /**
Chris@550:      * If this is set true on a write-mode MatrixFile, then the file
Chris@550:      * will close() itself when all columns have been written.
Chris@550:      */
Chris@550:     void setAutoClose(bool a) { m_autoClose = a; }
Chris@550: 
Chris@537:     void close(); // does not decrement ref count; that happens in dtor
Chris@148: 
Chris@929:     bool haveSetColumnAt(int x) const;
Chris@929:     void getColumnAt(int x, void *data); // may throw FileReadFailed
Chris@929:     void setColumnAt(int x, const void *data);
Chris@148: 
Chris@148: protected:
Chris@148:     int     m_fd;
Chris@148:     Mode    m_mode;
Chris@148:     int     m_flags;
Chris@148:     mode_t  m_fmode;
Chris@929:     int     m_cellSize;
Chris@929:     int     m_width;
Chris@929:     int     m_height;
Chris@929:     int     m_headerSize;
Chris@148:     QString m_fileName;
Chris@148: 
Chris@550:     ResizeableBitset *m_setColumns; // only in writer
Chris@550:     bool m_autoClose;
Chris@550: 
Chris@554:     // In reader: if this is >= 0, we can read that column directly
Chris@554:     // without seeking (and we know that the column exists)
Chris@554:     mutable int m_readyToReadColumn;
Chris@554: 
Chris@148:     static std::map<QString, int> m_refcount;
Chris@537:     static QMutex m_createMutex;
Chris@148: 
Chris@537:     void initialise();
Chris@929:     bool seekTo(int col) const;
Chris@148: };
Chris@148: 
Chris@148: #endif
Chris@148: