00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "mmstools/mmspulser.h"
00034 #include "mmstools/tools.h"
00035 #include "mmstools/mmserror.h"
00036 #include <math.h>
00037
00038 MMSPulser::MMSPulser() : MMSThread("MMSPulser") {
00039
00040 this->animRunning = false;
00041
00042
00043 setStacksize(128*1024);
00044
00045
00046 setStepsPerSecond(25);
00047 setMaxCPUUsage(100);
00048 setMaxFrameRate(25);
00049 setMaxOffset(0);
00050 setDuration(0);
00051
00052
00053 reset();
00054 }
00055
00056 MMSPulser::~MMSPulser() {
00057 }
00058
00059 void MMSPulser::reset() {
00060
00061 this->cancel = false;
00062 this->recalc_requested = true;
00063 this->recalc_cnt = 0;
00064 this->recalc_interval = 3;
00065 this->step_len = 0;
00066 this->offset = 0;
00067 this->offset_curve = 0;
00068 this->process_time = 0;
00069 this->frame_delay = 0;
00070 this->frame_rate = 0;
00071 this->frames = 0;
00072 this->times_buf_pos = 0;
00073 this->times_buf_cnt = 0;
00074 this->real_duration = 0;
00075 this->onAnimation_counter = 0;
00076
00077 if (this->max_offset > 0) {
00078
00079 this->recalc_interval = 1;
00080 }
00081
00082
00083 switch (this->seq_mode) {
00084 case MMSPULSER_SEQ_LINEAR:
00085 case MMSPULSER_SEQ_LOG_SOFT_START:
00086 case MMSPULSER_SEQ_LOG_SOFT_END:
00087 case MMSPULSER_SEQ_LOG_SOFT_START_AND_END:
00088 this->offset = 1;
00089 this->offset_curve = 0;
00090 calcCurve(this->offset, this->offset_curve);
00091 break;
00092 case MMSPULSER_SEQ_LINEAR_DESC:
00093 case MMSPULSER_SEQ_LOG_DESC_SOFT_START:
00094 case MMSPULSER_SEQ_LOG_DESC_SOFT_END:
00095 case MMSPULSER_SEQ_LOG_DESC_SOFT_START_AND_END:
00096 this->offset = this->max_offset - 1;
00097 this->offset_curve = this->max_offset;
00098 calcCurve(this->offset, this->offset_curve);
00099 break;
00100 default:
00101 break;
00102 }
00103 }
00104
00105 void MMSPulser::calcCurve(double &offset, double &offset_curve) {
00106
00107 if (this->max_offset > 0) {
00108 switch (this->seq_mode) {
00109 case MMSPULSER_SEQ_LINEAR:
00110 if (this->seq_start <= 0)
00111 offset_curve = offset;
00112 else
00113 offset_curve = this->seq_start + (offset * this->seq_range) / this->max_offset;
00114 break;
00115 case MMSPULSER_SEQ_LINEAR_DESC:
00116 if (this->seq_start <= 0)
00117 offset_curve = offset;
00118 else
00119 offset_curve = (offset * this->seq_range) / this->max_offset;
00120 break;
00121 case MMSPULSER_SEQ_LOG_SOFT_START:
00122
00123 if (this->max_offset - offset > 1) {
00124 offset_curve = this->seq_start
00125 + this->seq_range * (1 - (log(this->max_offset - offset) / this->max_offset_log));
00126 }
00127 else {
00128
00129 offset_curve = this->max_offset;
00130 }
00131 break;
00132 case MMSPULSER_SEQ_LOG_DESC_SOFT_START:
00133
00134 if (offset > 1) {
00135 offset_curve = this->seq_start
00136 - this->seq_range * (1 - (log(offset) / this->max_offset_log));
00137 }
00138 else {
00139
00140 offset_curve = 0;
00141 }
00142 break;
00143 case MMSPULSER_SEQ_LOG_SOFT_END:
00144
00145 if (offset == 1) offset++;
00146 offset_curve = this->seq_start
00147 + this->seq_range * (log(offset) / this->max_offset_log);
00148 break;
00149 case MMSPULSER_SEQ_LOG_DESC_SOFT_END:
00150
00151 if (this->max_offset - offset == 1) offset--;
00152 offset_curve = this->seq_start
00153 - this->seq_range * (log(this->max_offset - offset) / this->max_offset_log);
00154 break;
00155 case MMSPULSER_SEQ_LOG_SOFT_START_AND_END:
00156 if (offset_curve < this->max_offset / 2) {
00157 if (this->max_offset - offset > 0) {
00158 offset_curve = this->seq_start
00159 + this->seq_range * (1 - (log(this->max_offset - offset) / this->max_offset_log));
00160 if (offset_curve >= this->max_offset / 2) {
00161 offset = this->max_offset - offset + 1;
00162 calcCurve(offset, offset_curve);
00163 }
00164 }
00165 else {
00166
00167 offset_curve = this->max_offset;
00168 offset = 1;
00169 calcCurve(offset, offset_curve);
00170 }
00171 }
00172 else {
00173 offset_curve = (this->max_offset - this->seq_range)
00174 + this->seq_range * (log(offset) / this->max_offset_log);
00175 }
00176 break;
00177 case MMSPULSER_SEQ_LOG_DESC_SOFT_START_AND_END:
00178 if (offset_curve > this->max_offset / 2) {
00179 if (offset > 0) {
00180 offset_curve = (this->max_offset - this->seq_range)
00181 + this->seq_range * (log(offset) / this->max_offset_log);
00182 if (offset_curve <= this->max_offset / 2) {
00183 offset = this->max_offset - offset - 1;
00184 calcCurve(offset, offset_curve);
00185 }
00186 }
00187 else {
00188
00189 offset_curve = 0;
00190 offset = this->max_offset - 1;
00191 calcCurve(offset, offset_curve);
00192 }
00193 }
00194 else {
00195 offset_curve = this->seq_range * (1 - (log(this->max_offset - offset) / this->max_offset_log));
00196 }
00197 break;
00198
00199 default:
00200 offset_curve = 0;
00201 break;
00202 }
00203 }
00204 else
00205 offset_curve = 0;
00206 }
00207
00208 void MMSPulser::threadMain() {
00209
00210
00211 if (!this->onBeforeAnimation.emit(this)) {
00212
00213 return;
00214 }
00215
00216
00217 this->anim_start = getMTimeStamp();
00218
00219 while (1) {
00220
00221 unsigned int start_ts;
00222 unsigned int end_ts;
00223
00224
00225 if (this->recalc_requested) {
00226 start_ts = getMTimeStamp();
00227 }
00228
00229 if (this->cancel) {
00230
00231 break;
00232 }
00233
00234
00235 if (!this->onAnimation.emit(this)) {
00236
00237 break;
00238 }
00239 this->onAnimation_counter++;
00240
00241
00242 if (this->recalc_requested) {
00243
00244 end_ts = getMTimeStamp();
00245
00246
00247
00248
00249 unsigned int times = 0;
00250 unsigned int diff = getMDiff(start_ts, end_ts);
00251 this->times_buf[times_buf_pos++] = diff;
00252 if (this->times_buf_pos >= MMSPULSER_TIMES_BUF_SIZE) this->times_buf_pos = 0;
00253 if (this->times_buf_cnt < MMSPULSER_TIMES_BUF_SIZE) this->times_buf_cnt++;
00254 for (unsigned int i = 0; i < this->times_buf_cnt; i++) times+= this->times_buf[i];
00255 this->process_time = (times + diff / 2) / this->times_buf_cnt;
00256
00257
00258 int max_duration = 1000 / this->steps_per_second;
00259 if (this->seq_mode == MMSPULSER_SEQ_LOG_SOFT_START_AND_END || this->seq_mode == MMSPULSER_SEQ_LOG_DESC_SOFT_START_AND_END) {
00260
00261 max_duration/= 2;
00262 }
00263 int total_time = (this->process_time * 100) / this->max_cpu_usage;
00264 this->step_len = (total_time + max_duration - 1) / max_duration;
00265 this->frame_delay = max_duration * this->step_len - this->process_time;
00266 if (this->frame_delay <= 0) this->frame_delay = 1;
00267 int frame_duration = this->frame_delay + this->process_time;
00268 this->frame_rate = 1000 / frame_duration;
00269
00270 if (this->frame_rate > this->max_frame_rate) {
00271
00272
00273 this->frame_delay = 1000 / this->max_frame_rate - this->process_time;
00274 frame_duration = this->frame_delay + this->process_time;
00275 this->step_len = (frame_duration + max_duration - 1) / max_duration;
00276 this->frame_delay = max_duration * this->step_len - this->process_time;
00277 if (this->frame_delay <= 0) this->frame_delay = 1;
00278 frame_duration = this->frame_delay + this->process_time;
00279 this->frame_rate = 1000 / frame_duration;
00280 }
00281
00282
00283 this->recalc_cnt = 1;
00284 this->recalc_requested = (this->recalc_interval <= 1);
00285 }
00286 else {
00287
00288 this->recalc_cnt++;
00289 if (this->recalc_cnt >= this->recalc_interval) {
00290
00291 this->recalc_cnt = 0;
00292 this->recalc_requested = true;
00293 }
00294 }
00295
00296
00297 usleep((this->frame_delay>0)?this->frame_delay*1000:1000);
00298
00299
00300 this->frames++;
00301
00302
00303 switch (this->seq_mode) {
00304 case MMSPULSER_SEQ_LINEAR:
00305 case MMSPULSER_SEQ_LOG_SOFT_START:
00306 case MMSPULSER_SEQ_LOG_SOFT_END:
00307 case MMSPULSER_SEQ_LOG_SOFT_START_AND_END:
00308 this->offset+= this->step_len;
00309 break;
00310 case MMSPULSER_SEQ_LINEAR_DESC:
00311 case MMSPULSER_SEQ_LOG_DESC_SOFT_START:
00312 case MMSPULSER_SEQ_LOG_DESC_SOFT_END:
00313 case MMSPULSER_SEQ_LOG_DESC_SOFT_START_AND_END:
00314 this->offset-= this->step_len;
00315 break;
00316 }
00317
00318
00319 calcCurve(this->offset, this->offset_curve);
00320
00321
00322 bool stop = false;
00323 if (this->max_offset > 0) {
00324 if ((this->seq_mode == MMSPULSER_SEQ_LINEAR)
00325 ||(this->seq_mode == MMSPULSER_SEQ_LOG_SOFT_START)
00326 ||(this->seq_mode == MMSPULSER_SEQ_LOG_SOFT_END)
00327 ||(this->seq_mode == MMSPULSER_SEQ_LOG_SOFT_START_AND_END)) {
00328
00329 if (this->offset_curve > 0) {
00330 if (this->offset_curve >= this->max_offset) {
00331
00332 stop = true;
00333 }
00334 }
00335 else {
00336 if (this->offset >= this->max_offset) {
00337
00338 stop = true;
00339 }
00340 }
00341 }
00342 else {
00343
00344 if (this->offset_curve != 0) {
00345 if (this->offset_curve < 0) {
00346
00347 stop = true;
00348 }
00349 }
00350 else {
00351 if (this->offset < 0) {
00352
00353 stop = true;
00354 }
00355 }
00356 }
00357 }
00358
00359
00360 if ((this->duration) && (this->real_duration > this->duration)) {
00361
00362 stop = true;
00363 }
00364
00365
00366 this->anim_end = getMTimeStamp();
00367 this->real_duration = getMDiff(this->anim_start, this->anim_end);
00368
00369 if (stop) {
00370
00371 break;
00372 }
00373 }
00374
00375
00376 this->onAfterAnimation.emit(this);
00377 }
00378
00379 bool MMSPulser::start(bool separate_thread, bool wait) {
00380
00381 this->startlock.lock();
00382 while (isRunning()) {
00383 if (wait) {
00384 usleep(10000);
00385 }
00386 else {
00387 this->startlock.unlock();
00388 return false;
00389 }
00390 }
00391
00392
00393 reset();
00394
00395 if (separate_thread) {
00396
00397 bool ret = MMSThread::start();
00398 this->startlock.unlock();
00399 return ret;
00400 }
00401 else {
00402
00403 this->animRunning = true;
00404 this->startlock.unlock();
00405
00406 try {
00407
00408
00409 threadMain();
00410
00411 } catch(MMSError &error) {
00412 DEBUGMSG(this->identity.c_str(), "Abort due to: " + error.getMessage());
00413 }
00414
00415 this->animRunning = false;
00416 }
00417
00418 return true;
00419 }
00420
00421 bool MMSPulser::isRunning() {
00422 if (MMSThread::isRunning()) {
00423
00424 return true;
00425 }
00426 else {
00427
00428 return this->animRunning;
00429 }
00430 }
00431
00432 void MMSPulser::stop() {
00433 this->startlock.lock();
00434 this->cancel = true;
00435 this->startlock.unlock();
00436 }
00437
00438 bool MMSPulser::setStepsPerSecond(int steps_per_second) {
00439
00440 if (steps_per_second <= 0) return false;
00441 if (steps_per_second > 255) return false;
00442 this->steps_per_second = steps_per_second;
00443
00444
00445 recalc_cnt = 0;
00446 recalc_requested = true;
00447
00448 return true;
00449 }
00450
00451 int MMSPulser::getStepsPerSecond() {
00452 return this->steps_per_second;
00453 }
00454
00455 bool MMSPulser::setMaxCPUUsage(int max_cpu_usage) {
00456
00457 if (max_cpu_usage < 10) return false;
00458 if (max_cpu_usage > 100) return false;
00459 this->max_cpu_usage = max_cpu_usage;
00460
00461
00462 recalc_cnt = 0;
00463 recalc_requested = true;
00464
00465 return true;
00466 }
00467
00468 int MMSPulser::getMaxCPUUsage() {
00469 return this->max_cpu_usage;
00470 }
00471
00472 bool MMSPulser::setMaxFrameRate(int max_frame_rate) {
00473
00474 if (max_frame_rate < 10) return false;
00475 if (max_frame_rate > 100) return false;
00476 this->max_frame_rate = max_frame_rate;
00477
00478
00479 recalc_cnt = 0;
00480 recalc_requested = true;
00481
00482 return true;
00483 }
00484
00485 int MMSPulser::getMaxFrameRate() {
00486 return this->max_frame_rate;
00487 }
00488
00489 int MMSPulser::getFrameRate() {
00490 return this->frame_rate;
00491 }
00492
00493 int MMSPulser::getFrameDelay() {
00494 return this->frame_delay;
00495 }
00496
00497 unsigned int MMSPulser::getFrames() {
00498 return this->frames;
00499 }
00500
00501 int MMSPulser::getStepLength() {
00502 return this->step_len;
00503 }
00504
00505 bool MMSPulser::setMaxOffset(double max_offset, MMSPULSER_SEQ seq_mode, double seq_range) {
00506
00507 if ((max_offset < 2)&&(max_offset != 0)) return false;
00508 if ((seq_range < 2)&&(seq_range != 0)) return false;
00509 if (seq_range > max_offset) return false;
00510 this->max_offset = max_offset;
00511 this->seq_mode = seq_mode;
00512 this->seq_range = seq_range;
00513
00514
00515 if (this->seq_range <= 0) {
00516
00517 switch (this->seq_mode) {
00518 case MMSPULSER_SEQ_LINEAR:
00519 case MMSPULSER_SEQ_LOG_SOFT_START:
00520 case MMSPULSER_SEQ_LOG_SOFT_END:
00521 this->seq_start = 0;
00522 this->seq_range = this->max_offset;
00523 break;
00524 case MMSPULSER_SEQ_LOG_SOFT_START_AND_END:
00525 this->seq_start = 0;
00526 this->seq_range = this->max_offset / 2;
00527 break;
00528 case MMSPULSER_SEQ_LINEAR_DESC:
00529 case MMSPULSER_SEQ_LOG_DESC_SOFT_START:
00530 case MMSPULSER_SEQ_LOG_DESC_SOFT_END:
00531 this->seq_start = this->max_offset;
00532 this->seq_range = this->max_offset;
00533 break;
00534 case MMSPULSER_SEQ_LOG_DESC_SOFT_START_AND_END:
00535 this->seq_start = this->max_offset;
00536 this->seq_range = this->max_offset / 2;
00537 break;
00538 }
00539 }
00540 else {
00541
00542 switch (this->seq_mode) {
00543 case MMSPULSER_SEQ_LINEAR:
00544 case MMSPULSER_SEQ_LOG_SOFT_END:
00545 this->seq_start = this->max_offset - this->seq_range;
00546 break;
00547 case MMSPULSER_SEQ_LINEAR_DESC:
00548 case MMSPULSER_SEQ_LOG_DESC_SOFT_END:
00549 this->seq_start = this->seq_range;
00550 break;
00551 case MMSPULSER_SEQ_LOG_SOFT_START:
00552 this->seq_start = 0;
00553 break;
00554 case MMSPULSER_SEQ_LOG_SOFT_START_AND_END:
00555 this->seq_start = 0;
00556 this->seq_range/= 2;
00557 break;
00558 case MMSPULSER_SEQ_LOG_DESC_SOFT_START:
00559 this->seq_start = this->max_offset;
00560 break;
00561 case MMSPULSER_SEQ_LOG_DESC_SOFT_START_AND_END:
00562 this->seq_start = this->max_offset;
00563 this->seq_range/= 2;
00564 break;
00565 }
00566 }
00567
00568
00569 if (this->max_offset >= 2) {
00570 this->max_offset_log = log(this->max_offset);
00571 }
00572 else {
00573 this->max_offset_log = 0;
00574 }
00575
00576 return true;
00577 }
00578
00579 double MMSPulser::getOffset() {
00580 return this->offset_curve;
00581 }
00582
00583 bool MMSPulser::setDuration(unsigned int duration) {
00584 this->duration = duration;
00585 return true;
00586 }
00587
00588 unsigned int MMSPulser::getDuration() {
00589 return this->duration;
00590 }
00591
00592 unsigned int MMSPulser::getRealDuration() {
00593 return this->real_duration;
00594 }
00595
00596 unsigned int MMSPulser::getOnAnimationCounter() {
00597 return this->onAnimation_counter;
00598 }