OSCAR-code/oscar/SleepLib/machine.h
2024-01-31 19:14:19 -05:00

351 lines
9.4 KiB
C++

/* SleepLib Device Class Header
*
* Copyright (c) 2019-2024 The OSCAR Team
* Copyright (C) 2011-2018 Mark Watkins
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of the source code
* for more details. */
#ifndef MACHINE_H
#define MACHINE_H
#include <QString>
#include <QVariant>
#include <QDateTime>
#include <QPixmap>
#include <QRunnable>
#include <QThread>
#include <QMutex>
#include <QSemaphore>
#include <QHash>
#include <QVector>
#include <list>
#include "SleepLib/preferences.h"
#include "SleepLib/progressdialog.h"
#include "SleepLib/machine_common.h"
#include "SleepLib/event.h"
#include "SleepLib/session.h"
#include "SleepLib/schema.h"
#include "SleepLib/day.h"
class Day;
class Session;
class Profile;
class Machine;
/*! \class SaveThread
\brief This class is used in the multithreaded save code.. It accelerates the indexing of summary data.
*/
//class SaveThread: public QThread
//{
// Q_OBJECT
// public:
// SaveThread(Machine *m, QString p) { machine = m; path = p; }
//
// //! \brief Static millisecond sleep function.. Can be used from anywhere
// static void msleep(unsigned long msecs) { QThread::msleep(msecs); }
//
// //! \brief Start Save processing thread running
// virtual void run();
// protected:
// Machine *machine;
// QString path;
// signals:
// //! \brief Signal sent to update the Progress Bar
// void UpdateProgress(int i);
//};
class ImportTask:public QRunnable
{
public:
explicit ImportTask() {}
virtual ~ImportTask() {}
virtual void run() {}
};
class SaveTask:public ImportTask
{
public:
SaveTask(Session * s, Machine * m): sess(s), mach(m) {}
virtual ~SaveTask() {}
virtual void run();
protected:
Session * sess;
Machine * mach;
};
class LoadTask:public ImportTask
{
public:
LoadTask(Session * s, Machine * m): sess(s), mach(m) {}
virtual ~LoadTask() {}
virtual void run();
protected:
Session * sess;
Machine * mach;
};
class MachineLoader; // forward
/*! \class Machine
\brief This device class is the Heart of SleepyLib, representing a single device and holding it's data
*/
class Machine
{
friend class SaveThread;
// friend class MachineLaoder;
public:
/*! \fn Machine(MachineID id=0);
\brief Constructs a device object with MachineID id
If supplied MachineID is zero, it will generate a new unused random one.
*/
Machine(Profile * _profile, MachineID id = 0);
virtual ~Machine();
//! \brief Load all device summary data
bool Load(ProgressDialog *progress);
bool LoadSummary(ProgressDialog *progress);
//! \brief Save all Sessions where changed bit is set.
bool Save();
bool SaveSummaryCache();
//! \brief Save individual session
bool SaveSession(Session *sess);
//! \brief Deletes the crud out of all device data in the SleepLib database
bool Purge(int secret);
//! \brief Unlink a session from any device related indexes
bool unlinkSession(Session * sess);
bool unlinkDay(Day * day);
inline bool hasChannel(ChannelID code) {
return m_availableChannels.contains(code);
}
inline bool hasSetting(ChannelID code) {
return m_availableSettings.contains(code);
}
//! \brief Returns a pointer to a valid Session object if SessionID exists
Session *SessionExists(SessionID session);
//! \brief Adds the session to this device object, and the Master Profile list. (used during load)
bool AddSession(Session *s, bool allowOldSessions=false);
//! \brief Find the date this session belongs in, according to profile settings
QDate pickDate(qint64 start);
const QString getDataPath();
const QString getEventsPath();
const QString getSummariesPath();
const QString getBackupPath();
qint64 diskSpaceSummaries();
qint64 diskSpaceEvents();
qint64 diskSpaceBackups();
//! \brief Returns the machineID as a lower case hexadecimal string
QString hexid() ;
//! \brief Unused, increments the most recent sessionID
SessionID CreateSessionID() { return highest_sessionid + 1; }
//! \brief Returns this objects MachineID
const MachineID &id() { return m_id; }
void setId(MachineID id) { m_id = id; }
//! \brief Returns the date of the first loaded Session
const QDate &FirstDay() { return firstday; }
//! \brief Returns the date of the most recent loaded Session
const QDate &LastDay() { return lastday; }
bool hasModifiedSessions();
bool warnOnUntested() { return m_suppressUntestedWarning == false; }
void suppressWarnOnUntested() { m_suppressUntestedWarning = true; }
QSet<QString> & previouslySeenUnexpectedData() { return m_previousUnexpected; }
inline MachineType type() const { return info.type; }
inline QString brand() const { return info.brand; }
inline QString loaderName() const { return info.loadername; }
inline QString model() const { return info.model; }
inline QString modelnumber() const { return info.modelnumber; }
inline QString serial() const { return info.serial; }
inline QString series() const { return info.series; }
inline quint32 cap() const { return info.cap; }
inline int version() const { return info.version; }
inline QDateTime lastImported() const { return info.lastimported; }
inline QDate purgeDate() const { return info.purgeDate; }
inline void setModel(QString value) { info.model = value; }
inline void setBrand(QString value) { info.brand = value; }
inline void setSerial(QString value) { info.serial = value; }
inline void setType(MachineType type) { info.type = type; }
inline void setCap(quint32 value) { info.cap = value; }
inline void setPurgeDate(QDate value) {info.purgeDate = value; }
inline void clearPurgeDate() {info.purgeDate = QDate(); }
bool saveSessionInfo();
bool loadSessionInfo();
void setLoaderName(QString value);
QList<ChannelID> availableChannels(quint32 chantype);
MachineLoader * loader() { return m_loader; }
void setInfo(MachineInfo inf);
const MachineInfo getInfo() { return info; }
void updateChannels(Session * sess);
QString getPixmapPath();
QPixmap & getPixmap();
// //! \brief The multi-threading methods follow
// //! \brief Add a new task to the multithreaded save code
//void queSaveList(Session * sess);
//! \brief Grab the next task in the multithreaded save code
//Session *popSaveList();
// //! \brief Start the save threads which handle indexing, file storage and waveform processing
//void StartSaveThreads();
// //! \brief Finish the save threads and safely close them
//void FinishSaveThreads();
// void lockSaveMutex() { listMutex.lock(); }
// void unlockSaveMutex() { listMutex.unlock(); }
// void skipSaveTask() { lockSaveMutex(); m_donetasks++; unlockSaveMutex(); }
//
// void clearSkipped() { skipped_sessions = 0; }
// int skippedSessions() { return skipped_sessions; }
//
// inline int totalTasks() { return m_totaltasks; }
// inline void setTotalTasks(int value) { m_totaltasks = value; }
// inline int doneTasks() { return m_donetasks; }
// much more simpler multithreading...(no such thing - pholynyk)
void queTask(ImportTask * task);
void runTasks();
// Public Data Members follow
MachineInfo info;
bool m_suppressUntestedWarning;
QSet<QString> m_previousUnexpected;
//! \brief Contains a secondary index of day data, containing just this devices sessions
QMap<QDate, Day *> day;
//! \brief Contains all sessions for this device, indexed by SessionID
QHash<SessionID, Session *> sessionlist;
//! \brief The list of sessions that need saving (for multithreaded save code)
// QList<Session *> m_savelist;
// Following are the items related to multi-threading
// QVector<SaveThread *>thread;
// volatile int savelistCnt;
// int savelistSize;
QMutex listMutex;
QMutex saveMutex;
// QSemaphore *savelistSem;
protected: // only Data Memebers here
QDate firstday, lastday;
SessionID highest_sessionid;
MachineID m_id;
MachineType m_type;
QString m_path;
MachineLoader * m_loader;
bool changed;
bool firstsession;
QHash<ChannelID, bool> m_availableChannels;
QHash<ChannelID, bool> m_availableSettings;
QString m_summaryPath;
QString m_eventsPath;
QString m_dataPath;
Profile * profile;
// The following are the multi-threading data members
int m_totaltasks;
int m_donetasks;
int skipped_sessions;
volatile bool m_save_threads_running;
QList<ImportTask *> m_tasklist;
};
/*! \class CPAP
\brief A CPAP classed device object..
*/
class CPAP: public Machine
{
public:
CPAP(Profile *, MachineID id = 0);
virtual ~CPAP();
};
/*! \class Oximeter
\brief An Oximeter classed device object..
*/
class Oximeter: public Machine
{
public:
Oximeter(Profile *, MachineID id = 0);
virtual ~Oximeter();
protected:
};
/*! \class SleepStage
\brief A SleepStage classed device object..
*/
class SleepStage: public Machine
{
public:
SleepStage(Profile *, MachineID id = 0);
virtual ~SleepStage();
protected:
};
/*! \class PositionSensor
\brief A PositionSensor classed device object..
*/
class PositionSensor: public Machine
{
public:
PositionSensor(Profile *, MachineID id = 0);
virtual ~PositionSensor();
protected:
};
#endif // MACHINE_H