00001 /*************************************************************************** 00002 * Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider, * 00003 * Matthias Hardt, Guido Madaus * 00004 * * 00005 * Copyright (C) 2007-2008 BerLinux Solutions GbR * 00006 * Stefan Schwarzer & Guido Madaus * 00007 * * 00008 * Copyright (C) 2009-2013 BerLinux Solutions GmbH * 00009 * * 00010 * Authors: * 00011 * Stefan Schwarzer <stefan.schwarzer@diskohq.org>, * 00012 * Matthias Hardt <matthias.hardt@diskohq.org>, * 00013 * Jens Schneider <jens.schneider@diskohq.org>, * 00014 * Guido Madaus <guido.madaus@diskohq.org>, * 00015 * Patrick Helterhoff <patrick.helterhoff@diskohq.org>, * 00016 * René Bählkow <rene.baehlkow@diskohq.org> * 00017 * * 00018 * This library is free software; you can redistribute it and/or * 00019 * modify it under the terms of the GNU Lesser General Public * 00020 * License version 2.1 as published by the Free Software Foundation. * 00021 * * 00022 * This library is distributed in the hope that it will be useful, * 00023 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00025 * Lesser General Public License for more details. * 00026 * * 00027 * You should have received a copy of the GNU Lesser General Public * 00028 * License along with this library; if not, write to the * 00029 * Free Software Foundation, Inc., * 00030 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 00031 **************************************************************************/ 00032 00033 #ifndef MMSPULSER_H_ 00034 #define MMSPULSER_H_ 00035 00036 #include "mmstools/mmsthread.h" 00037 #include "mmstools/mmstypes.h" 00038 00039 // size of the times buffer needed for calculation of the CPU average 00040 #define MMSPULSER_TIMES_BUF_SIZE 10 00041 00042 //! Sequence mode for onAnimation callback. 00043 /*! 00044 Per default the sequence mode is set to MMSPULSER_OFFSET_LINEAR. 00045 You can change this mode with the setMaxOffset() method. This has effect to 00046 the return value of getOffset() which you should use in the onAnimation callback. 00047 \see setMaxOffset() 00048 \see getOffset() 00049 */ 00050 typedef enum { 00051 //! linear ascending 00052 MMSPULSER_SEQ_LINEAR = 0, 00053 //! linear descending 00054 MMSPULSER_SEQ_LINEAR_DESC, 00055 //! logarithmic ascending, animation starts smoothly and ends fast 00056 MMSPULSER_SEQ_LOG_SOFT_START, 00057 //! logarithmic descending, animation starts smoothly and ends fast 00058 MMSPULSER_SEQ_LOG_DESC_SOFT_START, 00059 //! logarithmic ascending, animation starts fast and ends smoothly 00060 MMSPULSER_SEQ_LOG_SOFT_END, 00061 //! logarithmic descending, animation starts fast and ends smoothly 00062 MMSPULSER_SEQ_LOG_DESC_SOFT_END, 00063 //! logarithmic ascending, animation starts smoothly and ends smoothly 00064 MMSPULSER_SEQ_LOG_SOFT_START_AND_END, 00065 //! logarithmic descending, animation starts smoothly and ends smoothly 00066 MMSPULSER_SEQ_LOG_DESC_SOFT_START_AND_END 00067 } MMSPULSER_SEQ; 00068 00069 00070 00071 //! This class helps the MMSGUI and user specific applications to get smooth animations. 00072 /*! 00073 There are three callbacks: onBeforeAnimation, onAnimation and onAfterAnimation. 00074 At least the onAnimation callback should be connected. This callback will be called 00075 for each frame which is to draw. 00076 The onBeforeAnimation callback can be used to setup something. 00077 The onAfterAnimation callback will be called, if the animation is finished. 00078 The initiator can be blocked during the animation (see start(false)). But it is also 00079 possible that the animation is running in a separate thread (see start(true)). 00080 \author Jens Schneider 00081 */ 00082 class MMSPulser : public MMSThread { 00083 private: 00084 //! helper mutex to perform a safe start 00085 MMSMutex startlock; 00086 00087 //! shows if the animation is running 00088 bool animRunning; 00089 00090 //! true if animation thread should stop 00091 bool cancel; 00092 00093 //! recalculation requested? 00094 bool recalc_requested; 00095 00096 //! after X loops, recalculate animation values 00097 int recalc_interval; 00098 00099 //! recalc loop counter 00100 int recalc_cnt; 00101 00102 //! current step length 00103 int step_len; 00104 00105 //! maximum offset 00106 double max_offset; 00107 00108 //! natural logarithm of max_offset 00109 double max_offset_log; 00110 00111 //! sequence mode, used in conjunction with max_offset 00112 MMSPULSER_SEQ seq_mode; 00113 00114 //! sequence range, used in conjunction with max_offset and seq_mode; 00115 double seq_range; 00116 00117 //! sequence start, used in conjunction with seq_range; 00118 double seq_start; 00119 00120 //! current offset 00121 double offset; 00122 00123 //! current offset, curve calculation in conjunction with seq_mode 00124 double offset_curve; 00125 00126 //! animation steps per second 00127 int steps_per_second; 00128 00129 //! maximum cpu usage in percent 00130 int max_cpu_usage; 00131 00132 //! duration of the onAnimation callback 00133 int process_time; 00134 00135 //! delay in milliseconds between two frames 00136 int frame_delay; 00137 00138 //! maximum frame rate 00139 int max_frame_rate; 00140 00141 //! current frame rate 00142 int frame_rate; 00143 00144 //! frame counter 00145 unsigned int frames; 00146 00147 //! ring buffer to calculate the CPU average 00148 unsigned int times_buf[MMSPULSER_TIMES_BUF_SIZE]; 00149 00150 //! next pos in the ring buffer to write to 00151 unsigned int times_buf_pos; 00152 00153 //! filling level of the ring buffer 00154 unsigned int times_buf_cnt; 00155 00156 //! start timestamp of the animation 00157 unsigned int anim_start; 00158 00159 //! end timestamp of the animation 00160 unsigned int anim_end; 00161 00162 //! requested duration in milliseconds of the animation 00163 unsigned int duration; 00164 00165 //! real duration in milliseconds of the animation (calculated after the animation) 00166 unsigned int real_duration; 00167 00168 //! counts the onAnimation calls, zero for the first onAnimation call 00169 unsigned int onAnimation_counter; 00170 00171 //! Internal method: Reset all values. 00172 void reset(); 00173 00174 //! Internal method: Calculate the offset curve. 00175 void calcCurve(double &offset, double &offset_curve); 00176 00177 //! Internal method: Main method for the animation timing control. 00178 void threadMain(); 00179 00180 public: 00181 //! The constructor. 00182 MMSPulser(); 00183 00184 //! The destructor. 00185 ~MMSPulser(); 00186 00187 //! Start the animation. 00188 /*! 00189 \param separate_thread true: a new thread will be started, 00190 false: the animation is running in callers thread context 00191 and the start() method will return if the animation is finished 00192 \param wait waiting for end of animation and then start the new one 00193 \return true or false 00194 */ 00195 bool start(bool separate_thread = true, bool wait = false); 00196 00197 //! Check if the animation is running. 00198 /*! 00199 \return true or false 00200 */ 00201 bool isRunning(); 00202 00203 //! Signals the animation thread that it has to stop immediately. 00204 void stop(); 00205 00206 //! Set animation steps per second. 00207 /*! 00208 \param steps_per_second 1..255 steps per second, default are 25 steps 00209 \return true, if parameter is accepted 00210 \see getStepsPerSecond() 00211 */ 00212 bool setStepsPerSecond(int steps_per_second); 00213 00214 //! Get steps per second. 00215 /*! 00216 \return steps per second 00217 \see setStepsPerSecond() 00218 */ 00219 int getStepsPerSecond(); 00220 00221 //! Set maximum CPU usage. 00222 /*! 00223 \param max_cpu_usage 10..100 percent, default is 100% 00224 \return true, if parameter is accepted 00225 \see getMaxCPUUsage() 00226 */ 00227 bool setMaxCPUUsage(int max_cpu_usage); 00228 00229 //! Get maximum CPU usage. 00230 /*! 00231 \return max CPU usage 00232 \see setMaxCPUUsage() 00233 */ 00234 int getMaxCPUUsage(); 00235 00236 //! Set maximum frame rate. 00237 /*! 00238 \param max_frame_rate 10..100 frames per second, default are 25 fps 00239 \return true, if parameter is accepted 00240 \see getMaxFrameRate() 00241 */ 00242 bool setMaxFrameRate(int max_frame_rate); 00243 00244 //! Get maximum frame rate. 00245 /*! 00246 \return max frame rate 00247 \see setMaxFrameRate() 00248 */ 00249 int getMaxFrameRate(); 00250 00251 //! Get the current frame rate. 00252 /*! 00253 \return current frame rate 00254 \note This value is valid during the animation (e.g. in the onAnimation callback). 00255 */ 00256 int getFrameRate(); 00257 00258 //! Get the delay in milliseconds between two frames. 00259 /*! 00260 \return delay in milliseconds 00261 \note This value is valid during the animation (e.g. in the onAnimation callback). 00262 */ 00263 int getFrameDelay(); 00264 00265 //! Get the frame counter. 00266 /*! 00267 \return frame counter 00268 \note This value is zero for the first time onAnimation callback is called. 00269 */ 00270 unsigned int getFrames(); 00271 00272 //! Get the length of the current animation step. 00273 /*! 00274 \return length of the step 00275 \note This value is valid during the animation (e.g. in the onAnimation callback). 00276 \note This value is zero for the first time onAnimation callback is called. 00277 \see getOffset() 00278 */ 00279 int getStepLength(); 00280 00281 //! Set the maximum offset returned by getOffset(). 00282 /*! 00283 The animation will be stopped, if the maximum offset is exceeded. 00284 Additionally you can set the sequence mode and a sequence range. With these parameters 00285 you have influence to the return value of getOffset(). 00286 \param max_offset maximum offset (2..n), default 0 means that no maximum is set 00287 if maximum offset is not set (value 0), the seq_mode and seq_range will be ignored 00288 \param seq_mode sequence mode, default is MMSPULSER_SEQ_LINEAR 00289 \param seq_range the seq_range for the curve calculation (2..max_offset), default 0 is equal to max_offset 00290 \return true, if parameters are accepted 00291 \note If your onAnimation callback returns false, the Animation will be stopped at any time. 00292 \note The seq_mode has NO influence to the return value of getStepLength(). 00293 \note With the parameter seq_range, you can get a flat curve at the end of the animation. 00294 \see getOffset() 00295 */ 00296 bool setMaxOffset(double max_offset = 0, MMSPULSER_SEQ seq_mode = MMSPULSER_SEQ_LINEAR, 00297 double seq_range = 0); 00298 00299 //! Get the offset of the animation. 00300 /*! 00301 After each onAnimation call the offset will be increased or decreased dependent on 00302 the seq_mode set with setMaxOffset(). 00303 \return offset 00304 \note This value is valid during the animation (e.g. in the onAnimation callback). 00305 \see setMaxOffset() 00306 \see getStepLength() 00307 */ 00308 double getOffset(); 00309 00310 //! Set the requested duration. 00311 /*! 00312 \param duration 0..n milliseconds, default is 0 and means endless animation 00313 \return true, if parameter is accepted 00314 \note If your onAnimation callback returns false, the Animation will be stopped at any time. 00315 \see getDuration() 00316 */ 00317 bool setDuration(unsigned int duration); 00318 00319 //! Get the requested duration in milliseconds of the animation. 00320 /*! 00321 \return requested duration in milliseconds 00322 \see setDuration() 00323 */ 00324 unsigned int getDuration(); 00325 00326 //! Get the real duration in milliseconds of the animation. 00327 /*! 00328 \return real duration in milliseconds 00329 \note This value will be increased during the animation and has its final state at the 00330 end of the animation (e.g. in onAfterAnimation callback). 00331 */ 00332 unsigned int getRealDuration(); 00333 00334 //! Get the number of onAnimation calls after the last onBeforeAnimation call. 00335 /*! 00336 \return number of calls 00337 \note This value is zero for the first time onAnimation is called. 00338 */ 00339 unsigned int getOnAnimationCounter(); 00340 00341 //! Set one or more callbacks for the onBeforeAnimation event. 00342 /*! 00343 The connected callbacks will be called during threadMain(). 00344 If at least one of the callbacks returns false, the animation will be stopped. 00345 00346 A callback method must be defined like this: 00347 00348 bool myclass::mycallbackmethod(MMSPulser *pulser); 00349 00350 \param pulser is the pointer to the caller (the pulser thread) 00351 00352 \return true if the animation should continue, else false if the animation should stop 00353 00354 To connect your callback to onBeforeAnimation do this: 00355 00356 sigc::connection connection; 00357 connection = mypulser->onBeforeAnimation.connect(sigc::mem_fun(myobject,&myclass::mycallbackmethod)); 00358 00359 To disconnect your callback do this: 00360 00361 connection.disconnect(); 00362 00363 Please note: 00364 00365 You HAVE TO disconnect myobject from onBeforeAnimation BEFORE myobject will be deleted!!! 00366 Else an abnormal program termination can occur. 00367 You HAVE TO call the disconnect() method of sigc::connection explicitly. The destructor will NOT do this!!! 00368 */ 00369 sigc::signal<bool, MMSPulser*>::accumulated<bool_accumulator> onBeforeAnimation; 00370 00371 //! Set one or more callbacks for the onAnimation event. 00372 /*! 00373 The connected callbacks will be called during threadMain(). 00374 If at least one of the callbacks returns false, the animation will be stopped. 00375 00376 A callback method must be defined like this: 00377 00378 bool myclass::mycallbackmethod(MMSPulser *pulser); 00379 00380 \param pulser is the pointer to the caller (the pulser thread) 00381 00382 \return true if the animation should continue, else false if the animation should stop 00383 00384 To connect your callback to onAnimation do this: 00385 00386 sigc::connection connection; 00387 connection = mypulser->onAnimation.connect(sigc::mem_fun(myobject,&myclass::mycallbackmethod)); 00388 00389 To disconnect your callback do this: 00390 00391 connection.disconnect(); 00392 00393 Please note: 00394 00395 You HAVE TO disconnect myobject from onAnimation BEFORE myobject will be deleted!!! 00396 Else an abnormal program termination can occur. 00397 You HAVE TO call the disconnect() method of sigc::connection explicitly. The destructor will NOT do this!!! 00398 */ 00399 sigc::signal<bool, MMSPulser*>::accumulated<bool_accumulator> onAnimation; 00400 00401 //! Set one or more callbacks for the onAfterAnimation event. 00402 /*! 00403 The connected callbacks will be called during threadMain(). 00404 00405 A callback method must be defined like this: 00406 00407 void myclass::mycallbackmethod(MMSPulser *pulser); 00408 00409 \param pulser is the pointer to the caller (the pulser thread) 00410 00411 To connect your callback to onAfterAnimation do this: 00412 00413 sigc::connection connection; 00414 connection = mypulser->onAfterAnimation.connect(sigc::mem_fun(myobject,&myclass::mycallbackmethod)); 00415 00416 To disconnect your callback do this: 00417 00418 connection.disconnect(); 00419 00420 Please note: 00421 00422 You HAVE TO disconnect myobject from onAfterAnimation BEFORE myobject will be deleted!!! 00423 Else an abnormal program termination can occur. 00424 You HAVE TO call the disconnect() method of sigc::connection explicitly. The destructor will NOT do this!!! 00425 */ 00426 sigc::signal<void, MMSPulser*> onAfterAnimation; 00427 }; 00428 00429 #endif /*MMSPULSER_H_*/