diff --git a/README b/README index 4a7d6d8..f38f031 100644 --- a/README +++ b/README @@ -1,3 +1,4 @@ + # DSRemote Operate your Rigol oscilloscope from your Linux desktop. ======================================================== @@ -5,31 +6,35 @@ Operate your Rigol oscilloscope from your Linux desktop. webpage and info: https://www.teuniz.net/DSRemote/ -How to compile: ---------------- +Compiling and installing on Ubuntu Linux and derivatives: +--------------------------------------------------------- + +sudo apt-get update +sudo apt-get install g++ make git qtbase5-dev-tools qtbase5-dev qt5-default +git clone https://gitlab.com/Teuniz/DSRemote.git +cd DSRemote +qmake +make -j4 +sudo make install +dsremote -- openSuse Leap 15.1 - sudo zypper in patterns-devel-base-devel_basis git-core make libqt5-qtbase-devel libQt5Core-devel libQt5Concurrent-devel libQt5Gui-devel libQt5Widgets-devel libQt5Network-devel libQt5PrintSupport-devel - git clone https://gitlab.com/Teuniz/DSRemote.git - cd DSRemote - qmake-qt5 - make - sudo make install For USB connection setup use the following commands: ---------------------------------------------------- - sudo groupadd usbtmc - sudo usermod -a -G usbtmc - reboot - +sudo groupadd usbtmc +sudo usermod -a -G usbtmc +reboot Now you can run the program by typing: dsremote +(USB connection does not work on modern USB host controllers thanks to +a bug in the scopes' firmware that Rigol does not want to fix.) Read also the file readme_usbtcm_driver.txt and the file notes.txt. + Supported devices --------------- @@ -46,99 +51,15 @@ Not tested yet: * serial decoding. -DS1000Z series: ---------------- -DSRemote assumes that, on your DS1054Z, all options are installed. -If that is not the case it's possible that the software does not work correctly. -On your scope, go to the menu Utility -> Options -> Installed and make sure you have the following options installed: -* DECODER RS232,I2C,SPI Official -* MEM_DEPTH 24M/12M/6M Official -* TRIGGER Timeout,Runt,Window,Delay,Setup,NthEdge,RS232,I2C,SPI Official -* RECORDER Record/Re-play Official -* BANDWIDTH 100M Official +Note: +This is a private project made available to the public. No pullrequests! +If you believe you found a bug or want to add some feature, open an issue on Gitlab or send me an email. +In case you want to add some code, send me a diff, no pull requests, they will be ignored. +Also, all requests regarding to support other platforms and/or other tools will be ignored. +Again, this a Linux & GCC & Make project. That means no Mac/windows/Clang/CMake etc. -Qt framework: -------------- -In case you want to use Qt5, the recommended way is not to use the Qt5 libraries that comes with your distro. -Instead, download and compile the Qt5 source and use that to compile DSRemote. -Here's a step by step list with instructions: - -First, fulfill the requirements for Qt: - -http://doc.qt.io/qt-5/linux.html - -Debian/Ubuntu: sudo apt-get install build-essential libgl1-mesa-dev libcups2-dev libx11-dev - -Fedora: sudo dnf groupinstall "C Development Tools and Libraries" - sudo dnf install mesa-libGL-devel cups-devel libx11-dev - -openSUSE: sudo zypper install -t pattern devel_basis - sudo zypper install xorg-x11-devel cups-devel freetype-devel fontconfig-devel libxkbcommon-devel libxkbcommon-x11-devel - -############################################################################################# - - Compile a static version of the Qt5 libraries excluding all modules that are not needed. - - This will not mess with your system libraries. The new compiled libraries will be stored - - in a new and separate directory: /usr/local/Qt-5.12.4-static - - It will not interfere with other Qt programs. - -############################################################################################# - -mkdir Qt5-source - -cd Qt5-source - -wget http://ftp1.nluug.nl/languages/qt/official_releases/qt/5.12/5.12.4/single/qt-everywhere-src-5.12.4.tar.xz - -here is a list of download mirrors: https://download.qt.io/static/mirrorlist/ -The Qt source package you are going to need is: qt-everywhere-src-5.12.4.tar.xz - -tar -xvf qt-everywhere-src-5.12.4.tar.xz - -cd qt-everywhere-src-5.12.4 - -./configure -v -prefix /usr/local/Qt-5.12.4-static -release -opensource -confirm-license -c++std c++11 -static -accessibility -fontconfig -skip qtdeclarative -skip qtconnectivity -skip qtmultimedia -qt-zlib -no-mtdev -no-journald -qt-libpng -qt-libjpeg -system-freetype -qt-harfbuzz -no-openssl -no-libproxy -no-glib -nomake examples -nomake tests -no-compile-examples -cups -no-evdev -no-dbus -no-eglfs -qreal double -no-opengl -skip qtlocation -skip qtsensors -skip qtwayland -skip qtgamepad -skip qtserialbus -skip qt3d -skip qtpurchasing -skip qtquickcontrols -skip qtquickcontrols2 -skip qtspeech -skip qtwebengine - -(takes about 2 minutes) - -make -j6 (change option -j according to number of available cpu cores e.g -j4 or -j8) - -(takes about 11 minutes) - -sudo make install - -Now go to the directory that contains the DSRemote sourcecode and enter the following commands: - -/usr/local/Qt-5.12.4-static/bin/qmake - -make -j6 (change option -j according to number of available cpu cores e.g -j4 or -j8) - -sudo make install - -reboot - -Now you can run the program by typing: dsremote - -Congratulations! -You have compiled a static version of DSRemote that can be deployed on other systems without the need -to install the Qt libraries. -In order to reduce the size of the executable, run the following commands: - -strip -s dsremote - -upx dsremote - - -Note: This is a private project made available to the public. No pullrequests! - If you believe you found a bug or want to add some feature, open an issue on Gitlab or send me an email. - In case you want to add some code, send me a diff, no pull requests, they will be ignored. - Also, all requests regarding to support other platforms and/or other tools will be ignored. - Again, this a Linux & GCC & Make project. That means no Mac/windows/Clang/CMake etc. diff --git a/edflib.c b/edflib.c index 35a6c5a..6354eeb 100644 --- a/edflib.c +++ b/edflib.c @@ -42,11 +42,11 @@ #include "edflib.h" -#define EDFLIB_VERSION 116 -#define EDFLIB_MAXFILES 64 +#define EDFLIB_VERSION (118) +#define EDFLIB_MAXFILES (64) -#if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) +#if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) || defined(__HAIKU__) #define fopeno fopen @@ -79,15 +79,15 @@ /* max size of annotationtext */ -#define EDFLIB_WRITE_MAX_ANNOTATION_LEN 40 +#define EDFLIB_WRITE_MAX_ANNOTATION_LEN (40) /* bytes in datarecord for EDF annotations, must be an integer multiple of three and two */ -#define EDFLIB_ANNOTATION_BYTES 114 +#define EDFLIB_ANNOTATION_BYTES (114) /* for writing only */ -#define EDFLIB_MAX_ANNOTATION_CHANNELS 64 +#define EDFLIB_MAX_ANNOTATION_CHANNELS (64) -#define EDFLIB_ANNOT_MEMBLOCKSZ 1000 +#define EDFLIB_ANNOT_MEMBLOCKSZ (1000) struct edfparamblock{ @@ -249,7 +249,7 @@ int edflib_get_handle(int file_number) } -int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int read_annotations) +int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int read_annotations_mode) { int i, j, channel, @@ -260,14 +260,14 @@ int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int r struct edfhdrblock *hdr; - if(read_annotations<0) + if(read_annotations_mode<0) { edfhdr->filetype = EDFLIB_INVALID_READ_ANNOTS_VALUE; return -1; } - if(read_annotations>2) + if(read_annotations_mode>2) { edfhdr->filetype = EDFLIB_INVALID_READ_ANNOTS_VALUE; @@ -408,26 +408,25 @@ int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int r edflib_strlcpy(edfhdr->equipment, hdr->plus_equipment, 81); edflib_strlcpy(edfhdr->recording_additional, hdr->plus_recording_additional, 81); - if((read_annotations==EDFLIB_READ_ANNOTATIONS)||(read_annotations==EDFLIB_READ_ALL_ANNOTATIONS)) + if(edflib_get_annotations(hdr, edfhdr->handle, read_annotations_mode)) { - if(edflib_get_annotations(hdr, edfhdr->handle, read_annotations)) - { - edfhdr->filetype = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; + edfhdr->filetype = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; - fclose(file); + fclose(file); - free(hdr->edfparam); - hdr->edfparam = NULL; - free(hdr); - hdr = NULL; - hdrlist[edfhdr->handle] = NULL; - free(annotationslist[edfhdr->handle]); - annotationslist[edfhdr->handle] = NULL; + free(hdr->edfparam); + hdr->edfparam = NULL; + free(hdr); + hdr = NULL; + hdrlist[edfhdr->handle] = NULL; + free(annotationslist[edfhdr->handle]); + annotationslist[edfhdr->handle] = NULL; - return -1; - } + return -1; } + edfhdr->starttime_subsecond = hdr->starttime_offset; + edfhdr->annotations_in_file = hdr->annots_in_file; } @@ -528,13 +527,13 @@ int edfclose_file(int handle) { annot2 = write_annotationslist[handle] + k; - p = edflib_fprint_ll_number_nonlocalized(hdr->file_hdl, (hdr->datarecords * hdr->long_data_record_duration) / EDFLIB_TIME_DIMENSION, 0, 1); + p = edflib_fprint_ll_number_nonlocalized(hdr->file_hdl, (hdr->datarecords * hdr->long_data_record_duration + hdr->starttime_offset) / EDFLIB_TIME_DIMENSION, 0, 1); - if(hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) + if((hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) || (hdr->starttime_offset)) { fputc('.', hdr->file_hdl); p++; - p += edflib_fprint_ll_number_nonlocalized(hdr->file_hdl, (hdr->datarecords * hdr->long_data_record_duration) % EDFLIB_TIME_DIMENSION, 7, 0); + p += edflib_fprint_ll_number_nonlocalized(hdr->file_hdl, (hdr->datarecords * hdr->long_data_record_duration + hdr->starttime_offset) % EDFLIB_TIME_DIMENSION, 7, 0); } fputc(20, hdr->file_hdl); fputc(20, hdr->file_hdl); @@ -586,6 +585,8 @@ int edfclose_file(int handle) { annot2 = write_annotationslist[handle] + k; + annot2->onset += hdr->starttime_offset / 1000LL; + p = 0; if(j==0) // first annotation signal @@ -595,12 +596,12 @@ int edfclose_file(int handle) break; } - p += edflib_snprint_ll_number_nonlocalized(str, (datarecords * hdr->long_data_record_duration) / EDFLIB_TIME_DIMENSION, 0, 1, EDFLIB_ANNOTATION_BYTES * 2); + p += edflib_snprint_ll_number_nonlocalized(str, (datarecords * hdr->long_data_record_duration + hdr->starttime_offset) / EDFLIB_TIME_DIMENSION, 0, 1, EDFLIB_ANNOTATION_BYTES * 2); - if(hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) + if((hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) || (hdr->starttime_offset)) { str[p++] = '.'; - n = edflib_snprint_ll_number_nonlocalized(str + p, (datarecords * hdr->long_data_record_duration) % EDFLIB_TIME_DIMENSION, 7, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p); + n = edflib_snprint_ll_number_nonlocalized(str + p, (datarecords * hdr->long_data_record_duration + hdr->starttime_offset) % EDFLIB_TIME_DIMENSION, 7, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p); p += n; } str[p++] = 20; @@ -2503,9 +2504,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro return NULL; } - edfhdr->startdate_year = edflib_atof_nonlocalized(scratchpad2 + 7); - - if(edfhdr->startdate_year<1970) + if(edfhdr->startdate_year != edflib_atof_nonlocalized(scratchpad2 + 7)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); @@ -2866,7 +2865,7 @@ int edflib_version(void) } -static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_annotations) +static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_annotations_mode) { int i, j, k, p, r=0, n, edfsignals, @@ -3055,7 +3054,7 @@ static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_ } else { - if(time_tmp>=EDFLIB_TIME_DIMENSION) + if((time_tmp>=EDFLIB_TIME_DIMENSION) || (time_tmp<0LL)) { error = 2; goto END; @@ -3063,6 +3062,11 @@ static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_ else { edfhdr->starttime_offset = time_tmp; + if(read_annotations_mode==EDFLIB_DO_NOT_READ_ANNOTATIONS) + { + error = 0; + goto END_OUT; + } } } elapsedtime = time_tmp; @@ -3158,9 +3162,11 @@ static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_ new_annotation->onset = edflib_get_long_time(time_in_txt); + new_annotation->onset -= edfhdr->starttime_offset; + edfhdr->annots_in_file++; - if(read_annotations==EDFLIB_READ_ANNOTATIONS) + if(read_annotations_mode==EDFLIB_READ_ANNOTATIONS) { if(!(strncmp(new_annotation->annotation, "Recording ends", 14))) { @@ -3238,6 +3244,8 @@ static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_ } } + END_OUT: + free(cnv_buf); free(scratchpad); free(time_in_txt); @@ -3937,6 +3945,44 @@ int edf_set_micro_datarecord_duration(int handle, int duration) } +int edf_set_subsecond_starttime(int handle, int subsecond) +{ + if(handle<0) + { + return -1; + } + + if(handle>=EDFLIB_MAXFILES) + { + return -1; + } + + if(hdrlist[handle]==NULL) + { + return -1; + } + + if(!(hdrlist[handle]->writemode)) + { + return -1; + } + + if(hdrlist[handle]->datarecords) + { + return -1; + } + + if((subsecond < 0) || (subsecond > 9999999)) + { + return -1; + } + + hdrlist[handle]->starttime_offset = (long long)subsecond; + + return 0; +} + + int edfwrite_digital_short_samples(int handle, short *buf) { int i, @@ -6384,7 +6430,7 @@ int edf_set_startdatetime(int handle, int startdate_year, int startdate_month, i return -1; } - if((startdate_year<1970) || (startdate_year>3000) || + if((startdate_year<1985) || (startdate_year>2084) || (startdate_month<1) || (startdate_month>12) || (startdate_day<1) || (startdate_day>31) || (starttime_hour<0) || (starttime_hour>23) || @@ -6465,7 +6511,7 @@ int edfwrite_annotation_utf8(int handle, long long onset, long long duration, co break; } - if(list_annot->annotation[i] < 32) + if(((unsigned char *)(list_annot->annotation))[i] < 32) { list_annot->annotation[i] = '.'; } @@ -6688,7 +6734,7 @@ static int edflib_fprint_int_number_nonlocalized(FILE *file, int q, int minimum, j++; - q = -q; + base = -base; } else { @@ -6760,7 +6806,7 @@ static int edflib_fprint_ll_number_nonlocalized(FILE *file, long long q, int min j++; - q = -q; + base = -base; } else { @@ -6900,7 +6946,7 @@ static int edflib_snprint_ll_number_nonlocalized(char *dest, long long q, int mi { dest[j++] = '-'; - q = -q; + base = -base; } else { @@ -6981,7 +7027,7 @@ static int edflib_snprint_number_nonlocalized(char *dest, double val, int sz) if(q < 0) { - q = -q; + base = -base; } } @@ -7035,7 +7081,7 @@ static int edflib_snprint_number_nonlocalized(char *dest, double val, int sz) if(q < 0) { - q = -q; + base = -base; } if(!q) @@ -7263,11 +7309,11 @@ static int edflib_write_tal(struct edfhdrblock *hdr, FILE *file) char str[EDFLIB_ANNOTATION_BYTES * (EDFLIB_MAX_ANNOTATION_CHANNELS + 1)]; - p = edflib_snprint_ll_number_nonlocalized(str, (hdr->datarecords * hdr->long_data_record_duration) / EDFLIB_TIME_DIMENSION, 0, 1, EDFLIB_ANNOTATION_BYTES * (EDFLIB_MAX_ANNOTATION_CHANNELS + 1)); - if(hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) + p = edflib_snprint_ll_number_nonlocalized(str, (hdr->datarecords * hdr->long_data_record_duration + hdr->starttime_offset) / EDFLIB_TIME_DIMENSION, 0, 1, EDFLIB_ANNOTATION_BYTES * (EDFLIB_MAX_ANNOTATION_CHANNELS + 1)); + if((hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) || (hdr->starttime_offset)) { str[p++] = '.'; - p += edflib_snprint_ll_number_nonlocalized(str + p, (hdr->datarecords * hdr->long_data_record_duration) % EDFLIB_TIME_DIMENSION, 7, 0, (EDFLIB_ANNOTATION_BYTES * (EDFLIB_MAX_ANNOTATION_CHANNELS + 1)) - p); + p += edflib_snprint_ll_number_nonlocalized(str + p, (hdr->datarecords * hdr->long_data_record_duration + hdr->starttime_offset) % EDFLIB_TIME_DIMENSION, 7, 0, (EDFLIB_ANNOTATION_BYTES * (EDFLIB_MAX_ANNOTATION_CHANNELS + 1)) - p); } str[p++] = 20; str[p++] = 20; diff --git a/edflib.h b/edflib.h index 5c87c3c..d3d8e0f 100644 --- a/edflib.h +++ b/edflib.h @@ -48,51 +48,51 @@ -#define EDFLIB_TIME_DIMENSION (10000000LL) -#define EDFLIB_MAXSIGNALS 640 -#define EDFLIB_MAX_ANNOTATION_LEN 512 +#define EDFLIB_TIME_DIMENSION (10000000LL) +#define EDFLIB_MAXSIGNALS (640) +#define EDFLIB_MAX_ANNOTATION_LEN (512) -#define EDFSEEK_SET 0 -#define EDFSEEK_CUR 1 -#define EDFSEEK_END 2 +#define EDFSEEK_SET (0) +#define EDFSEEK_CUR (1) +#define EDFSEEK_END (2) /* the following defines are used in the member "filetype" of the edf_hdr_struct */ /* and as return value for the function edfopen_file_readonly() */ -#define EDFLIB_FILETYPE_EDF 0 -#define EDFLIB_FILETYPE_EDFPLUS 1 -#define EDFLIB_FILETYPE_BDF 2 -#define EDFLIB_FILETYPE_BDFPLUS 3 -#define EDFLIB_MALLOC_ERROR -1 -#define EDFLIB_NO_SUCH_FILE_OR_DIRECTORY -2 +#define EDFLIB_FILETYPE_EDF (0) +#define EDFLIB_FILETYPE_EDFPLUS (1) +#define EDFLIB_FILETYPE_BDF (2) +#define EDFLIB_FILETYPE_BDFPLUS (3) +#define EDFLIB_MALLOC_ERROR (-1) +#define EDFLIB_NO_SUCH_FILE_OR_DIRECTORY (-2) /* when this error occurs, try to open the file with EDFbrowser, it will give you full details about the cause of the error. */ #define EDFLIB_FILE_CONTAINS_FORMAT_ERRORS -3 -#define EDFLIB_MAXFILES_REACHED -4 -#define EDFLIB_FILE_READ_ERROR -5 -#define EDFLIB_FILE_ALREADY_OPENED -6 -#define EDFLIB_FILETYPE_ERROR -7 -#define EDFLIB_FILE_WRITE_ERROR -8 -#define EDFLIB_NUMBER_OF_SIGNALS_INVALID -9 -#define EDFLIB_FILE_IS_DISCONTINUOUS -10 -#define EDFLIB_INVALID_READ_ANNOTS_VALUE -11 +#define EDFLIB_MAXFILES_REACHED (-4) +#define EDFLIB_FILE_READ_ERROR (-5) +#define EDFLIB_FILE_ALREADY_OPENED (-6) +#define EDFLIB_FILETYPE_ERROR (-7) +#define EDFLIB_FILE_WRITE_ERROR (-8) +#define EDFLIB_NUMBER_OF_SIGNALS_INVALID (-9) +#define EDFLIB_FILE_IS_DISCONTINUOUS (-10) +#define EDFLIB_INVALID_READ_ANNOTS_VALUE (-11) /* values for annotations */ -#define EDFLIB_DO_NOT_READ_ANNOTATIONS 0 -#define EDFLIB_READ_ANNOTATIONS 1 -#define EDFLIB_READ_ALL_ANNOTATIONS 2 +#define EDFLIB_DO_NOT_READ_ANNOTATIONS (0) +#define EDFLIB_READ_ANNOTATIONS (1) +#define EDFLIB_READ_ALL_ANNOTATIONS (2) /* the following defines are possible errors returned by the first sample write action */ -#define EDFLIB_NO_SIGNALS -20 -#define EDFLIB_TOO_MANY_SIGNALS -21 -#define EDFLIB_NO_SAMPLES_IN_RECORD -22 -#define EDFLIB_DIGMIN_IS_DIGMAX -23 -#define EDFLIB_DIGMAX_LOWER_THAN_DIGMIN -24 -#define EDFLIB_PHYSMIN_IS_PHYSMAX -25 -#define EDFLIB_DATARECORD_SIZE_TOO_BIG -26 +#define EDFLIB_NO_SIGNALS (-20) +#define EDFLIB_TOO_MANY_SIGNALS (-21) +#define EDFLIB_NO_SAMPLES_IN_RECORD (-22) +#define EDFLIB_DIGMIN_IS_DIGMAX (-23) +#define EDFLIB_DIGMAX_LOWER_THAN_DIGMIN (-24) +#define EDFLIB_PHYSMIN_IS_PHYSMAX (-25) +#define EDFLIB_DATARECORD_SIZE_TOO_BIG (-26) @@ -133,8 +133,10 @@ extern "C" { * This is not a concern anymore so the maximum datarecord size now is limited to 10MByte for EDF(+) and 15MByte for BDF(+). This helps to accommodate for higher samplingrates * used by modern Analog to Digital Converters. * - * EDF header character encoding: The EDF specification says that only ASCII characters are allowed. - * EDFlib will automatically convert characters with accents, umlauts, tilde, etc. to their "normal" equivalent without the accent/umlaut/tilde/etc. + * EDF header character encoding: The EDF specification says that only (printable) ASCII characters are allowed. + * When writing the header info, EDFlib will assume you are using Latin1 encoding and it will automatically convert + * characters with accents, umlauts, tilde, etc. to their "normal" equivalent without the accent/umlaut/tilde/etc. + * in order to create a valid EDF file. * * The description/name of an EDF+ annotation on the other hand, is encoded in UTF-8. * @@ -156,7 +158,7 @@ struct edf_param_struct{ /* this structure contains all the relevant EDF struct edf_annotation_struct{ /* this structure is used for annotations */ - long long onset; /* onset time of the event, expressed in units of 100 nanoSeconds and relative to the starttime in the header */ + long long onset; /* onset time of the event, expressed in units of 100 nanoSeconds and relative to the start of the file */ char duration[16]; /* duration time, this is a null-terminated ASCII text-string */ char annotation[EDFLIB_MAX_ANNOTATION_LEN + 1]; /* description of the event in UTF-8, this is a null terminated string */ }; @@ -419,7 +421,7 @@ int edf_set_physical_dimension(int handle, int edfsignal, const char *phys_dim); /* Sets the physical dimension (unit) of signal edfsignal. ("uV", "BPM", "mA", "Degr.", etc.) */ /* phys_dim is a pointer to a NULL-terminated ASCII-string containing the physical dimension of the signal edfsignal */ /* Returns 0 on success, otherwise -1 */ -/* This function is recommanded for every signal when you want to write a file */ +/* This function is recommended for every signal when you want to write a file */ /* and can be called only after opening a file in writemode and before the first sample write action */ @@ -427,7 +429,7 @@ int edf_set_startdatetime(int handle, int startdate_year, int startdate_month, i int starttime_hour, int starttime_minute, int starttime_second); /* Sets the startdate and starttime. */ -/* year: 1970 - 3000, month: 1 - 12, day: 1 - 31 */ +/* year: 1985 - 2084, month: 1 - 12, day: 1 - 31 */ /* hour: 0 - 23, minute: 0 - 59, second: 0 - 59 */ /* If not called, the library will use the system date and time at runtime */ /* Returns 0 on success, otherwise -1 */ @@ -609,7 +611,7 @@ int edf_blockwrite_digital_samples(int handle, int *buf); int edfwrite_annotation_utf8(int handle, long long onset, long long duration, const char *description); /* writes an annotation/event to the file */ -/* onset is relative to the starttime and startdate of the file */ +/* onset is relative to the start of the file */ /* onset and duration are in units of 100 microSeconds! resolution is 0.0001 second! */ /* for example: 34.071 seconds must be written as 340710 */ /* if duration is unknown or not applicable: set a negative number (-1) */ @@ -621,7 +623,7 @@ int edfwrite_annotation_utf8(int handle, long long onset, long long duration, co int edfwrite_annotation_latin1(int handle, long long onset, long long duration, const char *description); /* writes an annotation/event to the file */ -/* onset is relative to the starttime and startdate of the file */ +/* onset is relative to the start of the file */ /* onset and duration are in units of 100 microSeconds! resolution is 0.0001 second! */ /* for example: 34.071 seconds must be written as 340710 */ /* if duration is unknown or not applicable: set a negative number (-1) */ @@ -676,6 +678,16 @@ int edf_set_number_of_annotation_signals(int handle, int annot_signals); /* Returns 0 on success, otherwise -1 */ +int edf_set_subsecond_starttime(int handle, int subsecond); +/* Sets the subsecond starttime expressed in units of 100 nanoSeconds */ +/* Valid range is 0 to 9999999 inclusive. Default is 0 */ +/* This function is optional and can be called only after opening a file in writemode */ +/* and before the first sample write action */ +/* Returns 0 on success, otherwise -1 */ +/* It is strongly recommended to use a maximum resolution of no more than 100 micro-Seconds. */ +/* e.g. use 1234000 to set a starttime offset of 0.1234 seconds (instead of 1234567) */ +/* in other words, leave the last 3 digits at zero */ + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/global.h b/global.h index ed1c7e1..526a9db 100644 --- a/global.h +++ b/global.h @@ -35,7 +35,7 @@ #define PROGRAM_NAME "DSRemote" -#define PROGRAM_VERSION "0.37_2006141810" +#define PROGRAM_VERSION "0.37_2012070931" #define MAX_PATHLEN 1024 diff --git a/utils.c b/utils.c index e7c834a..58f96db 100644 --- a/utils.c +++ b/utils.c @@ -11,8 +11,7 @@ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. +* the Free Software Foundation, version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -243,6 +242,42 @@ void remove_leading_spaces(char *str) } +/* removes both leading and trailing spaces */ +void trim_spaces(char *str) +{ + int i, diff, len; + + len = strlen(str); + + for(i=0; i=0; i--) + { + if(str[i]!=' ') break; + } + + str[i+1] = 0; +} + + void remove_trailing_zeros(char *str) { @@ -717,7 +752,7 @@ int fprint_int_number_nonlocalized(FILE *file, int q, int minimum, int sign) j++; - q = -q; + base = -base; } else { @@ -789,7 +824,7 @@ int fprint_ll_number_nonlocalized(FILE *file, long long q, int minimum, int sign j++; - q = -q; + base = -base; } else { @@ -839,64 +874,64 @@ int fprint_ll_number_nonlocalized(FILE *file, long long q, int minimum, int sign /* if sign is zero, only negative numbers will have the sign '-' character */ /* if sign is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ -int sprint_int_number_nonlocalized(char *str, int q, int minimum, int sign) -{ - int flag=0, z, i, j=0, base = 1000000000; - - if(minimum < 0) - { - minimum = 0; - } - - if(minimum > 9) - { - flag = 1; - } - - if(q < 0) - { - str[j++] = '-'; - - q = -q; - } - else - { - if(sign) - { - str[j++] = '+'; - } - } - - for(i=10; i; i--) - { - if(minimum == i) - { - flag = 1; - } - - z = q / base; - - q %= base; - - if(z || flag) - { - str[j++] = '0' + z; - - flag = 1; - } - - base /= 10; - } - - if(!flag) - { - str[j++] = '0'; - } - - str[j] = 0; - - return j; -} +// int sprint_int_number_nonlocalized(char *str, int q, int minimum, int sign) +// { +// int flag=0, z, i, j=0, base = 1000000000; +// +// if(minimum < 0) +// { +// minimum = 0; +// } +// +// if(minimum > 9) +// { +// flag = 1; +// } +// +// if(q < 0) +// { +// str[j++] = '-'; +// +// q = -q; +// } +// else +// { +// if(sign) +// { +// str[j++] = '+'; +// } +// } +// +// for(i=10; i; i--) +// { +// if(minimum == i) +// { +// flag = 1; +// } +// +// z = q / base; +// +// q %= base; +// +// if(z || flag) +// { +// str[j++] = '0' + z; +// +// flag = 1; +// } +// +// base /= 10; +// } +// +// if(!flag) +// { +// str[j++] = '0'; +// } +// +// str[j] = 0; +// +// return j; +// } /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */ @@ -923,7 +958,7 @@ int sprint_ll_number_nonlocalized(char *str, long long q, int minimum, int sign) { str[j++] = '-'; - q = -q; + base = -base; } else { @@ -965,98 +1000,98 @@ int sprint_ll_number_nonlocalized(char *str, long long q, int minimum, int sign) } -int sprint_number_nonlocalized(char *str, double nr) -{ - int flag=0, z, i, j=0, q, base = 1000000000; - - double var; - - q = (int)nr; - - var = nr - q; - - if(nr < 0.0) - { - str[j++] = '-'; - - if(q < 0) - { - q = -q; - } - } - - for(i=10; i; i--) - { - z = q / base; - - q %= base; - - if(z || flag) - { - str[j++] = '0' + z; - - flag = 1; - } - - base /= 10; - } - - if(!flag) - { - str[j++] = '0'; - } - - base = 100000000; - - var *= (base * 10); - - q = (int)var; - - if(q < 0) - { - q = -q; - } - - if(!q) - { - str[j] = 0; - - return j; - } - - str[j++] = '.'; - - for(i=9; i; i--) - { - z = q / base; - - q %= base; - - str[j++] = '0' + z; - - base /= 10; - } - - str[j] = 0; - - j--; - - for(; j>0; j--) - { - if(str[j] == '0') - { - str[j] = 0; - } - else - { - j++; - - break; - } - } - - return j; -} +// int sprint_number_nonlocalized(char *str, double nr) +// { +// int flag=0, z, i, j=0, q, base = 1000000000; +// +// double var; +// +// q = (int)nr; +// +// var = nr - q; +// +// if(nr < 0.0) +// { +// str[j++] = '-'; +// +// if(q < 0) +// { +// q = -q; +// } +// } +// +// for(i=10; i; i--) +// { +// z = q / base; +// +// q %= base; +// +// if(z || flag) +// { +// str[j++] = '0' + z; +// +// flag = 1; +// } +// +// base /= 10; +// } +// +// if(!flag) +// { +// str[j++] = '0'; +// } +// +// base = 100000000; +// +// var *= (base * 10); +// +// q = (int)var; +// +// if(q < 0) +// { +// q = -q; +// } +// +// if(!q) +// { +// str[j] = 0; +// +// return j; +// } +// +// str[j++] = '.'; +// +// for(i=9; i; i--) +// { +// z = q / base; +// +// q %= base; +// +// str[j++] = '0' + z; +// +// base /= 10; +// } +// +// str[j] = 0; +// +// j--; +// +// for(; j>0; j--) +// { +// if(str[j] == '0') +// { +// str[j] = 0; +// } +// else +// { +// j++; +// +// break; +// } +// } +// +// return j; +// } double atof_nonlocalized(const char *str) @@ -2142,7 +2177,7 @@ char * strtok_r_e(char *str, const char *delim, char **saveptr) * plus the length of src. While this may seem somewhat confusing, * it was done to make truncation detection simple." */ -#if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) || defined(__FreeBSD__) +#if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) || defined(__FreeBSD__) || defined(__HAIKU__) /* nothing here */ #else int strlcpy(char *dst, const char *src, int sz) @@ -2172,7 +2207,7 @@ int strlcat(char *dst, const char *src, int sz) sz -= dstlen + 1; - if(!sz) return dstlen; + if(sz < 1) return dstlen; srclen = strlen(src); @@ -2187,7 +2222,109 @@ int strlcat(char *dst, const char *src, int sz) #endif - +void str_insert_substr(char *str, int pos, int len, const char *substr, int subpos, int sublen) +{ + int i, slen; + + if((pos >= len) || (pos < 0) || (len < 1) || (subpos >= sublen) || (subpos < 0) || (sublen < 1)) return; + + slen = strlen(str); + + if(pos > slen) return; + + if(sublen > (signed)strlen(substr)) sublen = strlen(substr); + + for(i=((slen+sublen)-1); i>=(pos + sublen); i--) + { + if(i < len) str[i] = str[i-sublen]; + } + + for(i=0; i= len) || ((subpos + i) >= sublen)) break; + + str[pos + i] = substr[subpos + i]; + } + + if((slen + sublen) < len) + { + str[slen + sublen] = 0; + } + else + { + str[len-1] = 0; + } +} + + +int str_replace_substr(char *str, int len, int n, const char *dest_substr, const char *src_substr) +{ + int i, pos, slen, destlen, srclen, occurrence=0, cnt=0, lendiff; + + slen = strlen(str); + + destlen = strlen(dest_substr); + + srclen = strlen(src_substr); + + lendiff = srclen - destlen; + + for(pos=0; pos 0) + { + for(i=((slen+lendiff)-1); i>=(pos + lendiff); i--) + { + if(i < len) str[i] = str[i-lendiff]; + } + } + else if(lendiff < 0) + { + for(i=(pos + srclen); i<(slen+lendiff); i++) + { + if(i < len) str[i] = str[i-lendiff]; + } + } + + for(i=0; i= len) break; + + str[pos + i] = src_substr[i]; + } + + if((slen + lendiff) < len) + { + slen += lendiff; + + str[slen] = 0; + + pos += lendiff; + } + else + { + str[len-1] = 0; + + slen = len; + + break; + } + + cnt++; + + if(n != -1) break; + } + + occurrence++; + } + } + + return cnt; +} diff --git a/utils.h b/utils.h index 409db29..b625331 100644 --- a/utils.h +++ b/utils.h @@ -11,8 +11,7 @@ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. +* the Free Software Foundation, version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -45,8 +44,21 @@ extern "C" { void remove_trailing_spaces(char *); void remove_leading_spaces(char *); +void trim_spaces(char *); void remove_trailing_zeros(char *); void convert_trailing_zeros_to_spaces(char *); + +/* Inserts a copy of substr into str. The substring is the portion of substr that begins at */ +/* the character position subpos and spans sublen characters (or until the end of substr */ +/* if substr is too short). */ +void str_insert_substr(char *str, int pos, int len, const char *substr, int subpos, int sublen); + +/* Replaces the nth occurence of dest_substr in str with src_substr. */ +/* If n = -1, all occurrences will be replaced. */ +/* len is the buffer length, not the string length! */ +/* Returns the number of substrings replaced. */ +int str_replace_substr(char *str, int len, int n, const char *dest_substr, const char *src_substr); + void remove_extension_from_filename(char *); /* removes extension including the dot */ int get_filename_from_path(char *dest, const char *src, int size); /* size is size of destination, returns length of filename */ int get_directory_from_path(char *dest, const char *src, int size); /* size is size of destination, returns length of directory */ @@ -56,7 +68,7 @@ void utf8_to_latin1(char *); int antoi(const char *, int); int atoi_nonlocalized(const char *); double atof_nonlocalized(const char *); -int sprint_number_nonlocalized(char *, double); +//int sprint_number_nonlocalized(char *, double); long long atoll_x(const char *, int); void strntolower(char *, int); @@ -67,7 +79,7 @@ char * strtok_r_e(char *, const char *, char **); /* if 4th argument is zero, only negative numbers will have the sign '-' character */ /* if 4th argument is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ -int sprint_int_number_nonlocalized(char *, int, int, int); +//int sprint_int_number_nonlocalized(char *, int, int, int); int sprint_ll_number_nonlocalized(char *, long long, int, int); int fprint_int_number_nonlocalized(FILE *, int, int, int); int fprint_ll_number_nonlocalized(FILE *, long long, int, int); @@ -108,7 +120,7 @@ int base64_dec(const void *, void *, int); * plus the length of src. While this may seem somewhat confusing, * it was done to make truncation detection simple." */ -#if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) || defined(__FreeBSD__) +#if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) || defined(__FreeBSD__) || defined(__HAIKU__) /* nothing here */ #else int strlcpy(char *, const char *, int);