/* Useful high-level functions for programs dealing with EBS files. Copyright (C) 1993/94 M. Prosch, R. Schamburger, A. Grossmann Institut fuer Physiologie und Biokybernetik (IPB), Universitaet Erlangen, Deutschland Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and related publications and that both that copyright notice and this permission notice appear in supporting documentation. The authors make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. Send your comments, suggestions or bug reports to ftpebs@uni-erlangen.de Or mail to Institut fuer Physiologie und Biokybernetik Markus Prosch Universitaetsstrasse 17 D-91054 Erlangen Germany $Id: ebsclass.cc,v 1.36 1995/03/02 16:10:52 boheigl Exp $ */ #include "ebsclass.h" #include "stream.h" #define BIGENDIAN 1 #define LITTLEENDIAN 2 #define YES 1 #define NO 0 #define TRUE 1 #define FALSE 0 #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif /* #include */ extern "C" { #include "ebs.h" #include #include #include #include #ifndef MSDOS #include int munmap(caddr_t, unsigned int); #endif } void error (char *s) { fprintf (stderr, "%s", s); } extern void MemUsage (char *info); static char *mystrdup(char const *todup) { if(todup == NULL) return NULL; char *p = new char[strlen(todup)+1]; strcpy(p, todup); return p; } static int empty (char const *in) { while (*in!= '\0') { if (!isspace (*in)) return (0); in++; } return (1); } void *EBSFile::ebs_time_t2buf(void *buf, unsigned long length, EBSFile::EBSTime const *ebs_time) { EBSTm const *etm= &(ebs_time->etm); switch (ebs_time->info) { case date_and_time: if (length!=4) return (NULL); sprintf( (char *) buf, "%04d%02d%02dT%02d%02d%02d", etm->year, etm->month, etm->day, etm->hour, etm->minute, etm->second); break; case only_date: if (length!=2) return (NULL); sprintf ( (char *) buf, "%04d%02d%02d", etm->year, etm->month, etm->day); break; case only_year: if (length!=1) return (NULL); sprintf ( (char *) buf, "%04d", etm->year); case only_time: default: break; } return (buf); } void EBSFile::buf2ebs_time_t(void const *buf, unsigned long length, EBSTime *ebs_time) { char *string = (char *)buf; if(((length==4) && (string[8]=='T') && (string[15]=='\0') && isdigit(string[ 0]) && isdigit(string[ 1]) && isdigit(string[ 2]) && isdigit(string[ 3]) && isdigit(string[ 4]) && isdigit(string[ 5]) && isdigit(string[ 6]) && isdigit(string[ 7]) && isdigit(string[ 9]) && isdigit(string[10]) && isdigit(string[11]) && isdigit(string[12]) && isdigit(string[13]) && isdigit(string[14])) || ((length==2) && isdigit(string[ 0]) && isdigit(string[ 1]) && isdigit(string[ 2]) && isdigit(string[ 3]) && isdigit(string[ 4]) && isdigit(string[ 5]) && isdigit(string[ 6]) && isdigit(string[ 7])) || ((length==1) && isdigit(string[ 0]) && isdigit(string[ 1]) && isdigit(string[ 2]) && isdigit(string[ 3]))) { struct tm tm; if (length == 4) sscanf (string, "%4d%2d%2dT%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,&tm.tm_min, &tm.tm_sec); if (length == 2) { sscanf (string, "%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday); tm.tm_sec = 0; tm.tm_min = 0; tm.tm_hour= 0; } if (length == 1) { sscanf (string, "%4d", &tm.tm_year); tm.tm_sec = 0; tm.tm_min = 0; tm.tm_hour= 0; tm.tm_mon = 1; tm.tm_mday= 1; } ebs_time->etm.year= tm.tm_year; ebs_time->etm.month= tm.tm_mon; ebs_time->etm.day= tm.tm_mday; ebs_time->etm.hour= tm.tm_hour; ebs_time->etm.minute= tm.tm_min; ebs_time->etm.second= tm.tm_sec; ebs_time->etm.fraction=0; tm.tm_year-= 1900; tm.tm_mon--; tm.tm_wday= -1; tm.tm_yday= -1; tm.tm_isdst= -1; // tm.tm_zone= NULL; // tm.tm_gmtoff= 0; ebs_time->time = mktime(&tm); ebs_time->utc= (ebs_time->time!= (time_t) -1); if (ebs_time->time == (time_t)-1) { ebs_time->info = no_date_or_time; } else if(length == 4) ebs_time->info = date_and_time; else ebs_time->info = only_date; } else ebs_time->info = no_date_or_time; } char const *EBSFile::EBSTimeToString2 (EBSFile::EBSTime const *ebs_time, EBSFile::TimeInfo info, int fractions, char *buf, unsigned long buflen) { static char text[50]; struct tm etm, *t; if (buf == NULL) { // wenn kein Puffer uebergeben wurde buf = text; buflen = sizeof text; } if (buflen== 0) return (NULL); // not even [0]= '\0' possible *buf= '\0'; if (info== no_date_or_time || ebs_time->info== no_date_or_time) return (buf); if (info!= ebs_time->info && ebs_time->info!= date_and_time) { if ((info== only_year || info== only_date) && ebs_time->info== only_time) return (buf); if ((ebs_time->info== only_year || ebs_time->info== only_date) && info== only_time) return (buf); if (info== date_and_time) info= ebs_time->info; } if (ebs_time->utc) t= localtime(&(ebs_time->time)); else { etm.tm_sec= ebs_time->etm.second; etm.tm_min= ebs_time->etm.minute; etm.tm_hour= ebs_time->etm.hour; etm.tm_mday= ebs_time->etm.day; etm.tm_mon= ebs_time->etm.month-1; etm.tm_year= ebs_time->etm.year-1900; etm.tm_wday= -1; etm.tm_yday= -1; // etm.tm_zone= NULL; // etm.tm_gmtoff= 0; etm.tm_isdst= -1; t= &etm; } if (t== NULL) return (buf); switch (info) { case EBSFile::only_year: strftime (buf, buflen, "%Y", t); break; case EBSFile::only_time: strftime (buf, buflen, "%X", t); break; case EBSFile::only_date: strftime (buf, buflen, "%x", t); break; case EBSFile::date_and_time: strftime (buf, buflen, "%c", t); break; default: buf[0]='\0'; break; } if (fractions && (info== EBSFile::only_time || info== EBSFile::date_and_time) && strlen(buf)+4< buflen) sprintf (buf+strlen(buf), ",%02d", (int) ((ebs_time->etm.fraction)*100)); return buf; } char const *EBSFile::EBSTimeToString2 (EBSFile::EBSTime ebs_time, EBSFile::TimeInfo info, int fractions, char *buf, unsigned long buflen) { return (EBSTimeToString2 (&ebs_time, info, fractions, buf, buflen)); } char const *EBSFile::EBSTimeToString (EBSFile::EBSTime const *ebs_time, char *buf, unsigned long buflen) { return EBSTimeToString2(ebs_time, ebs_time->info, 0, buf, buflen); } char const *EBSFile::EBSTimeToString (EBSFile::EBSTime ebs_time, char *buf, unsigned long buflen) { return EBSTimeToString (&ebs_time, buf, buflen); } EBSFile::EBSTime EBSFile::EBSTime::operator+ (double sec) { EBSTime result; struct tm *tm; USampleT sum; time_t t; double d; if (this->info== no_date_or_time) { result.info= no_date_or_time; return (result); } if (this->utc) { sum= (USampleT) (this->time+ sec+ this->etm.fraction); t= (time_t) sum; tm= localtime(&t); if (tm==NULL) error ("operator+: localtime not possible"); result.info= this->info; result.utc= 1; result.time= (time_t) sum; result.etm.year= tm->tm_year; result.etm.month= tm->tm_mon+1; result.etm.day= tm->tm_mday; result.etm.hour= tm->tm_hour; result.etm.minute= tm->tm_min; result.etm.second= tm->tm_sec; d= this->etm.fraction+ sec; d-= (USampleT) d; result.etm.fraction= d; return (result); } else error ("operator+: option not yet implemented"); result.info= no_date_or_time; return (result); } EBSFile::EBSTime EBSFile::EBSTime::operator+ (USampleT sec) { EBSTime result; struct tm *tm; time_t t; if (this->info== no_date_or_time) { result.info= no_date_or_time; return (result); } if (this->utc) { t= this->time+ (time_t) sec; tm= localtime(&t); if (tm==NULL) error ("operator+: localtime not possible"); result.info= this->info; result.utc= 1; result.time= t; result.etm.year= tm->tm_year; result.etm.month= tm->tm_mon+1; result.etm.day= tm->tm_mday; result.etm.hour= tm->tm_hour; result.etm.minute= tm->tm_min; result.etm.second= tm->tm_sec; result.etm.fraction= this->etm.fraction; return (result); } else error ("operator+: option not yet implemented"); result.info= no_date_or_time; return (result); } EBSFile::EBSTime EBSFile::EBSTime::operator+ (EBSFile::EBSTm d) { double sec; sec= ((((d.year*12+ d.month)*30+ d.day)*24+ d.hour)*60+ d.minute)+ d.second+ d.fraction; return (*this+ sec); } #if 0 { EBSTm t; USampleT sec; if (d<=1e-9) { t.year=t.month=t.day=0; t.hour=t.minute=t.second=t.fraction=0; if (d<0) error("Negative time"); return (t); } sec= d; t.fraction= d- sec; t.year= sec/ (360* 24* 3600l); sec-= t.year* (360* 24* 3600l); t.month= sec/ (30* 24* 3600l); sec-= t.month* (30* 24* 3600l); t.day= sec/ (24* 3600l); sec-= t.day* (24* 3600l); t.hour= sec/ 3600l; sec-= t.hour* 3600l; t.minute= sec/ 60l; sec-= t.minute* 60l; t.second= sec; return (t); } #endif EBSFile::EBSTm EBSFile::EBSTimeToTm (EBSFile::EBSTime ebs_time) { return (ebs_time.etm); } EBSFile::EBSTime EBSFile::EBSTmToTime (EBSFile::EBSTm etm, EBSFile::TimeInfo info) { struct tm t; struct EBSTime ebs_time; ebs_time.info= info; if (info== no_date_or_time) return (ebs_time); switch (info) { case only_year: etm.month= 11; etm.day= 28; case only_date: etm.hour= 0; etm.minute= 0; etm.second= 0; etm.fraction= 0; break; case only_time: etm.year= 1969; etm.month= 11; etm.day= 28; default: break; } if (etm.year< 1900 || etm.year> 2100 || etm.month< 1 || etm.month> 12 || etm.day< 1 || etm.day> 31 || etm.hour< 0 || etm.hour> 23 || etm.minute< 0 || etm.minute> 59 || etm.second< 0 || etm.second> 59 || etm.fraction< 0.0 || etm.fraction>= 1.0) return (ebs_time); t.tm_sec= etm.second; t.tm_min= etm.minute; t.tm_hour= etm.hour; t.tm_mday= etm.day; t.tm_mon= etm.month-1; t.tm_year= etm.year-1900; t.tm_wday= -1; t.tm_yday= -1; // t.tm_zone= NULL; // t.tm_gmtoff= 0; t.tm_isdst= -1; ebs_time.etm= etm; ebs_time.time = mktime(&t); ebs_time.utc= (ebs_time.time!= (time_t) -1); return (ebs_time); } EBSFile::EBSFile(char const *fname, char m, int defaults) { static char null= 0; usedefaults= defaults; // Initialsierung emptystring= &null; valid = 1; // valid 1 / invalid 0 patientname = NULL; dateofbirth = NULL; sexofpatient = sex_unknown; patientid = NULL; institution = NULL; rectimebuf = NULL; shortdesc = NULL; description = NULL; chngroups = NULL; chlocations = NULL; prochistory = NULL; samplerate= NULL; prefrange = NULL; chdescriptions = NULL; units = NULL; filters = NULL; yscale= NULL; nassumed= NULL; eventlist_int = NULL; eventlist= NULL; neventlists= 0; datamap = NULL; writechnpos = NULL; lastvaluechn = NULL; channelinfo = NULL; event.description= NULL; nsamples_int= NULL; filename = mystrdup(fname); // Kopie des Dateinamen anfertigen if(filename == NULL) { perror("No memory:"); SetInvalid(); return; ;//throw NoMem(); } mode = m; ebsstruct = ebs_open(filename, mode); if(ebsstruct == NULL) { perror(filename); // test test test test test test 1 2 3 SetInvalid(); return; ;//throw FileError(); } fstream = ebsstruct->fd; fd = fileno (fstream); /* Anzahl der Samples per channel bestimmen, falls nicht angegeben */ ebs_getfixedheader(ebsstruct, &fixed); if(mode == 'w') { nsamples = 0; nchannels = 0; } else { nsamples = determinesamples(); // mapped die Datei auch gleich nchannels = fixed.channels; } // von welchem Typ ist die EBS-Datei und kann sie groesser werden? ebs_type = fixed.encoding_id; if((ebs_type == EBS_TI_16D) || (ebs_type == EBS_CI_16D)) compresseddata = TRUE; else compresseddata = FALSE; if(ebs_type == EBS_CIB_16 || ebs_type == EBS_CIL_16 || ebs_type == EBS_CI_16D) // alle Channel-Based Order data_could_grow = NO; else data_could_grow = YES; channelinfo = new chninfo[nchannels]; int i; for(i = 0; i < nchannels; i++) { if(!compresseddata) { channelinfo[i].samnow = 0; channelinfo[i].valid = TRUE; } else channelinfo[i].valid = FALSE; } // bestimme ob Littleendian- oder Bigendian-Maschine unsigned int dummy = 1; if(*(char *)&dummy == 0) endian = BIGENDIAN; else endian = LITTLEENDIAN; #ifdef MSDOS data_could_grow = NO; if((ebs_type == EBS_TIB_16) || (ebs_type == EBS_TIL_16) || (ebs_type == EBS_CIB_16) || (ebs_type == EBS_CIL_16)) ValueType = &EBSFile::ValueMSDOS; else ValueType = &EBSFile::ValueNotSupp; ddata_offset = ebs_data_offset(ebsstruct); #else if(mode == 'r') { if(mapdatablock() == -1) { SetInvalid(); return; } // bestimme und setze ValueFunktion abhaengig von Little- und Bigendian if(ebs_type == EBS_TIB_16) { if(endian == BIGENDIAN) ValueType = &EBSFile::ValueT; else ValueType = &EBSFile::ValueTR; } else if(ebs_type == EBS_TIL_16) { if(endian == BIGENDIAN) ValueType = &EBSFile::ValueTR; else ValueType = &EBSFile::ValueT; } else if(ebs_type == EBS_CIB_16) { if(endian == BIGENDIAN) ValueType = &EBSFile::ValueC; else ValueType = &EBSFile::ValueCR; } else if(ebs_type == EBS_CIL_16) { if(endian == BIGENDIAN) ValueType = &EBSFile::ValueCR; else ValueType = &EBSFile::ValueC; } else ValueType = &EBSFile::ValueNotSupp; // komprimierte werden nicht unterstuetzt } else { if((ebs_type == EBS_TIB_16) || (ebs_type == EBS_TIL_16) || (ebs_type == EBS_CIB_16) || (ebs_type == EBS_CIL_16)) ValueType = &EBSFile::ValueMSDOS; else ValueType = &EBSFile::ValueNotSupp; ddata_offset = ebs_data_offset(ebsstruct); } #endif } EBSFile::~EBSFile(void) { uint32 i; delete [] filename; delete [] channelinfo; delete [] patientname; delete dateofbirth; delete [] patientid; delete [] institution; delete rectimebuf; delete [] shortdesc; delete [] description; if(chngroups != NULL) { for(i = 0; i < chngroups->ngroups; i++) { delete [] chngroups->group[i].name; delete [] chngroups->group[i].description; delete [] chngroups->group[i].channel; } delete [] chngroups->group; delete chngroups; } if (chlocations!= NULL) { delete [] chlocations->location; delete chlocations; } if(prochistory != NULL) { for(i = 0; i < prochistory->nlines; i++) delete prochistory->line [i]; delete [] prochistory->line; delete prochistory; } delete [] samplerate; delete [] prefrange; if(chdescriptions != NULL) for(i = 0; i < nchannels; i++) { delete(chdescriptions[i].short_description); delete(chdescriptions[i].long_description); } delete [] chdescriptions; if(units != NULL) for(i = 0; i < nchannels; i++) delete units[i].unit; delete [] units; if(filters != NULL) { for(i = 0; i < nchannels; i++) if(filters[i].nfilters > 0) delete [] filters[i].filter; delete [] filters; } delete [] yscale; delete(writechnpos); delete(lastvaluechn); delete [] nsamples_int; delete [] nassumed; if (eventlist!= NULL) for (i= 0; i< neventlists; ++i) { delete eventlist[i].name; delete eventlist[i].description; } delete [] eventlist; delete [] eventlist_int; #ifndef MSDOS // unmappe Datei if((mode != 'm') && (mode != 'w') && datamap!= NULL && filesize== 0) if((munmap(datamap, filesize)) == -1) { perror("unmap: "); } #endif ebs_close(ebsstruct); } char const *EBSFile::GetFilenameWithPath (void) { return (filename); } char const *EBSFile::GetOnlyFilename (void) { char *ptr; if (filename==NULL) return (NULL); #ifndef MSDOS if ((ptr= strrchr (filename, '/'))!= NULL) return (ptr+1); return (filename); #else if ((ptr= strrchr (filename, '\\'))!= NULL) return (ptr+1); if ((ptr= strrchr (filename, ':'))!= NULL && ptr== filename+ 1) return (ptr+1); return (filename); #endif } /* should be called before calling ebs_putattr() */ void EBSFile::BeforePutAttr (void) { ebs_mak2varheader(ebsstruct); } char const *EBSFile::GetPatientName(void) { if(patientname != NULL) return patientname; void *unichar; uint32 unilen; unichar = ebs_getattr(ebsstruct, EBS_PATIENT_NAME, &unilen); if(unichar == NULL) return emptystring; uint32 buflen = unilen*2; // unilen in words => (unilen*4)/2 patientname = new char[buflen]; gets4(patientname, buflen, &unichar); return patientname; } int EBSFile::SetPatientName(char const * nameofpatient) { void *unichar, *hlp; uint32 unilen; int is_put_ok; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (nameofpatient== NULL || empty (nameofpatient)) return (ebs_clearattr (ebsstruct, EBS_PATIENT_NAME)); unilen=s4len(nameofpatient); //liefert Anzahl der words unichar= (void *) new char[unilen*4]; //deshalb *4 hlp=unichar; //unichar zeigt nach puts4 ans ende des unistrings puts4(nameofpatient, &unichar); BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_PATIENT_NAME, hlp, unilen); delete [] hlp; if (is_put_ok == 0) { //wenn alles geklappt hat delete [] patientname; //gebe alten Speicher frei patientname=mystrdup(nameofpatient); //und cache patientname } return is_put_ok; //0 oder -1 durch ebs_putattr } EBSFile::EBSTime EBSFile::GetPatientBirthday(void) { if(dateofbirth != NULL) return *dateofbirth; void *buf; uint32 length; buf = ebs_getattr(ebsstruct, EBS_PATIENT_BIRTHDAY, &length); dateofbirth = new EBSTime; if(buf == NULL) { dateofbirth->info = no_date_or_time; return *dateofbirth; } buf2ebs_time_t(buf, length, dateofbirth); return *dateofbirth; } int EBSFile::SetPatientBirthday(EBSFile::EBSTime date) { void *buf; uint32 length; int is_put_ok; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (date.info== no_date_or_time) return (ebs_clearattr (ebsstruct, EBS_PATIENT_BIRTHDAY)); if(date.info!=only_date && date.info!=only_year) return (-1); if (date.info== only_date) length=2; //# words else length=1; buf=new char[9]; ebs_time_t2buf(buf, length, &date); BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_PATIENT_BIRTHDAY, buf, length); delete [] buf; if (is_put_ok == 0) { //wenn alles geklappt hat delete dateofbirth; //gebe alten Speicher frei dateofbirth=new EBSTime; //erzeuge dateofbirth neu *dateofbirth= date; //und cache birthdaybuf } return is_put_ok; } EBSFile::Sex EBSFile::GetPatientSex(void) { if(sexofpatient != sex_unknown) return sexofpatient; void *sexbuf; uint32 len; sexbuf = ebs_getattr(ebsstruct, EBS_PATIENT_SEX, &len); if(sexbuf == NULL) return sex_unknown; sexofpatient = (Sex) geti32(&sexbuf); if (sexofpatient!=sex_male && sexofpatient!=sex_female) sexofpatient= sex_unknown; return sexofpatient; } int EBSFile::SetPatientSex(Sex patientsex) { int is_put_ok; uint32 hh; void *ptr= &hh, *ptr2= ptr; puti32 ((uint32) patientsex, &ptr); if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if(patientsex == sex_unknown) return (ebs_clearattr (ebsstruct, EBS_PATIENT_SEX)); BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_PATIENT_SEX, (void *) ptr2, 1); if(is_put_ok == 0) //wenn alles ok dann sexofpatient = patientsex; //cache sexofpatient return is_put_ok; } char const *EBSFile::GetPatientID(void) { if(patientid != NULL) return patientid; void *unichar; uint32 unilen; unichar = ebs_getattr(ebsstruct, EBS_PATIENT_ID, &unilen); if(unichar == NULL) return emptystring; uint32 buflen = unilen*2; // unilen in words => (unilen*4)/2 patientid = new char[buflen]; gets4(patientid, buflen, &unichar); return patientid; } int EBSFile::SetPatientID(char const * idofpatient) { void *unichar, *hlp; uint32 unilen; int is_put_ok; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (idofpatient== NULL || empty (idofpatient)) return (ebs_clearattr (ebsstruct, EBS_PATIENT_ID)); unilen=s4len(idofpatient); //liefert Anzahl der words unichar=new char[unilen*4]; //deshalb *4 hlp=unichar; //unichar zeigt nach puts4 ans ende des unistrings puts4(idofpatient, &unichar); BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_PATIENT_ID, hlp, unilen); delete [] hlp; if (is_put_ok == 0) { //wenn alles geklappt hat delete [] patientid; //gebe alten Speicher frei patientid=mystrdup(idofpatient); //patientid cachen } return is_put_ok; //0 oder -1 durch ebs_putattr } char const *EBSFile::GetInstitution(void) { if(institution != NULL) return institution; void *unichar; uint32 unilen; unichar = ebs_getattr(ebsstruct, EBS_INSTITUTION, &unilen); if(unichar == NULL) return emptystring; uint32 buflen = unilen*2; // unilen in words => (unilen*4)/2 institution= new char[buflen]; gets4(institution, buflen, &unichar); return institution; } int EBSFile::SetInstitution(char const * insti) { void *unichar, *hlp; uint32 unilen; int is_put_ok; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (insti== NULL || empty (insti)) return (ebs_clearattr (ebsstruct, EBS_INSTITUTION)); unilen=s4len(insti); //liefert Anzahl der words unichar=new char[unilen*4]; //deshalb *4 hlp=unichar; //unichar zeigt nach puts4 ans ende des unistrings puts4(insti, &unichar); BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_INSTITUTION, hlp, unilen); delete [] hlp; if (is_put_ok == 0) { //wenn alles geklappt hat delete [] institution; //gebe alten Speicher frei institution=mystrdup(insti); //institution cachen } return is_put_ok; //0 oder -1 durch ebs_putattr } EBSFile::EBSTime EBSFile::GetRecordingTime(void) { if(rectimebuf != NULL) return *rectimebuf; rectimebuf = new EBSTime; void *buf; uint32 length; buf = ebs_getattr(ebsstruct, EBS_RECORDING_TIME, &length); if(buf == NULL) { rectimebuf->info = no_date_or_time; return *rectimebuf; } buf2ebs_time_t(buf, length, rectimebuf); return *rectimebuf; } int EBSFile::SetRecordingTime(EBSFile::EBSTime rectime) { void *buf; uint32 length; int is_put_ok; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (rectime.info== no_date_or_time) return (ebs_clearattr (ebsstruct, EBS_RECORDING_TIME)); if(rectime.info==date_and_time) { length=4; //# words buf=new char[16]; } else if(rectime.info==only_date) { length=2; //# words buf=new char[9]; } else return -1; ebs_time_t2buf(buf, length, &rectime); BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_RECORDING_TIME, buf, length); delete [] buf; if (is_put_ok == 0) { //wenn alles geklappt hat delete rectimebuf; //gebe alten Speicher frei rectimebuf=new EBSTime; //erzeuge rectimebuf neu *rectimebuf= rectime; //und cache rectimebuf } return is_put_ok; } char const *EBSFile::GetShortDescription(void) { if(shortdesc != NULL) return shortdesc; void *unichar; uint32 unilen; unichar = ebs_getattr(ebsstruct, EBS_SHORT_DESCRIPTION, &unilen); if(unichar == NULL) return emptystring; uint32 buflen = unilen*2; // unilen in words => (unilen*4)/2 shortdesc = new char[buflen]; gets4(shortdesc, buflen, &unichar); return shortdesc; } int EBSFile::SetShortDescription(char const * s_desc) { void *unichar, *hlp; uint32 unilen; int is_put_ok; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (s_desc== NULL || empty (s_desc)) return (ebs_clearattr (ebsstruct, EBS_SHORT_DESCRIPTION)); unilen=s4len(s_desc); //liefert Anzahl der words unichar=new char[unilen*4]; //deshalb *4 hlp=unichar; //unichar zeigt nach puts4 ans ende des unistrings puts4(s_desc, &unichar); BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_SHORT_DESCRIPTION, hlp, unilen); delete [] hlp; if (is_put_ok == 0) { //wenn alles geklappt hat delete [] shortdesc; //gebe alten Speicher frei shortdesc=mystrdup(s_desc); //shortdescription cachen } return is_put_ok; //0 oder -1 durch ebs_putattr } char const *EBSFile::GetDescription(void) { if(description != NULL) return description; void *unichar; uint32 unilen; unichar = ebs_getattr(ebsstruct, EBS_DESCRIPTION, &unilen); if(unichar == NULL) return emptystring; uint32 buflen = unilen*2; // unilen in words => (unilen*4)/2 description = new char[buflen]; gets4(description, buflen, &unichar); return description; } int EBSFile::SetDescription(char const * descr) { void *unichar, *hlp; uint32 unilen; int is_put_ok; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (descr== NULL || empty (descr)) return (ebs_clearattr (ebsstruct, EBS_DESCRIPTION)); unilen=s4len(descr); //liefert Anzahl der words unichar=new char[unilen*4]; //deshalb *4 hlp=unichar; //unichar zeigt nach puts4 ans ende des unistrings puts4(descr, &unichar); BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_DESCRIPTION, hlp, unilen); delete [] hlp; if (is_put_ok == 0) { //wenn alles geklappt hat delete [] description; //gebe alten Speicher frei description=mystrdup(descr); //description cachen } return is_put_ok; //0 oder -1 durch ebs_putattr } EBSFile::ChannelGroups const *EBSFile::GetChannelGroups(void) { if(chngroups != NULL) return (chngroups); void *buf; uint32 buflen; buf = ebs_getattr(ebsstruct, EBS_CHANNEL_GROUPS, &buflen); if(buf == NULL) return (NULL); // Wieviele Gruppen gibt es? void *help = buf; void *end = (void *)((char *) buf+(4*buflen)); uint32 tbuflen = buflen*4+1; char *tbuf = new char[tbuflen]; // Textpuffer uint32 k; uint32 i = 0; // Anzahl der Gruppen uint32 g = 0; // Anzahl der Channels pro Gruppe while(help < end) { gets4(tbuf, tbuflen, &help); gets4(tbuf, tbuflen, &help); g = geti32(&help); for(k = 0; k < g; k++) geti32(&help); i++; } // nun lese die Gruppen in die Struktur chngroups= new ChannelGroups; chngroups->ngroups = i; chngroups->group = new ChannelGroup [i]; i = 0; help = buf; while(help < end) { gets4(tbuf, tbuflen, &help); chngroups->group[i].name = mystrdup(tbuf); gets4(tbuf, tbuflen, &help); chngroups->group[i].description = mystrdup(tbuf); g = geti32(&help); chngroups->group[i].nchannels = g; chngroups->group[i].channel = new uint32 [g]; for(k = 0; k < g; k++) chngroups->group[i].channel[k] = (uint32) geti32(&help); i++; } delete [] tbuf; return chngroups; } int EBSFile::SetChannelGroups(ChannelGroups const * chgrp) { int is_put_ok; uint32 len=0; void *hlp, *buf; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (chgrp== NULL || chgrp->ngroups== 0) return (ebs_clearattr (ebsstruct, EBS_CHANNEL_GROUPS)); int i, j; for(i = 0; i < chgrp->ngroups; i++) { //bestimme die groesse des buffers len += s4len(chgrp->group[i].name); len += s4len(chgrp->group[i].description); len += chgrp->group[i].nchannels +1; //Anz. Chnls d. Gruppe + Number-Feld for (j= 0; j< chgrp->group[i].nchannels; ++j) if (chgrp->group[i].channel [j]>= nchannels) return (-1); } buf = (char *) new char[len*4]; //reserviere nun Speicher fuer buf hlp=buf; for(i = 0; i < chgrp->ngroups; i++) { //erzeuge buffer puts4(chgrp->group[i].name, &buf); puts4(chgrp->group[i].description, &buf); puti32(chgrp->group[i].nchannels, &buf); for(j = 0; j < chgrp->group[i].nchannels; j++) { puti32(chgrp->group[i].channel[j], &buf); } } BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_CHANNEL_GROUPS, hlp, len); delete [] hlp; if(is_put_ok == 0) { if(chngroups != NULL) for(i = 0; i < chngroups->ngroups; i++) { delete [] chngroups->group[i].name; delete [] chngroups->group[i].description; delete [] chngroups->group[i].channel; } delete [] chngroups->group; delete chngroups; chngroups = new ChannelGroups; chngroups->group= new ChannelGroup [chgrp->ngroups]; for(i = 0; i < chgrp->ngroups; i++) { //cache chgroups + ngroups chngroups->group[i].name = mystrdup(chgrp->group[i].name); chngroups->group[i].description = mystrdup(chgrp->group[i].description); chngroups->group[i].nchannels = chgrp->group[i].nchannels; chngroups->group[i].channel = new uint32 [chgrp->group[i].nchannels]; for(j = 0; j < chgrp->group[i].nchannels; j++) { chngroups->group[i].channel[j] = chgrp->group[i].channel[j]; } } chngroups->ngroups = chgrp->ngroups; } return is_put_ok; } EBSFile::LocationDiagram const *EBSFile::GetLocationDiagram(void) { void *ptr; uint32 len; static LocationDiagram result; ptr= ebs_getattr(ebsstruct, EBS_LOCATION_DIAGRAM, &len); if (ptr== NULL) return (NULL); result.ptr= ptr; result.size= len; return (&result); } int EBSFile::SetLocationDiagram(LocationDiagram const *diag) { int is_put_ok; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (diag== NULL || diag->size== 0 || diag->ptr== NULL) return (ebs_clearattr (ebsstruct, EBS_LOCATION_DIAGRAM)); if(diag->size < 1) return -1; BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_LOCATION_DIAGRAM, diag->ptr, diag->size); return is_put_ok; } EBSFile::ChannelLocations const *EBSFile::GetChannelLocations(void) { if(chlocations != NULL) return chlocations; void *buffer; uint32 bufferlen; buffer = ebs_getattr(ebsstruct, EBS_CHANNEL_LOCATIONS, &bufferlen); if(buffer == NULL) return (NULL); bufferlen = bufferlen/6; chlocations = new ChannelLocations; chlocations->location= new ChannelLocation [bufferlen]; int i; for(i = 0; i < bufferlen; i++) { chlocations->location[i].channel = geti32(&buffer); chlocations->location[i].picture = geti32(&buffer); chlocations->location[i].x1 = geti32(&buffer); chlocations->location[i].y1 = geti32(&buffer); chlocations->location[i].x2 = geti32(&buffer); chlocations->location[i].y2 = geti32(&buffer); } chlocations->nlocations= bufferlen; return chlocations; } int EBSFile::SetChannelLocations(ChannelLocations const * chloc) { int is_put_ok; unsigned long len=chloc->nlocations*6; //*6 wg. struktur void *hlp, *buf; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (chloc== NULL || chloc->nlocations== 0) return (ebs_clearattr (ebsstruct, EBS_CHANNEL_LOCATIONS)); buf = (void *) new char [len*4]; hlp=buf; int i; for(i = 0; i < chloc->nlocations; i++) { //erzeuge buffer puti32(chloc->location[i].channel, &buf); puti32(chloc->location[i].picture, &buf); puti32(chloc->location[i].x1, &buf); puti32(chloc->location[i].y1, &buf); puti32(chloc->location[i].x2, &buf); puti32(chloc->location[i].y2, &buf); } BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_CHANNEL_LOCATIONS, hlp, len); delete [] hlp; if(is_put_ok == 0) { if (chlocations!= NULL) { delete [] chlocations->location; delete chlocations; } chlocations = new ChannelLocations; chlocations->location= new ChannelLocation [chloc->nlocations]; for(i = 0; i < chloc->nlocations; i++) { //cache chlocations + nchlocations chlocations->location[i] = chloc->location[i]; } chlocations->nlocations = chloc->nlocations; } return is_put_ok; } EBSFile::ProcessingHistory const *EBSFile::GetProcessingHistory(void) { if(prochistory != NULL) return prochistory; void *unichar; uint32 unilen; unichar = ebs_getattr(ebsstruct, EBS_PROCESSING_HISTORY, &unilen); if(unichar == NULL) return (NULL); // Wieviele Multi Line Textstrings gibt es? void *help = unichar; void *end = (void *)(((char *) unichar)+(4*unilen)); uint32 buflen = unilen*4+1; char *buf = new char[buflen]; unsigned long i = 0; while(help < end) { gets4(buf, buflen, &help); i++; } // nun lese die Multi Line Strings aus prochistory= new ProcessingHistory; prochistory->nlines= i; prochistory->line= new char* [i]; i = 0; help = unichar; while(help < end) { gets4(buf, buflen, &help); prochistory->line [i] = mystrdup(buf); i++; } delete [] buf; return prochistory; } int EBSFile::SetProcessingHistory(ProcessingHistory const *hist) { int is_put_ok; uint32 len=0; void *hlp, *buf; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (hist== NULL || hist->nlines== 0) return (ebs_clearattr (ebsstruct, EBS_PROCESSING_HISTORY)); int i; for(i = 0; i < hist->nlines; i++) //bestimme die groesse des buffers len += s4len(hist->line[i]); buf = (void *) new char[len*4]; hlp=buf; for(i = 0; i < hist->nlines; i++) { //erzeuge buffer puts4(hist->line[i], &buf); } BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_PROCESSING_HISTORY, hlp, len); delete [] hlp; if(is_put_ok == 0) { if(prochistory != NULL) { for(i = 0; i < prochistory->nlines; i++) delete [] prochistory->line [i]; delete [] prochistory->line; delete prochistory; } prochistory= new ProcessingHistory; prochistory->line = new char* [hist->nlines]; for(i = 0; i < hist->nlines; i++) { //cache prochistory + historylen prochistory->line[i] = mystrdup(hist->line[i]); } prochistory->nlines = hist->nlines; } return is_put_ok; } double const *EBSFile::GetSampleRate(void) { void *buf; uint32 buflen; if (samplerate!= NULL) return samplerate; buf = ebs_getattr(ebsstruct, EBS_SAMPLE_RATE, &buflen); if(buf == NULL) { if (!usedefaults) return (NULL); samplerate= new double [nchannels]; for (uint32 i= 0; i< nchannels; ++i) samplerate [i]= 1; return samplerate; } int nan; double value = getf4(&buf, &nan); if(nan == 0) { uint32 i; samplerate= new double [nchannels]; for (i= 0; i< nchannels; ++i) samplerate [i]= value; return samplerate; } else return NULL; } double EBSFile::GetMinSampleRate(void) { if (samplerate!=NULL) return (samplerate[0]); (void) GetSampleRate (); if (samplerate!=NULL) return (samplerate[0]); if (usedefaults) return (1.0); return (0.0); /* schrott */ } double EBSFile::GetMaxSampleRate(void) { if (samplerate!=NULL) return (samplerate[0]); (void) GetSampleRate (); if (samplerate!=NULL) return (samplerate[0]); if (usedefaults) return (1.0); return (0.0); /* schrott */ } int EBSFile::SetSampleRate(double const *srate) { int is_put_ok; int len; void *buf, *hlp; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (srate== NULL) return (ebs_clearattr (ebsstruct, EBS_SAMPLE_RATE)); len=f4len(srate [0]); buf=new char[len*4]; hlp=buf; putf4(srate[0], &buf); BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_SAMPLE_RATE, hlp, len); delete [] hlp; if(is_put_ok == 0) { delete [] samplerate; samplerate= new double [nchannels]; int i; for (i= 0; i< nchannels; ++i) samplerate [i]= srate [0]; } return is_put_ok; } EBSFile::PreferredIntegerRange const *EBSFile::GetPreferredIntegerRange (void) { if(prefrange != NULL) return prefrange; void *buf; uint32 buflen; buf = ebs_getattr(ebsstruct, EBS_PREFERRED_INTEGER_RANGE, &buflen); if(buf == NULL) { if (!usedefaults) return NULL; prefrange = new PreferredIntegerRange [nchannels]; for(uint32 i = 0; i < nchannels; i++) { prefrange[i].min = -32768; prefrange[i].max = +32767; } return prefrange; } prefrange = new PreferredIntegerRange [nchannels]; uint32 i; for(i = 0; i < nchannels; i++) { prefrange[i].min = geti32(&buf); prefrange[i].max = geti32(&buf); } return prefrange; } int EBSFile::SetPreferredIntegerRange(PreferredIntegerRange const * pirange) { int is_put_ok; void *hlp, *buf; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (pirange== NULL) return (ebs_clearattr (ebsstruct, EBS_PREFERRED_INTEGER_RANGE)); buf = new char[nchannels*(1+1)*4]; hlp=buf; int i; for(i = 0; i < nchannels; i++) { puti32(pirange[i].min, &buf); puti32(pirange[i].max, &buf); } BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_PREFERRED_INTEGER_RANGE, hlp, nchannels*(1+1)); delete [] hlp; if(is_put_ok == 0) { delete [] prefrange; //gebe alten Speicher frei prefrange = new PreferredIntegerRange[nchannels]; for(i = 0; i < nchannels; i++) // cache prefrange prefrange[i]= pirange[i]; } return is_put_ok; } EBSFile::ChannelDescription const *EBSFile::GetChannelDescription (void) { char *buf, *hlp; char text [20]; if(chdescriptions != NULL) return chdescriptions; void *unichar; uint32 unilen; unichar = ebs_getattr(ebsstruct, EBS_CHANNEL_DESCRIPTION, &unilen); if(unichar == NULL) { if (!usedefaults) return (NULL); chdescriptions = new ChannelDescription[nchannels]; for(uint32 i = 0; i < nchannels; i++) { sprintf (text, "%d\n", i+1); chdescriptions[i].short_description = mystrdup(text); chdescriptions[i].long_description = mystrdup(emptystring); } return chdescriptions; } chdescriptions = new ChannelDescription[nchannels]; buf = new char[unilen*4]; hlp=buf; int i; for(i = 0; i < nchannels; i++) { gets4(buf, unilen*4, &unichar); // Kurzbeschreibung if (empty (buf)) { sprintf (text, "%d\n", i+1); chdescriptions[i].short_description = mystrdup(text); } else chdescriptions[i].short_description = mystrdup(buf); gets4(buf, unilen*4, &unichar); // Zusaetzliche Beschreibung chdescriptions[i].long_description = mystrdup(buf); } delete [] hlp; return chdescriptions; } int EBSFile::SetChannelDescription(ChannelDescription const * cdesc) { int is_put_ok; void *hlp, *buf; int len=0; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (cdesc== NULL) return (ebs_clearattr (ebsstruct, EBS_CHANNEL_DESCRIPTION)); int i; for(i = 0; i < nchannels; i++) { //bestimme die groesse des buffers len += s4len(cdesc[i].short_description); len += s4len(cdesc[i].long_description); } buf = (char *) new char[len*4]; hlp=buf; for(i = 0; i < nchannels; i++) { //erzeuge buffer puts4(cdesc[i].short_description, &buf); puts4(cdesc[i].long_description, &buf); } BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_CHANNEL_DESCRIPTION, hlp, len); delete [] hlp; if(is_put_ok == 0) { if(chdescriptions != NULL) //gebe alten Speicher frei for(i =0; i < nchannels; i++) { delete (chdescriptions[i].short_description); delete (chdescriptions[i].long_description); } delete [] chdescriptions; chdescriptions = new ChannelDescription[nchannels]; for(i = 0; i < nchannels; i++) { //cache chdescriptions chdescriptions[i].short_description = mystrdup(cdesc[i].short_description); chdescriptions[i].long_description = mystrdup(cdesc[i].long_description); } } return is_put_ok; } EBSFile::Unit const *EBSFile::GetUnits(void) { char *buf, *hlp; if(units != NULL) return units; void *unichar; uint32 unilen; unichar = ebs_getattr(ebsstruct, EBS_UNITS, &unilen); if(unichar == NULL) { if (!usedefaults) return NULL; units = new Unit [nchannels]; for(uint32 i = 0; i < nchannels; i++) { units [i].quotient= 1.0; units [i].specified= YES; units [i].unit= mystrdup (emptystring); } return (units); } units = new Unit [nchannels]; buf= new char [unilen*4]; hlp= buf; int i; int nan; for(i = 0; i < nchannels; i++) { units[i].quotient = getf4(&unichar, &nan); if(nan == 0) { units[i].specified = YES; gets4 (buf, unilen, &unichar); units[i].unit = mystrdup(buf); } else { if (!usedefaults) { units[i].specified = NO; gets4 (buf, unilen, &unichar); units[i].unit = mystrdup(emptystring); } else { units [i].quotient= 1.0; units [i].specified= YES; units [i].unit= mystrdup (emptystring); } } } delete [] hlp; return units; } int EBSFile::SetUnits(Unit const * un) { int is_put_ok; void *hlp, *buf; int len=0; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (un== NULL) return (ebs_clearattr (ebsstruct, EBS_UNITS)); int i; for(i = 0; i < nchannels; i++) { //bestimme die groesse des buffers if (un[i].specified == YES) { len += f4len(un[i].quotient); len += s4len(un[i].unit); } else len += 1+1; //je ein word fuer nan und empty string } buf = new char[len*4]; //da len nun bekannt kann speicher alloziert werden hlp=buf; for(i = 0; i < nchannels; i++) { //erzeuge buffer if (un[i].specified == YES) { putf4(un[i].quotient, &buf); puts4(un[i].unit, &buf); } else { //unspezifizierte Unit puts4("\0", &buf); puts4("\0", &buf); } } BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_UNITS, hlp, len); delete [] hlp; if(is_put_ok == 0) { if(units != NULL) //gebe alten Speicher frei for(i =0; i < nchannels; i++) delete units[i].unit; delete [] units; units = new Unit[nchannels]; for(i = 0; i < nchannels; i++) { //cache nunits units[i].quotient = un[i].quotient; if(un[i].specified == NO) units[i].unit = mystrdup(emptystring); else units[i].unit = mystrdup(un[i].unit); units[i].specified = un[i].specified; } } return is_put_ok; } EBSFile::Filters const *EBSFile::GetFilters(void) { if(filters != NULL) return filters; void *buf; uint32 buflen; buf = ebs_getattr(ebsstruct, EBS_FILTERS, &buflen); if(buf == NULL) return (NULL); void *help; filters= new Filters [nchannels]; int i, nan, k, ftype, y; for(i = 0; i < nchannels; i++) { help = buf; ftype = geti32(&help); if(ftype == EBS_NO_FILTER) { filters[i].nfilters = 0; filters[i].filter = NULL; buf = help; } else { k = 0; // bestimme zuerst, wieviele Filter fuer diesen Kanal vorhanden sind while(ftype != EBS_NO_FILTER) { getf4(&help, &nan); getf4(&help, &nan); ftype = geti32(&help); k++; } filters[i].nfilters = k; filters[i].filter = new Filter[k]; for(y = 0; y < k; y++) { filters[i].filter[y].type = geti32(&buf); filters[i].filter[y].cutoff_freq = getf4(&buf, &nan); filters[i].filter[y].falloff = getf4(&buf, &nan); if(nan == 0) filters[i].filter[y].falloff_specified = YES; else filters[i].filter[y].falloff_specified = NO; } geti32(&buf); } } return filters; } int EBSFile::SetFilters(Filters const * fltr) { int is_put_ok; uint32 len=0; void *hlp, *buf; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (fltr== NULL) return (ebs_clearattr (ebsstruct, EBS_FILTERS)); int i,j; for(i = 0; i < nchannels; i++) { //bestimme die groesse des buffers for(j = 0; j < fltr[i].nfilters; j++) { len++; // Feld type (int) len += f4len(fltr[i].filter[j].cutoff_freq); if(fltr[i].filter[j].falloff_specified==YES) len += f4len(fltr[i].filter[j].falloff); else len++; //unspezifiziert = nan = 0x00000000 } len++; //Abschluss mit 0xffffffff fuer jeden Kanal } buf = (void *) new char[len*4]; //reserviere nun Speicher fuer buf hlp=buf; for(i = 0; i < nchannels; i++) { //erzeuge buffer if(fltr[i].nfilters > 0) for(j = 0; j < fltr[i].nfilters; j++) { puti32(fltr[i].filter[j].type, &buf); //Filtertyp putf4(fltr[i].filter[j].cutoff_freq, &buf); if(fltr[i].filter[j].falloff_specified==YES) putf4(fltr[i].filter[j].falloff, &buf); else puts4("\0", &buf); //unspezifiziert = nan = 0x00000000 } puti32(EBS_NO_FILTER, &buf); //EBS_NO_FILTER am Ende } BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_FILTERS, hlp, len); delete [] hlp; if(is_put_ok == 0) { if (filters != NULL) { for(i = 0; i < nchannels; i++) if(filters[i].nfilters > 0) delete [] filters[i].filter; delete [] filters; } filters = new Filters [nchannels]; for(i = 0; i < nchannels; i++) { //cache filters filters[i].nfilters = fltr[i].nfilters; if(fltr[i].nfilters > 0) { filters[i].filter = new Filter [fltr[i].nfilters]; for(j = 0; j < fltr[i].nfilters; j++) filters[i].filter[j] = fltr[i].filter[j]; } else filters[i].filter = NULL; } } return is_put_ok; } uint32 EBSFile::GetNChannels(void) { return nchannels; } USampleT const *EBSFile::GetNSamples(void) { if(data_could_grow == NO && nsamples_int!=NULL) return nsamples_int; #ifndef MSDOS USampleT newsam = determinesamples(); if(newsam != nsamples) { nsamples= newsam; // unmappe Datei if((munmap(datamap, filesize)) == -1) { perror("unmap: "); SetInvalid(); } if(mapdatablock() == -1) { SetInvalid(); } } #endif delete [] nsamples_int; nsamples_int = new USampleT [nchannels]; uint32 i; for (i= 0; i< nchannels; ++i) nsamples_int[i]= nsamples; return nsamples_int; } USampleT EBSFile::GetMaxSamples(void) { return (USampleT) nsamples; } USampleT const *EBSFile::GetAssumedNSamples(void) { void *buf; uint32 buflen; if (nassumed!= NULL) return (nassumed); buf = ebs_getattr(ebsstruct, EBS_ASSUMED_NSAMPLES, &buflen); if (buf== NULL) { nassumed = new USampleT [nchannels]; for (uint32 i= 0; i< nchannels; ++i) nassumed[i]= nsamples_int[i]; return nassumed; } nassumed = new USampleT [nchannels]; uint32 i; for (i= 0; i< nchannels; ++i) nassumed[i]= getst(&buf); return nassumed; } int EBSFile::SetAssumedNSamples(USampleT const *assumed) { int is_put_ok; void *buf, *hlp; uint32 buflen; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if (assumed== NULL) return (ebs_clearattr (ebsstruct, EBS_ASSUMED_NSAMPLES)); buflen= 8* nchannels; /* *8 (= Bytes) /4 (= Worte) */ buf = (void *) new char[buflen]; //reserviere nun Speicher fuer buf hlp=buf; for (uint32 i= 0; i< nchannels; ++i) putst(assumed[i], &buf); BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_ASSUMED_NSAMPLES, hlp, buflen); if (is_put_ok) { delete [] nassumed; nassumed = new USampleT [nchannels]; uint32 i; for (i= 0; i< nchannels; ++i) nassumed[i]= assumed[i]; } delete [] hlp; return is_put_ok; } EBSFile::EBSTime EBSFile::GetRecordingEnd (void) { static EBSTime result; if (rectimebuf==NULL) (void) GetRecordingTime(); if(samplerate==NULL) { (void) GetSampleRate (); if (samplerate==NULL) return (*rectimebuf); } /* at the moment all channels have the same length and samplerate */ result= *rectimebuf+ (double)(nsamples/samplerate[0]); return (result); } char const *EBSFile::GetRecordingLength (void) { /* at the moment all channels have the same length and samplerate */ return (OffsetAtSampleNo (0, nsamples-1, 1)); } EBSFile::EBSTime EBSFile::GetAssumedRecordingEnd (void) { static EBSTime result; if (nassumed==NULL) (void) GetAssumedNSamples(); if (rectimebuf==NULL) (void) GetRecordingTime(); if(samplerate==NULL || nassumed==NULL) { (void) GetSampleRate (); if (samplerate==NULL) return (*rectimebuf); } /* at the moment all channels have the same length and samplerate */ result= *rectimebuf+ (double)(nassumed[0]/samplerate[0]); return (result); } char const *EBSFile::GetAssumedRecordingLength (void) { if (nassumed==NULL) (void) GetAssumedNSamples(); /* at the moment all channels have the same length and samplerate */ return (OffsetAtSampleNo (0, nassumed[0]-1, 1)); } EBSFile::EBSTime EBSFile::EBSTimeAtSampleNo (uint32 channel, USampleT sampleno) { static EBSTime result; if (rectimebuf==NULL) (void) GetRecordingTime(); if(samplerate==NULL) { (void) GetSampleRate (); if (samplerate==NULL) return (*rectimebuf); } result= *rectimebuf+ (double)(sampleno/samplerate[channel]); return (result); } char const * EBSFile::OffsetAtSampleNo (uint32 channel, USampleT sampleno, int fractions, char *buf, unsigned long buflen) { static char text [50]; USampleT hour, min, sec, sec_100; if (buf!=NULL && buflen==0) return (NULL); if (samplerate==NULL) (void) GetSampleRate (); if (samplerate==NULL) { sprintf (text, "%lu", (unsigned long) sampleno); if (buf==NULL) return (text); strncpy (buf, text, buflen); buf[buflen-1]= '\0'; return (buf); } sec_100= (USampleT) (((100.0* (double) sampleno)/ samplerate[channel])+ 0.5); hour= sec_100/ (60* 60* 100); sec_100-= hour* 60* 60* 100; min= sec_100/ (60* 100); sec_100-= min* 60* 100; sec= sec_100/ 100; sec_100-= sec* 100; *text= '\0'; if (hour== 0) sprintf (text+strlen(text), "%02ld:%02ld", min, sec); else sprintf (text+strlen(text), "%02ld:%02ld:%02ld", hour, min, sec); if (fractions) sprintf (text+strlen(text), ",%02ld", sec_100); if (buf==NULL) return (text); strncpy (buf, text, buflen); buf[buflen-1]= '\0'; return (buf); } char const *EBSFile::TimeAtSampleNo (uint32 channel, USampleT sampleno, EBSFile::TimeInfo info, int fractions, char *buf, unsigned long buflen) { char *string; static char text [100]; if (buf!=NULL && buflen==0) return (NULL); if (buf==NULL) { buf= text; buflen= sizeof text; } if (info==no_date_or_time) { *buf= '\0'; return (buf); } if (rectimebuf==NULL) (void) GetRecordingTime(); if (samplerate==NULL) (void) GetSampleRate (); if (samplerate!=NULL) { if (info==only_year || info==only_date) { if (rectimebuf->info==no_date_or_time || rectimebuf->info==only_time) { *buf= '\0'; return (buf); } if (info==only_year || rectimebuf->info==only_year) return (EBSTimeToString2(*rectimebuf+sampleno/samplerate[channel], only_year,fractions,buf,buflen)); return (EBSTimeToString2(*rectimebuf+sampleno/samplerate[channel], only_date,fractions,buf,buflen)); } if (info==only_time) { if (rectimebuf->info==only_time || rectimebuf->info==date_and_time) return (EBSTimeToString2(*rectimebuf+sampleno/samplerate[channel], only_time,fractions,buf,buflen)); return (OffsetAtSampleNo(channel, sampleno, fractions, buf, buflen)); } switch (rectimebuf->info) { case no_date_or_time: return (OffsetAtSampleNo(channel, sampleno, fractions, buf, buflen)); case date_and_time: return (EBSTimeToString2(*rectimebuf+sampleno/samplerate[channel], date_and_time,fractions,buf,buflen)); case only_year: case only_date: string= (char *)EBSTimeToString(*rectimebuf+sampleno/samplerate[channel], buf, buflen); return (OffsetAtSampleNo(channel, sampleno, fractions, string+strlen(string),buflen-strlen(string)-1)); case only_time: default: fprintf (stderr, "Not yet implemented\n"); *buf= '\0'; return (buf); } } else { if (info==only_year || info==only_date) { if (rectimebuf->info==no_date_or_time || rectimebuf->info==only_time) { *buf= '\0'; return (buf); } if (info==only_year || rectimebuf->info==only_year) return (EBSTimeToString2(rectimebuf,only_year,fractions,buf,buflen)); return (EBSTimeToString2(rectimebuf,only_date,fractions,buf,buflen)); } if (info==only_time) { sprintf (text, "%ld", sampleno); if (buf!= text) { strncpy (buf, text, buflen); buf[buflen-1]='\0'; } return (buf); } string= (char *) EBSTimeToString(rectimebuf,buf,buflen); if (*string== '\0') sprintf (string, "#%lu", (unsigned long) sampleno); else sprintf (string+strlen(string), " #%lu", (unsigned long) sampleno); if (buf!= text) { strncpy (buf, text, buflen); buf[buflen-1]='\0'; } return (buf); } } void EBSFile::SetDescriptionAtSampleNo (EBSFile::DescriptionTime type, int fractions, EBSFile::TimeInfo info) { description_type= type; description_info= info; description_fractions= fractions; } char const *EBSFile::DescriptionAtSampleNo (uint32 channel, USampleT sampleno) { if (description_type== realtime) return (TimeAtSampleNo (channel, sampleno, description_info, description_fractions)); else return (OffsetAtSampleNo (channel, sampleno, description_fractions)); } double EBSFile::PhysicalValue(uint32 channel, USampleT sample) { if (yscale== NULL) { Unit const *unit; int i; unit= GetUnits (); yscale= new double [nchannels]; if (unit==NULL) for (i= 0; i< nchannels; ++i) yscale[i]= 1.0; else for (i= 0; i< nchannels; ++i) { if (unit[i].specified) yscale[i]= unit[i].quotient; else yscale[i]= 1.0; } } return ((double) Value (channel, sample)* yscale [channel]); } #ifndef MSDOS int EBSFile::mapdatablock(void) { struct stat buf; stat (filename, &buf); filesize = buf.st_size; // neue filesize bestimmen // mappe Datei in Speicher (mit so wenig Header wie moeglich) mdata_offset = ebs_data_offset(ebsstruct); // Datenblock im Speicher USampleT mhelp = mdata_offset/4096; // 4096 ist die Seitengroesse mdata_offset -= 4096*mhelp; // Header nicht mappen mdata_act = mdata_offset; datamap = mmap(NULL, filesize, PROT_READ, MAP_SHARED, fd, 4096*mhelp); if(datamap == (caddr_t)(-1)) { perror("mmap: "); return -1; ;//throw NoMem(); } getdata = (short *)(datamap + mdata_offset); return 0; } #endif USampleT EBSFile::determinesamples(void) { // testet auf unspezifzierte Sampleanzahl if(fixed.sampleshigh == 0xffffffff && fixed.sampleslow == 0xffffffff) { if(fixed.encoding_id == EBS_CIB_16 || fixed.encoding_id == EBS_CIL_16 || fixed.encoding_id == EBS_CI_16D) { #ifdef DEBUG fprintf(stderr, "determinesamples: unspezified number of samples not\n"); fprintf(stderr, " allowd with channel based order.\n"); SetInvalid(); #endif return 0; ;//throw WrongNSamples(); } } else if(fixed.sampleshigh != 0) { // Datei zu gross? #ifdef DEBUG fprintf(stderr, "determinesamples: 64 bit samples not supported\n"); #endif SetInvalid(); return 0; ;//throw FileTooBig(); } else if((fixed.sampleshigh == 0) && (fixed.encoding_id == EBS_TI_16D || fixed.encoding_id == EBS_CI_16D)) return fixed.sampleslow; // Samples fuer komprimierte Datei gegeben // Dateigroesse bestimmen struct stat buf; stat (filename, &buf); USampleT filesize = buf.st_size; // beginn des Datenblockes ermitteln USampleT databegin = ebs_data_offset(ebsstruct); // testet, ob Dateilaenge korrekt ist USampleT datalength = 0; if(fixed.datalengthhigh==0xffffffff && fixed.datalengthlow==0xffffffff) { datalength = filesize - databegin; // auf naechste durch 4 teilbare Zahl aufrunden if(datalength & 3) { datalength |= 3; datalength++; } } else if (fixed.datalengthhigh!= 0 || fixed.datalengthlow> 0x20000000) { #ifdef DEBUG fprintf(stderr, "determinesamples: file to big.\n"); #endif SetInvalid(); return 0; ;//throw FileTooBig(); } else datalength = fixed.datalengthlow << 2; if(fixed.sampleslow == 0xffffffff) // unspezifizierte Samples return ((datalength/2)/fixed.channels); else { // spezifizierte Anzahl der Samples USampleT datapart; datapart = fixed.sampleslow * fixed.channels * 2; // auf naechste durch 4 teilbare Zahl aufrunden if(datapart & 3) {datapart |= 3; datapart++;} if (datalength != datapart) { #ifdef DEBUG fprintf(stderr, "determinesamples: data length value in fixed header"); fprintf(stderr, " is wrong.\n"); #endif SetInvalid(); return 0; ;//throw WrongNSamples(); } else return fixed.sampleslow; } } /* Hier wird abhaengig von Maschine und EBS_TYPE auf verschiedene Arten die Werte des Datenblocks aus dem Speicher gelesen. Abhaengigkeit: Bigendian oder Littleendian */ #ifndef MSDOS short EBSFile::ValueT(uint32 channel, USampleT sample) { // channel beginnt bei 0 oder 1? Markus fragen. USampleT position; position = nchannels * sample + channel; return *(getdata+position); } short EBSFile::ValueC(uint32 channel, USampleT sample) { USampleT position; position = nsamples*channel + sample; return *(getdata+position); } short EBSFile::ValueTR(uint32 channel, USampleT sample) { // transormiere big- nach littleendian bzw. umgekehrt USampleT position; unsigned char *getbyte, *wertptr; short wert; position = nchannels * sample + channel; getbyte = (unsigned char *)(getdata + position); wertptr = (unsigned char *)(&wert); *(wertptr+1) = *getbyte; // vertausche MSB getbyte++; // mit *wertptr = *getbyte; // LSB return wert; } short EBSFile::ValueCR(uint32 channel, USampleT sample) { // transormiere big- nach littleendian bzw. umgekehrt USampleT position; unsigned char *getbyte, *wertptr; short wert; position = nsamples * channel + sample; getbyte = (unsigned char *)(getdata + position); wertptr = (unsigned char *)(&wert); *(wertptr+1) = *getbyte; // vertausche MSB getbyte++; // mit *wertptr = *getbyte; // LSB return wert; } #endif short EBSFile::ValueMSDOS(uint32 channel, USampleT sample) { // ist nicht sonderlich schnell, aber sollte funktionieren USampleT position = ddata_offset; short wert; if((ebs_type == EBS_CIB_16) || (ebs_type == EBS_CIL_16)) position += 2*(nsamples * channel + sample); else position += 2*(nchannels * sample + channel); if(ftell(fstream) != position) fseek(fstream, position, SEEK_SET); // wenn MSDOS => LITTLEENDIAN if((ebs_type == EBS_CIL_16) || (ebs_type == EBS_TIL_16)) wert = fgeti16l(fstream); else wert = fgeti16(fstream); return wert; } short EBSFile::ValueNotSupp(uint32 channel, USampleT sample) { #ifdef DEBUG fprintf(stderr, "Value(): Datablocks which are compressed or of unknown type\n"); fprintf(stderr, " can only be touched by NextValue() and RewindValue().\n"); #endif return -1; } /* short EBSFile::NextValue(uint32 chn) { if(!compresseddata) return Value(chn, channelinfo[chn].samnow++); if(channelinfo[chn].valid == FALSE) { InitChnInfo(chn); channelinfo[chn].samnow = 0; return channelinfo[chn].samval; } if(channelinfo[chn].samnow == -1) { channelinfo[chn].samnow = 0; return channelinfo[chn].samval; } #ifdef MSDOS const int msdos = 1; #else const int msdos = 0; #endif if((mode == 'w') || (mode == 'm') || msdos) { short samval, diff; if(ebs_type == EBS_CI_16D) { fseek(fstream, channelinfo[chn].lposnow, SEEK_SET); diff = (signed char)fgetc(fstream); if(diff == -128) channelinfo[chn].lposnow += 3; else channelinfo[chn].lposnow += 1; fseek(fstream, channelinfo[chn].lposnow, SEEK_SET); diff = (signed char)fgetc(fstream); if(diff == -128) { // Wert absolut gespeichert samval = ((signed char)fgetc(fstream)) << 8; samval |= ((unsigned char)fgetc(fstream)); channelinfo[chn].samnow++; channelinfo[chn].samval = samval; return samval; } else { samval = channelinfo[chn].samval + diff; channelinfo[chn].samnow++; channelinfo[chn].samval = samval; return samval; } } else { // time based uint32 i; for(i = 0; i < nchannels; i++) {//ueberlese die Werte der anderen Kanaele fseek(fstream, channelinfo[chn].lposnow, SEEK_SET); diff = (signed char)fgetc(fstream); if(diff == -128) channelinfo[chn].lposnow += 3; else channelinfo[chn].lposnow += 1; } fseek(fstream, channelinfo[chn].lposnow, SEEK_SET); diff = (signed char)fgetc(fstream); if(diff == -128) { // Wert absolut gespeichert samval = ((signed char)fgetc(fstream)) << 8; samval |= ((unsigned char)fgetc(fstream)); channelinfo[chn].samnow++; channelinfo[chn].samval = samval; return samval; } else { samval = channelinfo[chn].samval + diff; channelinfo[chn].samnow++; channelinfo[chn].samval = samval; return samval; } } } else { short samval, diff; if(ebs_type == EBS_CI_16D) { diff = *(signed char *)(channelinfo[chn].posnow); if(diff == -128) channelinfo[chn].posnow += 3; else channelinfo[chn].posnow += 1; diff = *(signed char *)(channelinfo[chn].posnow); if(diff == -128) { // Wert absolut gespeichert samval = ((short)*(signed char*)(channelinfo[chn].posnow+1)) << 8; samval |= (short)*(unsigned char*)(channelinfo[chn].posnow+2); channelinfo[chn].samnow++; channelinfo[chn].samval = samval; return samval; } else { samval = channelinfo[chn].samval + diff; channelinfo[chn].samnow++; channelinfo[chn].samval = samval; return samval; } } else { // time based uint32 i; for(i = 0; i < nchannels; i++) {//ueberlese die Werte der anderen Kanaele diff = *(signed char *)(channelinfo[chn].posnow); if(diff == -128) channelinfo[chn].posnow += 3; else channelinfo[chn].posnow += 1; } diff = *(signed char *)(channelinfo[chn].posnow); if(diff == -128) { // Wert absolut gespeichert samval = ((short)*(signed char*)(channelinfo[chn].posnow+1)) << 8; samval |= (short)*(unsigned char*)(channelinfo[chn].posnow+2); channelinfo[chn].samnow++; channelinfo[chn].samval = samval; return samval; } else { samval = channelinfo[chn].samval + diff; channelinfo[chn].samnow++; channelinfo[chn].samval = samval; return samval; } } } } void EBSFile::RewindValue(uint32 chn) { if(compresseddata == FALSE) { channelinfo[chn].samnow = 0; return; } if(channelinfo[chn].valid == TRUE) { channelinfo[chn].posnow = channelinfo[chn].startpos; channelinfo[chn].lposnow = channelinfo[chn].lstartpos; short samval; // lese den ersten Wert ein #ifdef MSDOS const int msdos = 1; #else const int msdos = 0; #endif if((mode == 'w') || (mode == 'm') || msdos) { fseek(fstream, channelinfo[chn].lposnow+1, SEEK_SET); samval = ((signed char)fgetc(fstream)) << 8; samval |= ((unsigned char)fgetc(fstream)); } else { samval = ((short)*(signed char*)(channelinfo[chn].posnow+1)) << 8; samval |= (short)*(unsigned char*)(channelinfo[chn].posnow+2); } channelinfo[chn].samval = samval; channelinfo[chn].samnow = (USampleT)(-1); return; } InitChnInfo(chn); return; } */ void EBSFile::InitChnInfo(uint32 chn) { uint32 i, k; short diff, val; #ifdef MSDOS const int msdos = 1; #else const int msdos = 0; #endif if((mode == 'w') || (mode == 'm') || msdos) { USampleT diskpos = ddata_offset; if(ebs_type == EBS_TI_16D) { // gleich fuer alle Kanaele initialisieren fseek(fstream, ddata_offset, SEEK_SET); for(i = 0; i < nchannels; i++) { channelinfo[i].lstartpos = diskpos + i*3; channelinfo[i].lposnow = diskpos + i*3; channelinfo[i].samnow = (USampleT)(-1); fgetc(fstream); // ueberlese -128 val = ((signed char)fgetc(fstream)) << 8; val |= ((unsigned char)fgetc(fstream)); channelinfo[i].samval = val; channelinfo[i].valid = TRUE; } } else { // init. alle noch nicht init. bis chn USampleT helppos = diskpos; fseek(fstream, ddata_offset, SEEK_SET); if(channelinfo[0].valid == FALSE) { channelinfo[0].lstartpos = diskpos; channelinfo[0].lposnow = diskpos; channelinfo[0].samnow = (USampleT)(-1); fgetc(fstream); val = ((signed char)fgetc(fstream)) << 8; val |= ((unsigned char)fgetc(fstream)); channelinfo[0].samval = val; channelinfo[0].valid = TRUE; } for(i = 1; i <= chn; i++) { if(channelinfo[i].valid == TRUE) { helppos = channelinfo[i].lstartpos; continue; } else { helppos = channelinfo[i-1].lposnow; USampleT from = channelinfo[i-1].samnow; if(from == (USampleT)(-1)) from = 0; for(k = from; k < nsamples; k++) { fseek(fstream, helppos, SEEK_SET); diff = (signed char)fgetc(fstream); if(diff == -128) helppos += 3; else helppos += 1; } channelinfo[i].lstartpos = helppos; channelinfo[i].lposnow = helppos; channelinfo[i].samnow = (USampleT)(-1); fgetc(fstream); val = ((signed char)fgetc(fstream)) << 8; val |= ((unsigned char)fgetc(fstream)); channelinfo[i].samval = val; channelinfo[i].valid = TRUE; } } } } else { char *mempos = (char *)(getdata); if(ebs_type == EBS_TI_16D) { // gleich fuer alle Kanaele initialisieren for(i = 0; i < nchannels; i++) { channelinfo[i].startpos = mempos + i*3; channelinfo[i].posnow = mempos + i*3; channelinfo[i].samnow = (USampleT)(-1); val = *((signed char*)(channelinfo[i].posnow)+1)<< 8; val |= *((unsigned char*)(channelinfo[i].posnow)+2); channelinfo[i].samval = val; channelinfo[i].valid = TRUE; } } else { // init. alle noch nicht init. bis chn char *helppos = (char *) mempos; if(channelinfo[0].valid == FALSE) { channelinfo[0].startpos = mempos; channelinfo[0].posnow = mempos; channelinfo[0].samnow = (USampleT)(-1); val = *((signed char*)(channelinfo[0].posnow)+1) << 8; val |= *((unsigned char*)(channelinfo[0].posnow)+2); channelinfo[0].samval = val; channelinfo[0].valid = TRUE; } for(i = 1; i <= chn; i++) { if(channelinfo[i].valid == TRUE) { helppos = (char *) channelinfo[i].startpos; continue; } else { helppos = (char *) channelinfo[i-1].posnow; USampleT from = channelinfo[i-1].samnow; if(from == (USampleT)(-1)) from = 0; for(k = from; k < nsamples; k++) { diff = *(signed char *)(helppos); if(diff == -128) helppos += 3; else helppos += 1; } channelinfo[i].startpos = helppos; channelinfo[i].posnow = helppos; channelinfo[i].samnow = (USampleT)(-1); val = *((signed char*)(channelinfo[i].posnow)+1) << 8; val |= *((unsigned char*)(channelinfo[i].posnow)+2); channelinfo[i].samval = val; channelinfo[i].valid = TRUE; } } } } } void EBSFile::GetEventInfo(void) { if(eventlist != NULL) return; USampleT discpos, disclen; discpos = ebs_getdiscattr(ebsstruct, EBS_EVENTS, &disclen); if((discpos == 0) || (disclen == 0)) return; USampleT usrpos = ftell(fstream); USampleT discposend = discpos + 4*disclen; fseek(fstream, discpos, SEEK_SET); // wieviele EventGroups gibt es? uint32 g, e, i, m, max=0; g = 0; while(ftell(fstream) < discposend) { m=fgets4(NULL, 0, fstream); // ueberlese String if (m> max) max= m; m=fgets4(NULL, 0, fstream); // ueberlese multi line String if (m> max) max= m; e = fgeti32(fstream); for(i = 0; i < e; i++) { fgeti32(fstream); // channel fgeti32(fstream); // 64 fgeti32(fstream); // bit fgeti32(fstream); // 64 fgeti32(fstream); // bit fgets4(NULL, 0, fstream); // ueberlese String } g++; } neventlists= g; eventlist_int = new eventlist_info [g]; eventlist= new EventList [g]; fseek(fstream, discpos, SEEK_SET); uint32 k; uint32 buflen= max+1; char *buf = new char[buflen] ; // lese die Anzahl der Events pro Gruppe for(k = 0; k < g; k++) { eventlist_int[k].discpos = ftell(fstream); fgets4(buf, buflen, fstream); // ueberlese String eventlist[k].name= mystrdup (buf); fgets4(buf, buflen, fstream); // ueberlese multi line String eventlist[k].description= mystrdup (buf); e = fgeti32(fstream); eventlist_int[k].rewindpos = ftell(fstream); eventlist_int[k].actpos = eventlist_int[k].rewindpos; eventlist[k].nevents = e; for(i = 0; i < e; i++) { fgeti32(fstream); // channel fgeti32(fstream); // 64 fgeti32(fstream); // bit fgeti32(fstream); // 64 fgeti32(fstream); // bit fgets4(buf, buflen, fstream); // ueberlese String } } delete [] buf; fseek(fstream, usrpos, SEEK_SET); return; } uint32 EBSFile::GetNEventLists (void) { GetEventInfo(); return (neventlists); } EBSFile::EventList const *EBSFile::GetEventList (uint32 list) { GetEventInfo(); if(eventlist == NULL) return (NULL); return eventlist+list; } int EBSFile::RewindEventList(uint32 list, uint32 eventnum) { GetEventInfo(); if(eventlist == NULL) return -1; // es sollte vorher GetEventInfo() aufgerufen werden if(list > neventlists) return -1; if(eventnum >= eventlist [list].nevents) return -1; if(eventnum == 0) { eventlist_int[list].actpos = eventlist_int[list].rewindpos; eventlist_int[list].readpos = 0; return 0; } USampleT usrpos = ftell(fstream); if(fseek(fstream, eventlist_int[list].rewindpos, SEEK_SET) != 0) return -1; uint32 i; for(i = 0; i < eventnum; i++) { fgeti32(fstream); // channel fgeti32(fstream); // 64 fgeti32(fstream); // bit fgeti32(fstream); // 64 fgeti32(fstream); // bit fgets4(NULL, 0, fstream); // ueberlese String } eventlist_int[list].actpos = ftell(fstream); eventlist_int[list].readpos = eventnum; fseek(fstream, usrpos, SEEK_SET); return 0; } EBSFile::Event const *EBSFile::GetNextEvent(uint32 list) { GetEventInfo(); if(eventlist == NULL) return NULL; // es sollte vorher GetEventInfo() aufgerufen werden if(list > neventlists) return NULL; if(++eventlist_int[list].readpos >= eventlist_int[list].nevents) return NULL; USampleT usrpos = ftell(fstream); if(fseek(fstream, eventlist_int[list].actpos, SEEK_SET) != 0) return NULL; event.channel = fgeti32(fstream); event.position = fgetst(fstream); event.length = fgetst(fstream); delete [] event.description; char buf [500]; fgets4(buf, 500, fstream); event.description= mystrdup (buf); eventlist_int[list].actpos = ftell(fstream); fseek(fstream, usrpos, SEEK_SET); return &event; } void EBSFile::SetInvalid() { valid = 0; } int EBSFile::Valid(void) { return valid; } int EBSFile::InitDataPart(uint32 ebstype, uint32 nchn, USampleT nsamp) { // Medium immer disk if((mode != 'm') && (mode != 'w')) { #ifdef DEBUG fprintf(stderr, "File not opened for writing or modifing.\n"); #endif return -1; // Datei falsch geoeffnet. } if((mode == 'm') && (ebstype != ebs_type)) { #ifdef DEBUG fprintf(stderr, "Encoding_ID does not match.\n"); #endif return -1; // Daten in Datei liegen in anderen Format vor als sie nun // neu abgelegt werden sollen. } if(((ebstype == EBS_CI_16D) || (ebstype == EBS_TI_16D)) && (mode == 'm')) { #ifdef DEBUG fprintf(stderr, "Compressed data can't be modified.\n"); #endif return -1; // Komprimierte Daten koennen nicht veraendert werden. } if((ebstype == EBS_CIB_16) || (ebstype == EBS_TIB_16) || (ebstype == EBS_CIL_16) || (ebstype == EBS_TIL_16) || (ebstype == EBS_TI_16D) || (ebstype == EBS_CI_16D)) if((ebstype == EBS_TI_16D) || (ebstype == EBS_CI_16D)) compresseddata = TRUE; else compresseddata = FALSE; else { #ifdef DEBUG fprintf(stderr, "Unknown encoding format.\n"); #endif return -1; // nicht bekanntes Format } if(((ebstype == EBS_CIB_16) || (ebstype == EBS_CIL_16) || (ebstype == EBS_CI_16D)) && (nsamp == ~0)) { #ifdef DEBUG fprintf(stderr, "Number of samples must be specified by channel based order.\n"); #endif return -1; // Bei Channelbased Order muss die Anzahl der Samples // angegeben sein. } writechannels = nchn; writesamples = nsamp; counter = 0; if(nsamp == ~0) // selber mitzaehlen. count = TRUE; else count = FALSE; ebs_type = ebstype; fixed.encoding_id = ebstype; fixed.channels = nchn; nchannels= nchn; ebs_putfixedheader(ebsstruct, &fixed); ebs_flush(ebsstruct); // schreibe Variablen Header raus ddata_offset = ebs_data_offset(ebsstruct); ebs_getfixedheader(ebsstruct, &fixed); // hole neuen fixed header return 0; } int EBSFile::EndOfWritingData(void) { if(mode == 'r') { #ifdef DEBUG fprintf(stderr, "Error: File was opened for reading.\n"); #endif return -1; } if(mode == 'm') { // Nichts zu tun, da sich die Laenge des Datenblocks nicht return 0; // aendern kann. } #ifdef DEBUG fprintf(stderr,"EndOfWritingData():\n"); fprintf(stderr,"Attention: Be sure that you have written the last sample\n"); fprintf(stderr," of the last channel at last. Otherwise I will\n"); fprintf(stderr," cut the data part at the current position at\n"); fprintf(stderr," this moment.\n"); #endif if(count) nsamples = counter / writechannels; else nsamples = writesamples; nchannels = writechannels; ebs_setendof_data_block(ebsstruct); ebs_getfixedheader(ebsstruct, &fixed); // hole neuen fixed header fixed.sampleshigh = 0; fixed.sampleslow = nsamples; ebsstruct->fixed_flag = 2; ebs_putfixedheader(ebsstruct, &fixed); int retvalue = ebs_flush(ebsstruct); ebs_getfixedheader(ebsstruct, &fixed); // hole neuen fixed header return retvalue; } int EBSFile::SetDatum(uint32 chn, USampleT sam, short wert) { if(mode == 'r') { #ifdef DEBUG fprintf(stderr, "Error: File was opened for reading.\n"); #endif return -1; } if(compresseddata) { #ifdef DEBUG fprintf(stderr, "SetDatum(): can't be used for compressed data.\n"); #endif return -1; } if(count && ((ebs_type == EBS_CIB_16) || (ebs_type == EBS_CIL_16))) return -1; // Anzahl der Samples pro Kanal sind nicht bekannt if((chn > writechannels) || (sam > writesamples)) { #ifdef DEBUG fprintf(stderr, "SetDatum(): invalid arguments, out of range.\n"); #endif return -1; } USampleT position = ddata_offset; if((ebs_type == EBS_CIB_16) || (ebs_type == EBS_CIL_16)) position += 2*(writesamples * chn + sam); else position += 2*(writechannels * sam + chn); if(ftell(fstream) != position) if(fseek(fstream, position, SEEK_SET) != 0) { #ifdef DEBUG perror("SetDatum()"); #endif return -1; } if(count) counter++; if((ebs_type == EBS_CIL_16) || (ebs_type == EBS_TIL_16)) fputi16l(wert, fstream); else fputi16(wert, fstream); return 0; } void EBSFile::InitWriteChn(void) { writechnpos = new USampleT [writechannels]; int i; for(i = 0; i < writechannels; i++) writechnpos[i] = 0; } int EBSFile::SetNextDatumOnChn(uint32 chn, short wert) { if(mode == 'r') { #ifdef DEBUG fprintf(stderr, "Error: File was opened for reading.\n"); #endif return -1; } if(compresseddata) { #ifdef DEBUG fprintf(stderr, "SetNextDatumOnChn(): can't be used for compressed data."); #endif return -1; } if(count && ((ebs_type == EBS_CIB_16) || (ebs_type == EBS_CIL_16))) return -1; // Anzahl der Samples pro Kanal sind nicht bekannt if(writechnpos == NULL) InitWriteChn(); USampleT position = ddata_offset; if((ebs_type == EBS_CIB_16) || (ebs_type == EBS_CIL_16)) position += 2*(writesamples * chn + writechnpos[chn]); else position += 2*(writechannels * writechnpos[chn] + chn); if(ftell(fstream) != position) { if(fseek(fstream, position, SEEK_SET) != 0) { #ifdef DEBUG perror("SetNextDatumOnChn()"); #endif return -1; } } writechnpos[chn]++; if(count) // ergibt nachher die Anzahl der Samples bei Time Based counter++; // Samples = counter / channels if((ebs_type == EBS_CIL_16) || (ebs_type == EBS_TIL_16)) fputi16l(wert, fstream); else fputi16(wert, fstream); return 0; } int EBSFile::SetNextDatum(short wert) { if(mode == 'r') { #ifdef DEBUG fprintf(stderr, "Error: File was opened for reading.\n"); #endif return -1; } static USampleT position = ddata_offset; static USampleT long intcount = 0; static short lastvalue = 0; if(ftell(fstream) != position) if(fseek(fstream, position, SEEK_SET) != 0) { #ifdef DEBUG perror("SetNextDatum()"); #endif return -1; } if(count) // ergibt nachher die Anzahl der Samples bei Time Based counter++; // Samples = counter / channels int writeout = 0; // wird hochgesetzt, falls 3 Bytes geschrieben werden if(compresseddata) { short diff; if(ebs_type == EBS_TI_16D) { if(lastvaluechn == NULL) { // initialisiere lastvaluechn = new short[writechannels]; int i; for(i = 0; i < writechannels; i++) lastvaluechn[i] = 0; } if(intcount < writechannels) { writeout++; } uint32 actchn = intcount % writechannels; diff = wert - lastvaluechn[actchn]; lastvaluechn[actchn] = wert; } else { if((intcount % writesamples) == 0) { lastvalue = 0; writeout++; } diff = wert - lastvalue; lastvalue = wert; } if((diff > 127) || (diff < -127)) writeout++; if(writeout > 0) { putc((signed char)(-128), fstream); fputi16(wert, fstream); position = position + 3; intcount++; return 0; } else { putc((unsigned char)(diff), fstream); position++; intcount++; return 0; } } else { // nicht komprimiert if((ebs_type == EBS_CIL_16) || (ebs_type == EBS_TIL_16)) fputi16l(wert, fstream); else fputi16(wert, fstream); position = position + 2; return 0; } } int EBSFile::SetNChannels(uint32 n) { if(mode == 'w') nchannels = n; else return -1; return 0; } int EBSFile::AppEventlist(char* name, char* description, uint32 nevents, Event* events) { uint32 len=0; void *buf; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if(nevents < 1) return -1; if (events== NULL || name== NULL || description== NULL) return (0); len += s4len(name); //bestimme die groesse des buffers len += s4len(description); len ++; //Laenge von 32bit int "number of events" int i=0; for(i = 0; i < nevents; i++) { len += 5; // 1x32bit + 2x64bit (channel, start pos, interval length) len += s4len(events[i].description); } buf = ebs_appattr(ebsstruct, EBS_EVENTS, len); //Append Events puts4(name, &buf); //schreibe buffer puts4(description, &buf); puti32(nevents, &buf); for(i = 0; i < nevents; i++) { puti32(events[i].channel, &buf); putst(events[i].position, &buf); putst(events[i].length, &buf); puts4(events[i].description, &buf); } if(eventlist != NULL) { //falls eventinfo schon gepuffert for (uint32 i= 0; i< neventlists; ++i) { delete [] eventlist[i].name; delete [] eventlist[i].description; } delete [] eventlist; delete [] eventlist_int; eventlist = NULL; neventlists = 0; eventlist_int= NULL; } return 0; } int EBSFile::SetEventlist(char* name, char* description, uint32 nevents, Event* events) { int is_put_ok; uint32 len=0; void *buf, *hlp; if((mode != 'm')&&(mode !='w')) return -1; // Kein Schreibrecht if(nevents < 1) return -1; if (events== NULL || name== NULL || description== NULL) return (ebs_clearattr (ebsstruct, EBS_EVENTS)); len += s4len(name); //bestimme die Groesse des buffers len += s4len(description); len ++; //Laenge von 32bit int "number of events" int i=0; for(i = 0; i < nevents; i++) { len += 5; // 1x32bit + 2x64bit (channel, start pos, interval length) len += s4len(events[i].description); } buf = (char *) new char[len*4]; //reserviere nun Speicher fuer buf hlp = buf; puts4(name, &buf); //erzeuge buffer puts4(description, &buf); puti32(nevents, &buf); for(i = 0; i < nevents; i++) { puti32(events[i].channel, &buf); putst(events[i].position, &buf); putst(events[i].length, &buf); puts4(events[i].description, &buf); } BeforePutAttr (); is_put_ok = ebs_putattr(ebsstruct, EBS_EVENTS, hlp, len); delete [] hlp; if(eventlist != NULL) { //falls eventinfo schon gepuffert for (uint32 i= 0; i< neventlists; ++i) { delete [] eventlist[i].name; delete [] eventlist[i].description; } delete [] eventlist; delete [] eventlist_int; eventlist = NULL; neventlists = 0; eventlist_int= NULL; } return is_put_ok; } void EBSFile::DEventList::init(void) { evl = new EventList; // setzen der Default-Werte evl->name = NULL; evl->description = NULL; evl->nevents = 0; valid = 1; } EBSFile::DEventList::DEventList(void) { init(); // Initialisierung von evl } EBSFile::DEventList::DEventList(char const *name, char const *description) { init(); // Initialisierung von evl strcpy(evl->name, (char *)name); strcpy(evl->description, (char *)description); } EBSFile::DEventList::~DEventList(void) { delete evl->name; delete evl->description; delete evl; } // direktes Schreiben in EBSFile-Objekt // Grossteil aus EBSFile::SetEventList bzw. EBSFile::AddEventList uebernommen int EBSFile::DEventList::Put(EBSFile *ebsf) { int is_put_ok; uint32 len=0; void *buf, *hlp; Event const *ev; USampleT *assumed; uint32 i; // Falls Datenteil noch nicht initialisiert wurde, dann initialisieren if(ebsf->ebsstruct->fixedheader.encoding_id == -1) { if(ebsf->InitDataPart(EBS_CIB_16,0,0) || ebsf->SetAssumedNSamples(0)) return -1; } if((ebsf->mode != 'm')&&(ebsf->mode !='w')) return -1; // Kein Schreibrecht if (evl->name== NULL || evl->description== NULL) // sind notwendig return -3; len += s4len(evl->name); //bestimme die groesse des buffers len += s4len(evl->description); len ++; //Laenge von 32bit int "number of events" // Laenge des Puffers aus Summe der Laengen der einzelnen Events berechnen Rewind(); while((ev = GetEvent()) != NULL) { len += 5; // 1x32bit + 2x64bit (channel, start pos, interval length) len += s4len(ev->description); } assumed = new USampleT[ebsf->GetNChannels()]; for(i = 0; i < ebsf->GetNChannels(); i++) { assumed[i] = (ev->position > (ebsf->GetAssumedNSamples())[i] ? ev->position : (ebsf->GetAssumedNSamples())[i]); ebsf->SetAssumedNSamples(assumed); } if(ebsf->GetNEventLists() == 0) // falls schon Event-Listen existieren buf = (char *) new char[len*4]; //reserviere nun Speicher fuer buf else buf = ebs_appattr(ebsf->ebsstruct, EBS_EVENTS, len); hlp = buf; puts4(evl->name, &buf); //erzeuge buffer puts4(evl->description, &buf); puti32(evl->nevents, &buf); // Events in den Puffer schreiben Rewind(); while((ev=GetEvent()) != NULL) { puti32(ev->channel, &buf); putst(ev->position, &buf); putst(ev->length, &buf); puts4(ev->description, &buf); } is_put_ok = 0; if(ebsf->GetNEventLists() == 0) { // Falls noch keine Event-Listen existieren ebsf->BeforePutAttr (); is_put_ok = ebs_putattr(ebsf->ebsstruct, EBS_EVENTS, hlp, len); delete [] hlp; } if(ebsf->eventlist != NULL) { //falls eventinfo schon gepuffert for (uint32 i= 0; i< ebsf->neventlists; ++i) { delete [] ebsf->eventlist[i].name; delete [] ebsf->eventlist[i].description; } delete [] ebsf->eventlist; delete [] ebsf->eventlist_int; ebsf->eventlist = NULL; ebsf->neventlists = 0; ebsf->eventlist_int= NULL; } return is_put_ok; } // EBS-Datei erzeugen und Put(EBSFile*) aufrufen int EBSFile::DEventList::Put(char *filename) { EBSFile *ebsf; FILE *test; int retval = -1; test = fopen(filename,"r"); fclose(test); if(test == NULL) // existiert die Datei bereits? ebsf = new EBSFile(filename, 'w'); // nein, dann Schreib-Modus else ebsf = new EBSFile(filename, 'm'); // ja, dann Modifikations-Modus if(ebsf->Valid()) retval = Put(ebsf); else retval = -5; delete ebsf; // hinausschreiben return retval; } void EBSFile::DEventList::CopyEvent(Event *e1, const Event *e2) { e1->channel = e2->channel; e1->position = e2->position; e1->length = e2->length; delete [] e1->description; e1->description = mystrdup(e2->description); } virtual const EBSFile::Event *EBSFile::DEventList::GetEvent(void) { Event const *ev; ev = LookEvent(); SkipEvent(); return ev; } EBSFile::OutEventList::OutEventList(char const *name, char const *description) : EBSFile::DEventList() { evl->name = strdup((char *)name); evl->description = strdup((char *)description); // initialisieren der verketteten Liste first = last = current = NULL; } int EBSFile::OutEventList::Append(Event const *ev) { Event *nev = new Event; nev->description = NULL; EvListEl *elem = new EvListEl; if(last != NULL) if(ev->position < last->ev->position) return -1; CopyEvent(nev, ev); // ins Verkettete-Listen-Element eintragen und "reinhaengen" elem->ev = nev; elem->next = NULL; if(first == NULL) { first = elem; } else { last->next = elem; } last = elem; evl->nevents++; return 0; } int EBSFile::OutEventList::Append(DEventList *evlist) { Event const *ev; // die einzelnen Events der Liste anfuegen evlist->Rewind(); while((ev = evlist->GetEvent()) != NULL) { if(Append(ev)) return -1; } return 0; } virtual const EBSFile::Event *EBSFile::OutEventList::LookEvent(void) { static Event ev; static char description[501]; ev.description = description; if(current != NULL) { ev.channel = current->ev->channel; ev.position = current->ev->position; ev.length = current->ev->length; strncpy(description, current->ev->description, 500); return &ev; } else { return NULL; } } virtual int EBSFile::OutEventList::SkipEvent(void) { if(current!=NULL) { current = current->next; return 0; } else{ return -1; } } virtual void EBSFile::OutEventList::Rewind(void) { current = first; } void EBSFile::OutEventList::Clear(void) { Rewind(); current = first; while(current != NULL) { first = current; current = current->next; // Objekte und Strings freigeben delete [] first->ev->description; delete first->ev; delete first; } first = last = current; } EBSFile::OutEventList::~OutEventList(void) { Clear(); } EBSFile::EBSEventList::EBSEventList(EBSFile *mebsf, uint32 mlistnr, uint32 moffset, int32 mlength, uint32 mbegin, int32 mend) : EBSFile::DEventList() { const EBSFile::EventList *mevl; // Uebernehmen der Parameter ebsf = mebsf; listnr = mlistnr; offset = moffset; length = mlength; begin = mbegin; end = mend; // Plausibilitaetspruefungen if(listnr >= ebsf->GetNEventLists() || begin < 0 || end < -1 || length < -1 || listnr < -1) { valid = 0; return; } mevl = ebsf->GetEventList(listnr); if(mevl == NULL) { valid = 0; return; } evl->name = mystrdup(mevl->name); evl->description = mystrdup(mevl->description); // Berechnung der Anzahl der relevanten Events evl->nevents = (end == -1 ? mevl->nevents : (mevl->nevents > end+1 ? end+1 : mevl->nevents)); evl->nevents -= begin; if(ebsf->RewindEventList(listnr)) { valid = 0; return; } readpos = 0; if((rewindpos = GetFirstPos()) == 0) { valid = 0; return; } actpos = rewindpos; if(LookEvent() == NULL) { valid = 0; return; } } USampleT EBSFile::EBSEventList::GetFirstPos(void) { USampleT discpos, disclen; discpos = ebs_getdiscattr(ebsf->ebsstruct, EBS_EVENTS, &disclen); if((discpos == 0) || (disclen == 0)) return 0; USampleT usrpos = ftell(ebsf->fstream); fseek(ebsf->fstream, discpos, SEEK_SET); int32 k, e, i; for(k = 0; k <= listnr; k++) { fgets4(NULL, 0, ebsf->fstream); // ueberlese String fgets4(NULL, 0, ebsf->fstream); // ueberlese multi line String e = fgeti32(ebsf->fstream); // Anzahl der Events for(i = 0; i < (k==listnr ? (int32)begin - 1 : e); i++) { fgeti32(ebsf->fstream); // channel fgeti32(ebsf->fstream); // 64 fgeti32(ebsf->fstream); // bit fgeti32(ebsf->fstream); // 64 fgeti32(ebsf->fstream); // bit fgets4(NULL, 0, ebsf->fstream); // ueberlese String } } discpos = ftell(ebsf->fstream); fseek(ebsf->fstream, usrpos, SEEK_SET); return discpos; } virtual const EBSFile::Event *EBSFile::EBSEventList::LookEvent(void) { static Event ev; static char description[501]; ev.description = description; USampleT usrpos = ftell(ebsf->fstream); if(readpos >= evl->nevents) //Ende der Liste erreicht return NULL; if(fseek(ebsf->fstream, actpos, SEEK_SET) != 0) return NULL; ev.channel = fgeti32(ebsf->fstream); ev.position = fgetst(ebsf->fstream); ev.length = fgetst(ebsf->fstream); // Offset beruecksichtigen ev.position += offset; // ggf. Laenge setzen ev.length = (length == -1 ? ev.length : length); fgets4(description, 500, ebsf->fstream); nextpos = ftell(ebsf->fstream); fseek(ebsf->fstream, usrpos, SEEK_SET); return &ev; } virtual int EBSFile::EBSEventList::SkipEvent(void) { if(++readpos >= evl->nevents) { //Ende der Liste erreicht actpos = nextpos; return -1; } if(nextpos != 0) { //naechste Position schon bekannt? actpos = nextpos; nextpos = 0; } else { LookEvent(); actpos = nextpos; } return 0; } virtual void EBSFile::EBSEventList::Rewind(void) { fseek(ebsf->fstream, rewindpos, SEEK_SET); readpos = 0; actpos = rewindpos; nextpos = 0; }