Marsyas
0.6.0-alpha
|
00001 /* 00002 ** Copyright (C) 1998-2011 George Tzanetakis <gtzan@cs.uvic.ca> 00003 ** 00004 ** This program is free software; you can redistribute it and/or modify 00005 ** it under the terms of the GNU General Public License as published by 00006 ** the Free Software Foundation; either version 2 of the License, or 00007 ** (at your option) any later version. 00008 ** 00009 ** This program is distributed in the hope that it will be useful, 00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 ** GNU General Public License for more details. 00013 ** 00014 ** You should have received a copy of the GNU General Public License 00015 ** along with this program; if not, write to the Free Software 00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 */ 00018 00019 #include "../common_source.h" 00020 #include "WavFileSource.h" 00021 00022 00023 using namespace std; 00024 using namespace Marsyas; 00025 00026 WavFileSource::WavFileSource(mrs_string name):AbsSoundFileSource("WavFileSource",name) 00027 { 00028 idata_ = 0; 00029 sdata_ = 0; 00030 cdata_ = 0; 00031 sfp_ = 0; 00032 pos_ = 0; 00033 00034 addControls(); 00035 } 00036 00037 00038 WavFileSource::WavFileSource(const WavFileSource& a): AbsSoundFileSource(a) 00039 { 00040 ctrl_pos_ = getctrl("mrs_natural/pos"); 00041 ctrl_currentlyPlaying_ = getctrl("mrs_string/currentlyPlaying"); 00042 ctrl_previouslyPlaying_ = getctrl("mrs_string/previouslyPlaying"); 00043 ctrl_regression_ = getctrl("mrs_bool/regression"); 00044 ctrl_currentLabel_ = getctrl("mrs_real/currentLabel"); 00045 ctrl_previousLabel_ = getctrl("mrs_real/previousLabel"); 00046 ctrl_labelNames_ = getctrl("mrs_string/labelNames"); 00047 ctrl_nLabels_ = getctrl("mrs_natural/nLabels"); 00048 ctrl_currentHasData_ = getctrl("mrs_bool/currentHasData"); 00049 ctrl_currentLastTickWithData_ = getctrl("mrs_bool/currentLastTickWithData"); 00050 } 00051 00052 00053 00054 WavFileSource::~WavFileSource() 00055 { 00056 delete [] idata_; 00057 delete [] sdata_; 00058 delete [] cdata_; 00059 if (sfp_ != NULL) 00060 fclose(sfp_); 00061 } 00062 00063 MarSystem* 00064 WavFileSource::clone() const 00065 { 00066 return new WavFileSource(*this); 00067 } 00068 00069 void 00070 WavFileSource::addControls() 00071 { 00072 addctrl("mrs_bool/hasData", true); 00073 addctrl("mrs_bool/lastTickWithData", false); 00074 00075 addctrl("mrs_natural/pos", (mrs_natural)0, ctrl_pos_); 00076 setctrlState("mrs_natural/pos", true); 00077 00078 addctrl("mrs_natural/loopPos", (mrs_natural)0); 00079 setctrlState("mrs_natural/pos", true); 00080 00081 addctrl("mrs_natural/size", (mrs_natural)0); 00082 00083 addctrl("mrs_string/filename", "dwavfile"); 00084 setctrlState("mrs_string/filename", true); 00085 00086 addctrl("mrs_string/filetype", "wav"); 00087 00088 addctrl("mrs_real/repetitions", 1.0); 00089 setctrlState("mrs_real/repetitions", true); 00090 00091 addctrl("mrs_real/duration", -1.0); 00092 setctrlState("mrs_real/duration", true); 00093 00094 addctrl("mrs_natural/advance", 0); 00095 setctrlState("mrs_natural/advance", true); 00096 00097 addctrl("mrs_bool/shuffle", false); 00098 setctrlState("mrs_bool/shuffle", true); 00099 00100 addctrl("mrs_natural/cindex", 0); 00101 setctrlState("mrs_natural/cindex", true); 00102 00103 addctrl("mrs_string/allfilenames", ","); 00104 setctrlState("mrs_string/allfilenames", true); 00105 00106 addctrl("mrs_natural/numFiles", 1); 00107 addctrl("mrs_string/currentlyPlaying", "daufile", ctrl_currentlyPlaying_); //"dwavfile" [?] 00108 addctrl("mrs_string/previouslyPlaying", "daufile", ctrl_previouslyPlaying_); //"dwavfile" [?] 00109 00110 addctrl("mrs_bool/regression", false, ctrl_regression_); 00111 addctrl("mrs_real/currentLabel", 0.0, ctrl_currentLabel_); 00112 addctrl("mrs_real/previousLabel", 0.0, ctrl_previousLabel_); 00113 addctrl("mrs_natural/nLabels", 0, ctrl_nLabels_); 00114 addctrl("mrs_string/labelNames", ",", ctrl_labelNames_); 00115 00116 addctrl("mrs_bool/currentHasData", true, ctrl_currentHasData_); 00117 00118 addctrl("mrs_bool/currentLastTickWithData", false, ctrl_currentLastTickWithData_); 00119 00120 } 00121 00122 void 00123 WavFileSource::getHeader(mrs_string filename) 00124 { 00125 00126 if (sfp_ != NULL) 00127 fclose(sfp_); 00128 00129 sfp_ = fopen(filename.c_str(), "rb"); 00130 if (sfp_) 00131 { 00132 char magic[5]; 00133 00134 fseek(sfp_, 8, SEEK_SET); // Locate wave id 00135 if (fread(magic, 4, 1, sfp_) == 0) 00136 { 00137 MRSERR("WavFileSource: File " + filename + " is empty "); 00138 } 00139 magic[4] = '\0'; 00140 00141 if (strcmp(magic, "WAVE")) 00142 { 00143 MRSWARN("Filename " + filename + " is not correct .wav file \n or has settings that are not supported in Marsyas"); 00144 // setctrl("mrs_natural/nChannels", 1); 00145 setctrl("mrs_real/israte", (mrs_real)22050.0); 00146 setctrl("mrs_natural/size", 0); 00147 hasData_ = false; 00148 lastTickWithData_ = true; 00149 setctrl("mrs_bool/hasData", false); 00150 setctrl("mrs_bool/lastTickWithData", true); 00151 00152 } 00153 else 00154 { 00155 char id[5]; 00156 int chunkSize; 00157 if (fread(id, 4, 1, sfp_) != 1) { 00158 MRSERR("Error reading wav file"); 00159 } 00160 id[4] = '\0'; 00161 00162 while (strcmp(id, "fmt ")) 00163 { 00164 if (fread(&chunkSize, 4, 1, sfp_) != 1) { 00165 MRSERR("Error reading wav file"); 00166 } 00167 #if defined(MARSYAS_BIGENDIAN) 00168 chunkSize = ByteSwapLong(chunkSize); 00169 #else 00170 //chunkSize = chunkSize; 00171 #endif 00172 fseek(sfp_, chunkSize, SEEK_CUR); 00173 if (fread(id, 4, 1, sfp_) != 1) { 00174 MRSERR("Error reading wav file"); 00175 } 00176 } 00177 00178 if (fread(&chunkSize, 4, 1, sfp_) != 1) { 00179 MRSERR("Error reading wav file"); 00180 } 00181 #if defined(MARSYAS_BIGENDIAN) 00182 chunkSize = ByteSwapLong(chunkSize); 00183 #else 00184 //chunkSize = chunkSize; 00185 #endif 00186 00187 unsigned short format_tag; 00188 if (fread(&format_tag, 2, 1, sfp_) != 1) { 00189 MRSERR("Error reading wav file"); 00190 } 00191 00192 #if defined(MARSYAS_BIGENDIAN) 00193 format_tag = ByteSwapShort(format_tag); 00194 #else 00195 //format_tag = format_tag; 00196 #endif 00197 00198 if (format_tag != 1) 00199 { 00200 fclose(sfp_); 00201 MRSWARN("Non pcm(compressed) wave files are not supported"); 00202 exit(1); 00203 } 00204 00205 // Get number of channels 00206 unsigned short channels; 00207 if (fread(&channels, 2,1, sfp_) != 1) { 00208 MRSERR("Error reading wav file"); 00209 } 00210 00211 #if defined(MARSYAS_BIGENDIAN) 00212 channels = ByteSwapShort(channels); 00213 #else 00214 //channels = channels; 00215 #endif 00216 00217 setctrl("mrs_natural/onObservations", (mrs_natural)channels); 00218 00219 unsigned int srate; 00220 if (fread(&srate, 4,1,sfp_) != 1) { 00221 MRSERR("Error reading wav file"); 00222 } 00223 00224 #if defined(MARSYAS_BIGENDIAN) 00225 srate = ByteSwapLong(srate); 00226 #else 00227 //srate = srate; 00228 #endif 00229 00230 00231 setctrl("mrs_real/israte", (mrs_real)srate); 00232 setctrl("mrs_real/osrate", (mrs_real)srate); 00233 00234 fseek(sfp_,6,SEEK_CUR); 00235 if (fread(&bits_, 2, 1, sfp_) != 1) { 00236 MRSERR("Error reading wav file"); 00237 } 00238 00239 #if defined(MARSYAS_BIGENDIAN) 00240 bits_ = ByteSwapShort(bits_); 00241 #else 00242 //bits_ = bits_; 00243 #endif 00244 00245 if ((bits_ != 16)&&(bits_ != 8)&&(bits_!=32)) 00246 { 00247 MRSWARN("WavFileSource::Only linear 8-bit, 16-bit, and 32-bit samples are supported "); 00248 } 00249 fseek(sfp_, chunkSize - 16, SEEK_CUR); 00250 00251 if (fread(id, 4, 1, sfp_) != 1) { 00252 MRSERR("Error reading wav file"); 00253 } 00254 id[4] = '\0'; 00255 while (strcmp(id, "data")) 00256 { 00257 if (fread(&chunkSize, 4, 1, sfp_) != 1) { 00258 MRSERR("Error reading wav file"); 00259 } 00260 #if defined(MARSYAS_BIGENDIAN) 00261 chunkSize = ByteSwapLong(chunkSize); 00262 #else 00263 //chunkSize = chunkSize; 00264 #endif 00265 00266 fseek(sfp_,chunkSize,SEEK_CUR); 00267 if (fread(&id,4,1,sfp_) != 1) { 00268 MRSERR("Error reading wav file"); 00269 } 00270 } 00271 00272 int bytes; 00273 if (fread(&bytes, 4, 1, sfp_) != 1) { 00274 MRSERR("Error reading wav file"); 00275 } 00276 00277 #if defined(MARSYAS_BIGENDIAN) 00278 bytes = ByteSwapLong(bytes); 00279 #else 00280 //bytes = bytes; 00281 #endif 00282 00283 //size in number of samples per channel 00284 size_ = bytes / (bits_ / 8)/ (getctrl("mrs_natural/onObservations")->to<mrs_natural>()); 00285 csize_ = size_; 00286 00287 setctrl("mrs_natural/size", size_); 00288 ctrl_currentlyPlaying_->setValue(filename, NOUPDATE); 00289 ctrl_previouslyPlaying_->setValue(filename, NOUPDATE); 00290 ctrl_currentLabel_->setValue((mrs_real)0.0, NOUPDATE); 00291 ctrl_previousLabel_->setValue((mrs_real)0.0, NOUPDATE); 00292 00293 ctrl_labelNames_->setValue(",", NOUPDATE); 00294 ctrl_nLabels_->setValue(0, NOUPDATE); 00295 sfp_begin_ = ftell(sfp_); 00296 hasData_ = true; 00297 lastTickWithData_ = false; 00298 pos_ = 0; 00299 samplesOut_ = 0; 00300 MRSDIAG("WavFileSource: " 00301 << filename 00302 << " has the following properties: "); 00303 mrs_real temprate = getControl("mrs_real/israte")->to<mrs_real>(); 00304 mrs_natural numInSamples = getControl("mrs_natural/inSamples")->to<mrs_natural>(); 00305 MRSDIAG("israte == " << temprate); 00306 MRSDIAG("inSamples == " << numInSamples); 00307 (void) temprate; 00308 (void) numInSamples; // in case the macro is not expanded 00309 00310 } 00311 } 00312 else 00313 { 00314 MRSWARN("couldn't open file: " << filename); 00315 // setctrl("mrs_natural/nChannels", 1); 00316 setctrl("mrs_real/israte", (mrs_real)22050.0); 00317 setctrl("mrs_natural/onObservations", 1); 00318 setctrl("mrs_natural/size", 0); 00319 hasData_ = false; 00320 lastTickWithData_ = true; 00321 setctrl("mrs_bool/hasData", false); 00322 setctrl("mrs_bool/lastTickWithData", true); 00323 pos_ = 0; 00324 } 00325 00326 nChannels_ = getctrl("mrs_natural/onObservations")->to<mrs_natural>(); 00327 } 00328 00329 void 00330 WavFileSource::myUpdate(MarControlPtr sender) 00331 { 00332 (void) sender; //suppress warning of unused parameter(s) 00333 inSamples_ = getctrl("mrs_natural/inSamples")->to<mrs_natural>(); 00334 inObservations_ = getctrl("mrs_natural/inObservations")->to<mrs_natural>(); 00335 israte_ = getctrl("mrs_real/israte")->to<mrs_real>(); 00336 osrate_ = getctrl("mrs_real/osrate")->to<mrs_real>(); 00337 00338 nChannels_ = getctrl("mrs_natural/onObservations")->to<mrs_natural>(); 00339 00340 setctrl("mrs_natural/onSamples", inSamples_); 00341 setctrl("mrs_natural/onObservations", nChannels_); 00342 //setctrl("mrs_real/osrate", osrate_); 00343 //osrate_ = getctrl("mrs_real/osrate")->to<mrs_real>(); 00344 pos_ = getctrl("mrs_natural/pos")->to<mrs_natural>(); 00345 rewindpos_ = getctrl("mrs_natural/loopPos")->to<mrs_natural>(); 00346 00347 delete [] idata_; 00348 delete [] sdata_; 00349 delete [] cdata_; 00350 00351 idata_ = new int[inSamples_ * nChannels_]; 00352 sdata_ = new short[inSamples_ * nChannels_]; 00353 cdata_ = new unsigned char[inSamples_ * nChannels_]; 00354 00355 repetitions_ = getctrl("mrs_real/repetitions")->to<mrs_real>(); 00356 duration_ = getctrl("mrs_real/duration")->to<mrs_real>(); 00357 00358 if (duration_ != -1.0) 00359 { 00360 csize_ = (mrs_natural)(duration_ * israte_); 00361 } 00362 00363 samplesToRead_ = inSamples_ * nChannels_; 00364 MRSDIAG("WavFileSource::myUpdate " 00365 << " has the following properties: "); 00366 mrs_real temprate = getControl("mrs_real/israte")->to<mrs_real>(); 00367 mrs_natural numInSamples = getControl("mrs_natural/inSamples")->to<mrs_natural>(); 00368 MRSDIAG("israte == " << temprate); 00369 MRSDIAG("inSamples == " << numInSamples); 00370 (void) temprate; 00371 (void) numInSamples; // in case the macro is not expanded 00372 00373 } 00374 00375 mrs_natural 00376 WavFileSource::getLinear8(realvec& slice) 00377 { 00378 mrs_natural t; 00379 mrs_natural c = 0; 00380 fseek(sfp_, pos_ * nChannels_ + sfp_begin_, SEEK_SET); 00381 00382 samplesToRead_ = inSamples_ * nChannels_; 00383 samplesRead_ = (mrs_natural)fread(cdata_, sizeof(unsigned char), samplesToRead_, sfp_); 00384 00385 00386 if (samplesRead_ != samplesToRead_) 00387 { 00388 for (c=0; c < nChannels_; ++c) 00389 for (t=0; t < inSamples_; t++) 00390 { 00391 slice(c,t) = 0.0; 00392 } 00393 samplesToWrite_ = samplesRead_ / nChannels_; 00394 } 00395 else 00396 samplesToWrite_ = inSamples_; 00397 00398 for (t=0; t < samplesToWrite_; t++) 00399 { 00400 for (c=0; c < nChannels_; ++c) 00401 { 00402 slice(c, t) = (mrs_real)-1.0 + (mrs_real) cdata_[nChannels_ * t + c] / 127; 00403 } 00404 } 00405 00406 pos_ += samplesToWrite_; 00407 return pos_; 00408 } 00409 00410 // oh dear. "long" here means 32 bits 00411 unsigned long 00412 WavFileSource::ByteSwapLong(unsigned long nLongNumber) 00413 { 00414 return (((nLongNumber&0x000000FF)<<24)+((nLongNumber&0x0000FF00)<<8)+ 00415 ((nLongNumber&0x00FF0000)>>8)+((nLongNumber&0xFF000000)>>24)); 00416 } 00417 00418 unsigned int 00419 WavFileSource::ByteSwapInt(unsigned int nInt) 00420 { 00421 return (((nInt&0x000000FF)<<24)+((nInt&0x0000FF00)<<8)+ 00422 ((nInt&0x00FF0000)>>8)+((nInt&0xFF000000)>>24)); 00423 } 00424 00425 00426 unsigned short 00427 WavFileSource::ByteSwapShort (unsigned short nValue) 00428 { 00429 return (static_cast<unsigned short>((nValue & 0xff00) >> 8) | 00430 static_cast<unsigned short>((nValue & 0xff) << 8)); 00431 } 00432 00433 mrs_natural 00434 WavFileSource::getLinear32(realvec& slice) 00435 { 00436 mrs_natural c,t; 00437 00438 fseek(sfp_, 4 * pos_ * nChannels_ + sfp_begin_, SEEK_SET); 00439 samplesRead_ = (mrs_natural)fread(idata_, sizeof(int), samplesToRead_, sfp_); 00440 00441 // pad with zeros if necessary 00442 if ((samplesRead_ != samplesToRead_)&&(samplesRead_ != 0)) 00443 { 00444 for (c=0; c < nChannels_; ++c) 00445 for (t=0; t < inSamples_; t++) 00446 slice(c, t) = 0.0; 00447 samplesToWrite_ = samplesRead_ / nChannels_; 00448 } 00449 else // default case - read enough samples or no samples in which case zero output 00450 { 00451 samplesToWrite_ = inSamples_; 00452 00453 // if there are no more samples output zeros 00454 if (samplesRead_ == 0) 00455 for (t=0; t < inSamples_; t++) 00456 { 00457 nt_ = nChannels_ * t; 00458 for (c=0; c < nChannels_; ++c) 00459 { 00460 idata_[nt_ + c] = 0; 00461 } 00462 } 00463 } 00464 00465 // write the read samples to output slice once for each channel 00466 for (t=0; t < samplesToWrite_; t++) 00467 { 00468 ival_ = 0; 00469 nt_ = nChannels_ * t; 00470 #if defined(MARSYAS_BIGENDIAN) 00471 for (c=0; c < nChannels_; ++c) 00472 { 00473 // oh dear. "long" here means 32 bits 00474 ival_ = ByteSwapInt(idata_[nt_ + c]); 00475 slice(c, t) = (mrs_real) ival_ / (PCM_FMAXINT + 1); 00476 } 00477 #else 00478 for (c=0; c < nChannels_; ++c) 00479 { 00480 ival_ = idata_[nt_ + c]; 00481 slice(c, t) = ((mrs_real) ival_ / (PCM_FMAXINT + 1)); 00482 } 00483 #endif 00484 } 00485 00486 pos_ += samplesToWrite_; 00487 return pos_; 00488 } 00489 00490 00491 mrs_natural 00492 WavFileSource::getLinear16(realvec& slice) 00493 { 00494 mrs_natural c,t; 00495 00496 fseek(sfp_, 2 * pos_ * nChannels_ + sfp_begin_, SEEK_SET); 00497 samplesRead_ = (mrs_natural)fread(sdata_, sizeof(short), samplesToRead_, sfp_); 00498 00499 // pad with zeros if necessary 00500 if ((samplesRead_ != samplesToRead_)&&(samplesRead_ != 0)) 00501 { 00502 for (c=0; c < nChannels_; ++c) 00503 for (t=0; t < inSamples_; t++) 00504 slice(c, t) = 0.0; 00505 samplesToWrite_ = samplesRead_ / nChannels_; 00506 } 00507 else // default case - read enough samples or no samples in which case zero output 00508 { 00509 samplesToWrite_ = inSamples_; 00510 00511 // if there are no more samples output zeros 00512 if (samplesRead_ == 0) 00513 for (t=0; t < inSamples_; t++) 00514 { 00515 nt_ = nChannels_ * t; 00516 for (c=0; c < nChannels_; ++c) 00517 { 00518 sdata_[nt_ + c] = 0; 00519 } 00520 } 00521 } 00522 00523 // write the read samples to output slice once for each channel 00524 for (t=0; t < samplesToWrite_; t++) 00525 { 00526 sval_ = 0; 00527 nt_ = nChannels_ * t; 00528 #if defined(MARSYAS_BIGENDIAN) 00529 for (c=0; c < nChannels_; ++c) 00530 { 00531 sval_ = ByteSwapShort(sdata_[nt_ + c]); 00532 slice(c, t) = (mrs_real) sval_ / (PCM_FMAXSHRT + 1); 00533 } 00534 #else 00535 for (c=0; c < nChannels_; ++c) 00536 { 00537 sval_ = sdata_[nt_ + c]; 00538 slice(c, t) = ((mrs_real) sval_ / (PCM_FMAXSHRT + 1)); 00539 } 00540 #endif 00541 } 00542 00543 pos_ += samplesToWrite_; 00544 return pos_; 00545 } 00546 00547 void 00548 WavFileSource::myProcess(realvec& in, realvec& out) 00549 { 00550 (void) in; 00551 switch(bits_) 00552 { 00553 case 32: 00554 { 00555 getLinear32(out); 00556 ctrl_pos_->setValue(pos_, NOUPDATE); 00557 00558 if (pos_ >= rewindpos_ + csize_) 00559 { 00560 if (repetitions_ != 1) 00561 pos_ = rewindpos_; 00562 } 00563 samplesOut_ += onSamples_; 00564 00565 if (repetitions_ != 1) 00566 { 00567 hasData_ = (samplesOut_ < repetitions_ * csize_); 00568 00569 lastTickWithData_ = ((samplesOut_ + onSamples_>= repetitions_ * csize_) && hasData_); 00570 } 00571 00572 else 00573 { 00574 hasData_ = pos_ < rewindpos_ + csize_; 00575 lastTickWithData_ = ((pos_ + onSamples_ >= rewindpos_ + csize_) && hasData_); 00576 } 00577 00578 if (repetitions_ == -1) 00579 { 00580 hasData_ = true; 00581 lastTickWithData_ = false; 00582 } 00583 break; 00584 } 00585 case 16: 00586 { 00587 getLinear16(out); 00588 ctrl_pos_->setValue(pos_, NOUPDATE); 00589 00590 if (pos_ >= rewindpos_ + csize_) 00591 { 00592 if (repetitions_ != 1) 00593 pos_ = rewindpos_; 00594 } 00595 samplesOut_ += onSamples_; 00596 00597 if (repetitions_ != 1) 00598 { 00599 hasData_ = (samplesOut_ < repetitions_ * csize_); 00600 00601 lastTickWithData_ = ((samplesOut_ + onSamples_>= repetitions_ * csize_) && hasData_); 00602 } 00603 00604 else 00605 { 00606 hasData_ = pos_ < rewindpos_ + csize_; 00607 lastTickWithData_ = ((pos_ + onSamples_ >= rewindpos_ + csize_) && hasData_); 00608 } 00609 00610 if (repetitions_ == -1) 00611 { 00612 hasData_ = true; 00613 lastTickWithData_ = false; 00614 } 00615 break; 00616 } 00617 case 8: 00618 { 00619 getLinear8(out); 00620 ctrl_pos_->setValue(pos_, NOUPDATE); 00621 00622 if (pos_ >= rewindpos_ + csize_) 00623 { 00624 if (repetitions_ != 1) 00625 pos_ = rewindpos_; 00626 } 00627 samplesOut_ += onSamples_; 00628 00629 if (repetitions_ != 1) 00630 { 00631 hasData_ = (samplesOut_ < repetitions_ * csize_); 00632 lastTickWithData_ = ((samplesOut_ + onSamples_ >= repetitions_ * csize_) && hasData_); 00633 } 00634 else 00635 { 00636 hasData_ = pos_ < rewindpos_ + csize_; 00637 lastTickWithData_ = ((pos_ + onSamples_ >= rewindpos_ + csize_) && hasData_); 00638 } 00639 00640 if (repetitions_ == -1) 00641 { 00642 hasData_ = true; 00643 lastTickWithData_ = false; 00644 } 00645 break; 00646 00647 00648 } 00649 } 00650 ctrl_currentHasData_->setValue(hasData_); 00651 00652 ctrl_currentLastTickWithData_->setValue(lastTickWithData_); 00653 }