1 /* 2 MIDI Sequencer C++ library 3 Copyright (C) 2006-2021, Pedro Lopez-Cabanillas <plcl@users.sf.net> 4 5 This library is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #ifndef DRUMSTICK_ALSATIMER_H 20 #define DRUMSTICK_ALSATIMER_H 21 22 extern "C" { 23 #include <alsa/asoundlib.h> 24 } 25 26 #include <QObject> 27 #include <QList> 28 #include <QThread> 29 #include <QReadWriteLock> 30 #include <QPointer> 31 #include "macros.h" 32 33 namespace drumstick { namespace ALSA { 34 35 /** 36 * @file alsatimer.h 37 * Classes managing ALSA Timers 38 */ 39 40 class TimerQuery; 41 class TimerId; 42 class TimerGlobalInfo; 43 44 /** 45 * @addtogroup ALSATimer ALSA Timers 46 * @{ 47 * 48 * @class TimerInfo 49 * ALSA Timer information container. 50 * 51 * This class is used to hold properties about ALSA Timers. 52 */ 53 class DRUMSTICK_EXPORT TimerInfo 54 { 55 friend class Timer; 56 57 public: 58 TimerInfo(); 59 TimerInfo(const TimerInfo& other); 60 explicit TimerInfo(const snd_timer_info_t* other); 61 virtual ~TimerInfo(); 62 TimerInfo* clone(); 63 TimerInfo& operator=(const TimerInfo& other); 64 int getSizeOfInfo() const; 65 66 bool isSlave(); 67 int getCard(); 68 QString getId(); 69 QString getName(); 70 long getResolution(); 71 long getFrequency(); 72 73 protected: 74 Q_DECL_DEPRECATED long getTicks(); 75 76 private: 77 snd_timer_info_t *m_Info; 78 }; 79 80 /** 81 * ALSA Timer identifier container. 82 * 83 * This class provides an unique identifier for a Timer. 84 */ 85 class DRUMSTICK_EXPORT TimerId 86 { 87 friend class TimerQuery; 88 friend class TimerGlobalInfo; 89 friend class QueueTimer; 90 91 public: 92 TimerId(); 93 TimerId(const TimerId& other); 94 explicit TimerId(const snd_timer_id_t *other); 95 TimerId(int cls, int scls, int card, int dev, int sdev); 96 virtual ~TimerId(); 97 TimerId* clone(); 98 TimerId& operator=(const TimerId& other); 99 int getSizeOfInfo() const; 100 101 void setClass(int devclass); 102 int getClass(); 103 void setSlaveClass(int devsclass); 104 int getSlaveClass(); 105 void setCard(int card); 106 int getCard(); 107 void setDevice(int device); 108 int getDevice(); 109 void setSubdevice(int subdevice); 110 int getSubdevice(); 111 112 private: 113 snd_timer_id_t *m_Info; 114 }; 115 116 /** 117 * List of timer identifiers 118 */ 119 typedef QList<TimerId> TimerIdList; 120 121 /** 122 * Global timer information container. 123 * 124 * This class provides global timer parameters. 125 */ 126 class DRUMSTICK_EXPORT TimerGlobalInfo 127 { 128 friend class TimerQuery; 129 130 public: 131 TimerGlobalInfo(); 132 TimerGlobalInfo(const TimerGlobalInfo& other); 133 explicit TimerGlobalInfo(const snd_timer_ginfo_t* other); 134 virtual ~TimerGlobalInfo(); 135 TimerGlobalInfo* clone(); 136 TimerGlobalInfo& operator=(const TimerGlobalInfo& other); 137 int getSizeOfInfo() const; 138 139 void setTimerId(const TimerId& tid); 140 TimerId& getTimerId(); 141 unsigned int getFlags(); 142 int getCard(); 143 QString getId(); 144 QString getName(); 145 unsigned long getResolution(); 146 unsigned long getMinResolution(); 147 unsigned long getMaxResolution(); 148 unsigned int getClients(); 149 150 private: 151 snd_timer_ginfo_t* m_Info; 152 TimerId m_Id; 153 }; 154 155 /** 156 * ALSA Timer inquiry helper. 157 * 158 * This class provides a mechanism to enumerate the available system timers. 159 */ 160 class DRUMSTICK_EXPORT TimerQuery 161 { 162 public: 163 TimerQuery(const QString& deviceName, int openMode); 164 TimerQuery(const QString& deviceName, int openMode, snd_config_t* conf); 165 virtual ~TimerQuery(); 166 /** 167 * Gets the list of available timers 168 * @return List of TimerId objects 169 */ getTimers()170 TimerIdList getTimers() const { return m_timers; } 171 TimerGlobalInfo& getGlobalInfo(); 172 void setGlobalParams(snd_timer_gparams_t* params); 173 void getGlobalParams(snd_timer_gparams_t* params); 174 void getGlobalStatus(snd_timer_gstatus_t* status); 175 176 protected: 177 void readTimers(); 178 void freeTimers(); 179 180 private: 181 snd_timer_query_t *m_Info; 182 TimerIdList m_timers; 183 TimerGlobalInfo m_GlobalInfo; 184 }; 185 186 /** 187 * ALSA Timer parameters container. 188 * 189 * This class provides several parameters about a Timer. 190 */ 191 class DRUMSTICK_EXPORT TimerParams 192 { 193 friend class Timer; 194 195 public: 196 TimerParams(); 197 TimerParams(const TimerParams& other); 198 explicit TimerParams(const snd_timer_params_t* other); 199 virtual ~TimerParams(); 200 TimerParams* clone(); 201 TimerParams& operator=(const TimerParams& other); 202 int getSizeOfInfo() const; 203 204 void setAutoStart(bool auto_start); 205 bool getAutoStart(); 206 void setExclusive(bool exclusive); 207 bool getExclusive(); 208 void setEarlyEvent(bool early_event); 209 bool getEarlyEvent(); 210 void setTicks(long ticks); 211 long getTicks(); 212 void setQueueSize(long queue_size); 213 long getQueueSize(); 214 void setFilter(unsigned int filter); 215 unsigned int getFilter(); 216 217 private: 218 snd_timer_params_t* m_Info; 219 }; 220 221 /** 222 * ALSA Timer status container. 223 * 224 * This class provides some status information about a Timer. 225 */ 226 class DRUMSTICK_EXPORT TimerStatus 227 { 228 friend class Timer; 229 230 public: 231 TimerStatus(); 232 TimerStatus(const TimerStatus& other); 233 explicit TimerStatus(const snd_timer_status_t* other); 234 virtual ~TimerStatus(); 235 TimerStatus* clone(); 236 TimerStatus& operator=(const TimerStatus& other); 237 int getSizeOfInfo() const; 238 239 snd_htimestamp_t getTimestamp(); 240 long getResolution(); 241 long getLost(); 242 long getOverrun(); 243 long getQueue(); 244 245 private: 246 snd_timer_status_t* m_Info; 247 }; 248 249 /** 250 * ALSA Timer events handler. 251 * 252 * This abstract class is used to define an interface that other class can 253 * implement to receive timer events. 254 */ 255 class DRUMSTICK_EXPORT TimerEventHandler 256 { 257 public: 258 /** Destructor */ 259 virtual ~TimerEventHandler() = default; 260 /** 261 * Timer event handler. This method is called when the timer expires. 262 * @param ticks The time in ticks. 263 * @param msecs The time in milliseconds. 264 */ 265 virtual void handleTimerEvent(int ticks, int msecs) = 0; 266 }; 267 268 /** 269 * ALSA Timer management. 270 * 271 * This class represents an ALSA timer object. 272 */ 273 class DRUMSTICK_EXPORT Timer : public QObject 274 { 275 Q_OBJECT 276 277 private: 278 /** 279 * This class manages timer events input from ALSA 280 */ 281 class TimerInputThread : public QThread 282 { 283 public: 284 /** Constructor */ TimerInputThread(Timer * t,int timeout)285 TimerInputThread(Timer* t, int timeout) 286 : QThread(), 287 m_timer(t), 288 m_Wait(timeout), 289 m_Stopped(false) {} 290 /** Destructor */ 291 virtual ~TimerInputThread() = default; 292 void run() override; 293 bool stopped(); 294 void stop(); 295 private: 296 Timer* m_timer; 297 int m_Wait; 298 bool m_Stopped; 299 QReadWriteLock m_mutex; 300 }; 301 302 public: 303 Timer(int cls, int scls, int card, int dev, int sdev, int openMode, QObject* parent = nullptr); 304 Timer(const QString& deviceName, int openMode, QObject* parent = nullptr); 305 Timer(const QString& deviceName, int openMode, snd_config_t* config, QObject* parent = nullptr); 306 Timer(TimerId& id, int openMode, QObject* parent = nullptr); 307 virtual ~Timer(); 308 309 static TimerId bestGlobalTimerId(); 310 static Timer* bestGlobalTimer(int openMode, QObject* parent = nullptr); 311 /** 312 * Gets the ALSA timer object. 313 * @return ALSA timer object pointer. 314 */ getHandle()315 snd_timer_t* getHandle() { return m_Info; } 316 TimerInfo& getTimerInfo(); 317 TimerStatus& getTimerStatus(); 318 void setTimerParams(const TimerParams& params); 319 320 void start(); 321 void stop(); 322 void continueRunning(); 323 324 void addAsyncTimerHandler(snd_async_callback_t callback, void *private_data); 325 int getPollDescriptorsCount(); 326 void pollDescriptors(struct pollfd *pfds, unsigned int space); 327 void pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds, unsigned short *revents); 328 ssize_t read(void *buffer, size_t size); 329 snd_timer_t* getTimerHandle(); 330 /** 331 * Sets an event handler providing a method to be called when a timer expires. 332 * @param h A TimerEventHandler instance. 333 */ setHandler(TimerEventHandler * h)334 void setHandler(TimerEventHandler* h) { m_handler = h; } 335 void startEvents(); 336 void stopEvents(); 337 338 protected: 339 void doEvents(); 340 341 signals: 342 /** 343 * This signal is emitted when the timer has expired, if there is not an 344 * event hander installed. 345 * 346 * @param ticks The time in ticks. 347 * @param msecs The time in milliseconds. 348 */ 349 void timerExpired(int ticks, int msecs); 350 351 private: 352 snd_timer_t *m_Info; 353 snd_async_handler_t *m_asyncHandler; 354 TimerEventHandler* m_handler; 355 QPointer<TimerInputThread> m_thread; 356 TimerInfo m_TimerInfo; 357 TimerStatus m_TimerStatus; 358 QString m_deviceName; 359 snd_htimestamp_t m_last_time; 360 }; 361 362 /** @} */ 363 364 }} /* namespace drumstick::ALSA */ 365 366 #endif /* DRUMSTICK_ALSATIMER_H */ 367