From 1f706ed42b8d7fd1012212f10f4d33b0aa2d5152 Mon Sep 17 00:00:00 2001 From: Mark Watkins Date: Wed, 16 Oct 2013 12:52:25 +1000 Subject: [PATCH] Some unfinished work on F&P Icon loader and ResMed S9 importer --- .../SleepLib/loader_plugins/icon_loader.cpp | 374 ++++++++---------- .../SleepLib/loader_plugins/icon_loader.h | 14 +- .../SleepLib/loader_plugins/resmed_loader.cpp | 218 +++++++++- sleepyhead/docs/release_notes.html | 6 +- sleepyhead/main.cpp | 2 +- 5 files changed, 399 insertions(+), 215 deletions(-) diff --git a/sleepyhead/SleepLib/loader_plugins/icon_loader.cpp b/sleepyhead/SleepLib/loader_plugins/icon_loader.cpp index 1ece98c9..0584e20c 100644 --- a/sleepyhead/SleepLib/loader_plugins/icon_loader.cpp +++ b/sleepyhead/SleepLib/loader_plugins/icon_loader.cpp @@ -198,50 +198,107 @@ int FPIconLoader::OpenMachine(Machine *mach, QString & path, Profile * profile) } while (it!=Sessions.begin()); - qDebug() << "Unmatched Sessions"; - QList chunks; - for (QMap::iterator dit=FLWDate.begin();dit!=FLWDate.end();dit++) { - int k=dit.key(); - //QDate date=dit.value(); -// QList values = SessDate.values(date); - for (int j=0;j chunks; +// for (QMap::iterator dit=FLWDate.begin();dit!=FLWDate.end();dit++) { +// int k=dit.key(); +// //QDate date=dit.value(); +//// QList values = SessDate.values(date); +// for (int j=0;jchannelDataExists(CPAP_FlowRate)) c=true; - } - qDebug() << k << "-" <channelDataExists(CPAP_FlowRate)) c=true; - } - qDebug() << chunk.file << ":" << i << zz << dur << "minutes" << (b ? "*" : "") << (c ? QDateTime::fromTime_t(zz).toString() : ""); - } +// zz=FLWTS[k].at(j)/1000; +// dur=double(FLWDuration[k].at(j))/60000.0; +// bool b,c=false; +// if (Sessions.contains(zz)) b=true; else b=false; +// if (b) { +// if (Sessions[zz]->channelDataExists(CPAP_FlowRate)) c=true; +// } +// qDebug() << k << "-" <channelDataExists(CPAP_FlowRate)) c=true; +// } +// qDebug() << chunk.file << ":" << i << zz << dur << "minutes" << (b ? "*" : "") << (c ? QDateTime::fromTime_t(zz).toString() : ""); +// } mach->Save(); return true; } +QDateTime FPIconLoader::readFPDateTime(quint8 * data) +{ + quint32 ts=(data[3] << 24) | (data[2] << 16) | ((data[1] << 8) | data[0]);// ^ 0xc00000; + // 0x20a41b18 + quint8 day=ts & 0x1f; // 0X18 24 + ts >>= 5; // 10520D8 + quint8 month=ts & 0x0f; // 0X08 8 + ts >>= 4; // 10520D + quint8 year=ts & 0x3f; // 0X0D 13 + ts >>= 6; // 4148 + quint8 second=ts & 0x3f;// 0X08 8 + ts >>= 6; // 20A + quint8 minute=ts & 0x3f;// 0A 10 + ts >>= 6; // 10 + quint8 hour=ts & 0x1f; // 10 16 + QDate date=QDate(2000+year,month,day); + QTime time=QTime(hour,minute,second); + QDateTime datetime=QDateTime(date,time); + return datetime; +} + +/* + *in >> a1; +in >> a2; +t1=a2 << 8 | a1; + +if (t1==0xfafe) + break; + +day=t1 & 0x1f; +month=(t1 >> 5) & 0x0f; +year=2000+((t1 >> 9) & 0x3f); + +in >> a1; +in >> a2; + +ts=((a2 << 8) | a1) << 1; +ts|=(t1 >> 15) & 1; + +second=(ts & 0x3f); +minute=(ts >> 6) & 0x3f; +hour=(ts >> 12) & 0x1f; */ + + + +// FLW Header Structure +// 0x0000-0x01fe +// newline (0x0d) seperated list of machine information strings. +// magic? 0201 +// version 1.5.0 +// serial number 12 digits +// Machine Series "ICON" +// Machine Model "Auto" +// Remainder of header is 0 filled... +// 0x01ff 8 bit additive sum checksum byte of previous header bytes + +// 0x0200-0x0203 32bit timestamp in bool FPIconLoader::OpenFLW(Machine * mach,QString filename, Profile * profile) { Q_UNUSED(mach); @@ -250,15 +307,12 @@ bool FPIconLoader::OpenFLW(Machine * mach,QString filename, Profile * profile) quint16 t1; quint32 ts; double ti; - //qint8 b; + EventList * flow=NULL, * pressure=NULL, *leak=NULL; QDateTime datetime; - quint8 a1,a2; + unsigned char * buf, *endbuf; - int month,day,year,hour,minute,second; - - long pos=0; qDebug() << filename; QByteArray header; @@ -301,55 +355,28 @@ bool FPIconLoader::OpenFLW(Machine * mach,QString filename, Profile * profile) buf=(unsigned char *)data.data(); endbuf=buf+data.size(); - a1=*buf++; - a2=*buf++; - t1=a2 << 8 | a1; - pos+=2; - + t1=buf[1] << 8 | buf[0]; if (t1==0xfafe) // End of file marker.. { qDebug() << "FaFE observed in" << filename; - + return false; } - day=t1 & 0x1f; - month=((t1 >> 5) & 0x0f); - year=2000+((t1 >> 9) & 0x7f); + datetime=readFPDateTime(buf); + buf+=4; - a1=*buf++; - a2=*buf++; - - t1=a2 << 8 | a1; - - // Why the heck does F&P do this? This affects the MINUTES field and the HOURS field. - // But is clearly not a valid UTC conversion.. Bug? Or idiotic obfuscation attempt? - // It would of made (idiotic) sense if they shifted the bits on bit further to the right. - t1-=0xc0; - - pos+=2; - - second=(t1 & 0x1f) * 2; - minute=(t1 >> 5) & 0x3f; - hour=(t1 >> 11) & 0x1f; - - datetime=QDateTime(QDate(year,month,day),QTime(hour,minute,second),Qt::UTC); QDate date; QTime time; - if (!datetime.isValid() || (datetime.date()session() << ":" << sess->hours()*60.0; } else { - sess=NULL; + sess=new Session(mach,ts); + sess->set_first(ti); + newsess=true; qDebug() << filenum << ":" << date << "couldn't find matching session for" << ts; } + const int samples_per_block=50; + const double rate=1000.0/double(samples_per_block); - const double rate=1000.0/50.0; + // F&P Overwrites this file, not appends to it. + flow=new EventList(EVL_Waveform,1.0,0,0,0,rate); + leak=new EventList(EVL_Event,1.0,0,0,0,rate*double(samples_per_block)); // 1 per second + pressure=new EventList(EVL_Event,0.01,0,0,0,rate*double(samples_per_block)); // 1 per second + flow->setFirst(ti); + leak->setFirst(ti); + pressure->setFirst(ti); - int count; - for (int chunks=0;bufsetFirst(ti); - leak->setFirst(ti); - pressure->setFirst(ti); + bool corrupt=false; - FLWMapFlow[filenum].push_back(flow); - FLWMapLeak[filenum].push_back(leak); - FLWMapPres[filenum].push_back(pressure); - FLWTS[filenum].push_back(ti); - - count=0; - int len; - qint16 pr; - quint16 lkaj; + do { + quint8 * p=buf; + // Scan ahead looking for end of block, marked by ff ff do { - unsigned char * p=buf,*p2; - - // scan ahead to 0xffff marker - p2=buf+103; - if (p2>endbuf) - break; - if (!((p2[0]==0xff) && (p2[1]==0xff))) { - if (count>0) { - //int i=5; - } - do { - while ((*p++ != 0xff) && (p < endbuf)) { - pos++; - } - if (p >= endbuf) - break; - pos++; - } while ((*p++ != 0xff) && (p < endbuf)); - if (p >= endbuf) - break; - } else { - //if (count>0) - p=p2+2; + p++; + if (p>=endbuf) { + delete flow; + delete leak; + delete pressure; + return false; } - p2=p-5; - len=p2-buf; - pr=p2[1] << 8 | p2[0]; // pressure * 100 - lkaj=p2[2]; // Could this value perhaps be Leak??? - len/=2; + } while (!((p[0]==0xff) && (p[1]==0xff))); - count++; + // The Pressure and lkaj codes are before the end of block marker + p-=3; + pr=p[0] << 8 | p[1]; + lkaj=p[2]; + int i=0; - //if (pr<0) { - //quint16 z3=pr; - // int i=5; - //} + do { + tmp=buf[1] << 8 | buf[0]; + val=(EventDataType(tmp)/100.0)-lkaj; + if (val<-128) val=-128; + else if (val>128) val=128; + buf+=2; - if (leak) { - leak->AddEvent(ti,lkaj); - } - if (pressure) { - pressure->AddEvent(ti,pr); - } + pbuf[i++]=val; + } while (bufAddWaveform(ti,pbuf,i,rate); + ti+=i*rate; - if (flow) { - qint16 tmp; - unsigned char * bb=(unsigned char *)buf; - //char c; - //if (len>50) { - //int i=5; - //} + buf=p+5; - EventDataType val; - for (int i=0;i128) val=128; - bb+=2; - - pbuf[i]=val; - } - - flow->AddWaveform(ti,pbuf,len,rate); - } - - ti+=len*rate; - - buf=p; - - if (buf >= endbuf-1) break; - if ((p[0]==0xff) && (p[1]==0x7f)) { - buf+=2; - pos+=2; - while ((*buf++ == 0) && (buf < endbuf)) pos++; - break; - } - } while (buf < endbuf); -// pressure->setType(EVL_Waveform); -// pressure->getTime().clear(); -// leak->getTime().clear(); -// leak->setType(EVL_Waveform); - - if (sess && FLWMapFlow[filenum].size()==1 && (st==sess->first())) { - sess->eventlist[CPAP_FlowRate].push_back(FLWMapFlow[filenum].at(0)); - sess->eventlist[CPAP_Leak].push_back(FLWMapLeak[filenum].at(0)); - sess->eventlist[CPAP_MaskPressure].push_back(FLWMapPres[filenum].at(0)); -// FLWMapFlow[filenum].erase(FLWMapFlow[filenum].begin()); -// FLWMapLeak[filenum].erase(FLWMapLeak[filenum].begin()); -// FLWMapPres[filenum].erase(FLWMapPres[filenum].begin()); - } + if (buf>=endbuf) + break; + } while (!((buf[0]==0xff) && (buf[1]==0x7f))); - qDebug() << ts << dec << double(ti-st)/60000.0; - FLWDuration[filenum].push_back(ti-st); - st=ti; - } while (buf < endbuf); - - - QList values = SessDate.values(date); - for (int i = 0; i < values.size(); ++i) { - sess=values.at(i); - qDebug() << date << sess->session() << ":" << QString::number(sess->hours()*60.0,'f',0); + if (sess && (st==sess->first())) { + sess->eventlist[CPAP_FlowRate].push_back(flow); + sess->eventlist[CPAP_Leak].push_back(leak); + sess->eventlist[CPAP_MaskPressure].push_back(pressure); } + if (newsess) + mach->AddSession(sess,profile); return true; } +//////////////////////////////////////////////////////////////////////////////////////////// +// Open Summary file +//////////////////////////////////////////////////////////////////////////////////////////// bool FPIconLoader::OpenSummary(Machine * mach,QString filename, Profile * profile) { qDebug() << filename; @@ -564,18 +532,19 @@ bool FPIconLoader::OpenSummary(Machine * mach,QString filename, Profile * profil day=t1 & 0x1f; month=(t1 >> 5) & 0x0f; - year=2000+((t1 >> 9) & 0x7f); + year=2000+((t1 >> 9) & 0x3f); in >> a1; in >> a2; - t1=a2 << 8 | a1; + ts=((a2 << 8) | a1) << 1; + ts|=(t1 >> 15) & 1; - second=(t1 & 0x1f) * 2; - minute=(t1 >> 5) & 0x3f; - hour=(t1 >> 11) & 0x1f; + second=(ts & 0x3f); + minute=(ts >> 6) & 0x3f; + hour=(ts >> 12) & 0x1f; - datetime=QDateTime(QDate(year,month,day),QTime(hour,minute,second),Qt::UTC); + datetime=QDateTime(QDate(year,month,day),QTime(hour,minute,second)); date=datetime.date(); ts=datetime.toTime_t(); @@ -690,7 +659,6 @@ bool FPIconLoader::OpenDetail(Machine * mach, QString filename, Profile * profil quint16 strt; quint8 recs,z1,z2; - int day,month,year,hour,minute,second; int totalrecs=0; @@ -704,17 +672,21 @@ bool FPIconLoader::OpenDetail(Machine * mach, QString filename, Profile * profil day=t1 & 0x1f; month=(t1 >> 5) & 0x0f; - year=2000+((t1 >> 9) & 0x7f); + year=2000+((t1 >> 9) & 0x3f); in >> z1; in >> z2; - t1=z2 << 8 | z1; + // - second=(t1 & 0x1f) * 2; - minute=(t1 >> 5) & 0x3f; - hour=(t1 >> 11) & 0x1f; + ts=((z2 << 8) | z1) << 1; + ts|=(t1 >> 15) & 1; - datetime=QDateTime(QDate(year,month,day),QTime(hour,minute,second),Qt::UTC); + // + second=(ts & 0x3f); + minute=(ts >> 6) & 0x3f; + hour=(ts >> 12) & 0x1f; + + datetime=QDateTime(QDate(year,month,day),QTime(hour,minute,second)); //datetime=datetime.toTimeSpec(Qt::UTC); ts=datetime.toTime_t(); diff --git a/sleepyhead/SleepLib/loader_plugins/icon_loader.h b/sleepyhead/SleepLib/loader_plugins/icon_loader.h index 602e2c4d..8c2492c3 100644 --- a/sleepyhead/SleepLib/loader_plugins/icon_loader.h +++ b/sleepyhead/SleepLib/loader_plugins/icon_loader.h @@ -75,16 +75,18 @@ public: static void Register(); protected: + QDateTime readFPDateTime(quint8 * data); + QString last; QHash MachList; QMap Sessions; QMultiMap SessDate; - QMap > FLWMapFlow; - QMap > FLWMapLeak; - QMap > FLWMapPres; - QMap > FLWDuration; - QMap > FLWTS; - QMap FLWDate; + //QMap > FLWMapFlow; + //QMap > FLWMapLeak; + //QMap > FLWMapPres; + //QMap > FLWDuration; + //QMap > FLWTS; + //QMap FLWDate; unsigned char * m_buffer; }; diff --git a/sleepyhead/SleepLib/loader_plugins/resmed_loader.cpp b/sleepyhead/SleepLib/loader_plugins/resmed_loader.cpp index 96e6d534..090cebc6 100644 --- a/sleepyhead/SleepLib/loader_plugins/resmed_loader.cpp +++ b/sleepyhead/SleepLib/loader_plugins/resmed_loader.cpp @@ -470,8 +470,9 @@ int ResmedLoader::Open(QString & path,Profile *profile) // Process the actual STR.edf data /////////////////////////////////////////////////////////////////////////////////// - qint64 duration=stredf.GetNumDataRecords()*stredf.GetDuration(); - int days=duration/86400000L; + qint64 numrecs=stredf.GetNumDataRecords(); + qint64 duration=numrecs*stredf.GetDuration(); + int days=duration/86400000L; // GetNumDataRecords = this.. Duh! //QDateTime dt1=QDateTime::fromTime_t(stredf.startdate/1000L); //QDateTime dt2=QDateTime::fromTime_t(stredf.enddate/1000L); @@ -1157,7 +1158,9 @@ int ResmedLoader::Open(QString & path,Profile *profile) continue; } else { sess->SetChanged(true); + qint64 dif=sess->first()-stredf.startdate; + int dn=dif/86400000L; int mode; EventDataType prset, prmode; @@ -1173,12 +1176,18 @@ int ResmedLoader::Open(QString & path,Profile *profile) sig=stredf.lookupSignal(RMS9_EPR); if (sig) { prmode=EventDataType(sig->data[dn])*sig->gain; + if (prmode>sig->physical_maximum) { + int i=5; + } sess->settings[CPAP_PresReliefMode]=prmode; } sig=stredf.lookupSignal(RMS9_EPRSet); if (sig) { prset=EventDataType(sig->data[dn])*sig->gain; + if (prset>sig->physical_maximum) { + int i=5; + } sess->settings[CPAP_PresReliefSet]=prset; } @@ -1290,6 +1299,211 @@ int ResmedLoader::Open(QString & path,Profile *profile) m->AddSession(sess,profile); } } + +///////////////////////////////////////////////////////////////////////////////// +// Process STR.edf now all valid Session data is imported +///////////////////////////////////////////////////////////////////////////////// +/* + qint64 tt=stredf.startdate; + QDateTime dt=QDateTime::fromMSecsSinceEpoch(tt); + QDateTime mt; + QDate d; + + EDFSignal *maskon=stredf.lookup["Mask On"]; + EDFSignal *maskoff=stredf.lookup["Mask Off"]; + int nr1=maskon->nr; + int nr2=maskoff->nr; + + qint64 mon, moff; + + int mode; + EventDataType prset, prmode; + + SessionID sid; + for (int dn=0; dn < days; dn++, tt+=86400000L) { + dt=QDateTime::fromMSecsSinceEpoch(tt); + d=dt.date(); + Day * day=PROFILE.GetDay(d, MT_CPAP); + if (day) { + continue; + } + QString a; + // Todo: check session start times. + // mask time is in minutes per day, assuming starting from 12 noon + // Also to think about: users who are too lazy to set their clocks, or who have flat clock batteries. + + int nr=maskon->nr; + int j=dn * nr; + qint16 m_on=-1, m_off=-1, m_off2=0; + for (int i=0;i<10;i++) { + m_on=maskon->data[j+i]; + if ((i>0) && (m_on >=0) && (m_on < m_off)) { + qDebug() << "Mask on before previous off"; + } + m_off=maskoff->data[j+i]; + m_off2=m_off; + + + if ((m_on >= 0) && (m_off < 0)) { + // valid session.. but machine turned off the next day + // look ahead and pinch the end time from tomorrows record + if ((dn+1) > days) { + qDebug() << "Last record should have contained a mask off event :("; + continue; + } + m_off=maskoff->data[j + nr]; + + if (maskon->data[j + nr] < 0) { + qDebug() << dn << "Looking ahead maskon should be < 0"; + continue; + } + if (m_off < 0) { + qDebug() << dn << "Looking ahead maskoff should be > 0"; + continue; + } + + // It's in the next day, so add one day in minutes.. + m_off+=1440; + + // Valid + + } else if ((m_off >= 0) && (m_on < 0)) { + + if (i>0) { + qDebug() << "WTH!??? Mask off but no on"; + } + // first record of day.. might already be on (crossing noon) + // Safely ignore because they are picked up on the other day. + continue; + } else if ((m_off < 0) && (m_on < 0)) + continue; + + mon=tt + m_on * 60000L; + moff=tt + m_off * 60000L; + + sid=mon/1000L; + QDateTime on=QDateTime::fromMSecsSinceEpoch(mon); + QDateTime off=QDateTime::fromMSecsSinceEpoch(moff); + + sess=new Session(m,sid); + sess->set_first(mon); + sess->set_last(moff); + + sig=stredf.lookupSignal(CPAP_Mode); + if (sig) { + mode=sig->data[dn]; + } else mode=0; + + sess->settings[CPAP_PresReliefType]=PR_EPR; + + // AutoSV machines don't have both fields + sig=stredf.lookupSignal(RMS9_EPR); + if (sig) { + prmode=EventDataType(sig->data[dn])*sig->gain; + if (prmode>sig->physical_maximum) { + int i=5; + } + sess->settings[CPAP_PresReliefMode]=prmode; + } + + sig=stredf.lookupSignal(RMS9_EPRSet); + if (sig) { + prset=EventDataType(sig->data[dn])*sig->gain; + if (prset>sig->physical_maximum) { + int i=5; + } + sess->settings[CPAP_PresReliefSet]=prset; + } + + + if (mode==0) { + sess->settings[CPAP_Mode]=MODE_CPAP; + sig=stredf.lookupSignal(RMS9_SetPressure); // ?? What's meant by Set Pressure? + if (sig) { + EventDataType pressure=sig->data[dn]*sig->gain; + sess->settings[CPAP_Pressure]=pressure; + } + } else if (mode>5) { + if (mode>=7) + sess->settings[CPAP_Mode]=MODE_ASV; + else + sess->settings[CPAP_Mode]=MODE_BIPAP; + + EventDataType tmp,epap=0,ipap=0; + if (stredf.lookup.contains("EPAP")) { + sig=stredf.lookup["EPAP"]; + epap=sig->data[dn]*sig->gain; + sess->settings[CPAP_EPAP]=epap; + } + if (stredf.lookup.contains("IPAP")) { + sig=stredf.lookup["IPAP"]; + ipap=sig->data[dn]*sig->gain; + sess->settings[CPAP_IPAP]=ipap; + } + if (stredf.lookup.contains("PS")) { + sig=stredf.lookup["PS"]; + tmp=sig->data[dn]*sig->gain; + sess->settings[CPAP_PS]=tmp; // technically this is IPAP-EPAP + if (!ipap) { + // not really possible. but anyway, just in case.. + sess->settings[CPAP_IPAP]=epap+tmp; + } + } + if (stredf.lookup.contains("Min PS")) { + sig=stredf.lookup["Min PS"]; + tmp=sig->data[dn]*sig->gain; + sess->settings[CPAP_PSMin]=tmp; + sess->settings[CPAP_IPAPLo]=epap+tmp; + sess->setMin(CPAP_IPAP,epap+tmp); + } + if (stredf.lookup.contains("Max PS")) { + sig=stredf.lookup["Max PS"]; + tmp=sig->data[dn]*sig->gain; + sess->settings[CPAP_PSMax]=tmp; + sess->settings[CPAP_IPAPHi]=epap+tmp; + } + if (stredf.lookup.contains("RR")) { // Is this a setting to force respiratory rate on S/T machines? + sig=stredf.lookup["RR"]; + tmp=sig->data[dn]; + sess->settings[CPAP_RespRate]=tmp*sig->gain; + } + + if (stredf.lookup.contains("Easy-Breathe")) { + sig=stredf.lookup["Easy-Breathe"]; + tmp=sig->data[dn]*sig->gain; + + sess->settings[CPAP_PresReliefSet]=tmp; + sess->settings[CPAP_PresReliefType]=(int)PR_EASYBREATHE; + sess->settings[CPAP_PresReliefMode]=(int)PM_FullTime; + } + + } else { + sess->settings[CPAP_Mode]=MODE_APAP; + sig=stredf.lookupSignal(CPAP_PressureMin); + if (sig) { + EventDataType pressure=sig->data[dn]*sig->gain; + sess->settings[CPAP_PressureMin]=pressure; + //sess->setMin(CPAP_Pressure,pressure); + } + sig=stredf.lookupSignal(CPAP_PressureMax); + if (sig) { + EventDataType pressure=sig->data[dn]*sig->gain; + sess->settings[CPAP_PressureMax]=pressure; + //sess->setMax(CPAP_Pressure,pressure); + } + + } + + m->AddSession(sess,profile); + + a=QString("[%3] %1:%2, ").arg(on.toString()).arg(off.toString()).arg(sid); + qDebug() << a.toStdString().data(); + } + + + } +*/ + #ifdef DEBUG_EFFICIENCY { qint64 totalbytes=0; diff --git a/sleepyhead/docs/release_notes.html b/sleepyhead/docs/release_notes.html index a2439e18..aabc1968 100644 --- a/sleepyhead/docs/release_notes.html +++ b/sleepyhead/docs/release_notes.html @@ -7,10 +7,6 @@

For a lot of you, this is a minor interim release mainly to bring the various platform builds in sync again and fix a couple of crashes.
To native Mac users this is a fairly large update because you missed out on the last one, if you weren't using the windows one in Parallels/etc.... (Thanks for being so patient!)

-

There is one caveat for this release on native Mac though, printing had to be disabled due to a change in MacOSX that broke something in the QT libraries which causes a consistent crash. -That bug is fixed in the next version of Qt, but something else broke there that's way worse.. Still waiting on upstream for a fix. -Hopefully next time I can switch it back on, but the feedback I've received indicates a lot of you would rather still have the software without it for now.
-

Oximetry importing support has been improved, so now you should be able to import directly from your CMS50X oximeters without messing around with the windows software.
Please remember, for achieving the best sync, always start your oximeter at the same time as your CPAP machine!
@@ -21,11 +17,11 @@ Also like to thank

  • Improved CMS50 Oximetry serial importing
  • +
  • Printing works on Mac OSX 10.8.x again
  • Support for the PRS1 Series 60, in large part due to a patch from Keary Griffin.
  • A bunch of small PRS1 fixes, especially for the AutoSV.
  • Added Flow Limit to the summary and overview screens. This can be a useful indicator in certain types of apnea.
  • Some 64-bit fixes, and some other bugfixes mainly useful to those building from source, especially on linux.
  • -
  • Added Melbourne as a timezone option.
  • Fixed some issues with the prescription changes table with certain machines.
  • diff --git a/sleepyhead/main.cpp b/sleepyhead/main.cpp index 32e6885e..60ae2b5d 100644 --- a/sleepyhead/main.cpp +++ b/sleepyhead/main.cpp @@ -70,7 +70,7 @@ void MyOutputHandler(QtMsgType type, const QMessageLogContext & context, const Q break; } #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) - msg=typestr+msgtxt+QString(" (%1:%2, %3)").arg(context.file).arg(context.line).arg(context.function); + msg=typestr+msgtxt;//+QString(" (%1:%2, %3)").arg(context.file).arg(context.line).arg(context.function); #else msg=typestr+msgtxt; #endif