drumstick 0.5.0

alsatimer.cpp

Go to the documentation of this file.
00001 /*
00002     MIDI Sequencer C++ library
00003     Copyright (C) 2006-2010, Pedro Lopez-Cabanillas <plcl@users.sf.net>
00004 
00005     This library is free software; you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or
00008     (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License along
00016     with this program; if not, write to the Free Software Foundation, Inc.,
00017     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018 */
00019 
00020 #include "alsatimer.h"
00021 #include <QReadLocker>
00022 #include <QWriteLocker>
00023 #include <cmath>
00024 #include <cstdio>
00025 
00031 namespace drumstick {
00032 
00088 TimerInfo::TimerInfo()
00089 {
00090     snd_timer_info_malloc(&m_Info);
00091 }
00092 
00097 TimerInfo::TimerInfo(const snd_timer_info_t *other)
00098 {
00099     snd_timer_info_malloc(&m_Info);
00100     snd_timer_info_copy(m_Info, other);
00101 }
00102 
00107 TimerInfo::TimerInfo(const TimerInfo& other)
00108 {
00109     snd_timer_info_malloc(&m_Info);
00110     snd_timer_info_copy(m_Info, other.m_Info);
00111 }
00112 
00116 TimerInfo::~TimerInfo()
00117 {
00118     snd_timer_info_free(m_Info);
00119 }
00120 
00125 TimerInfo*
00126 TimerInfo::clone()
00127 {
00128     return new TimerInfo(m_Info);
00129 }
00130 
00135 TimerInfo&
00136 TimerInfo::operator=(const TimerInfo& other)
00137 {
00138     snd_timer_info_copy(m_Info, other.m_Info);
00139     return *this;
00140 }
00141 
00146 bool
00147 TimerInfo::isSlave()
00148 {
00149     return (snd_timer_info_is_slave(m_Info) != 0);
00150 }
00151 
00156 int
00157 TimerInfo::getCard()
00158 {
00159     return snd_timer_info_get_card(m_Info);
00160 }
00161 
00166 QString
00167 TimerInfo::getId()
00168 {
00169     return QString(snd_timer_info_get_id(m_Info));
00170 }
00171 
00176 QString
00177 TimerInfo::getName()
00178 {
00179     return QString(snd_timer_info_get_name(m_Info));
00180 }
00181 
00186 long
00187 TimerInfo::getResolution()
00188 {
00189     return snd_timer_info_get_resolution(m_Info);
00190 }
00191 
00196 long
00197 TimerInfo::getFrequency()
00198 {
00199     long res = getResolution();
00200     if (res > 0)
00201     {
00202         return 1000000000L / res;
00203     }
00204     return 0;
00205 }
00206 
00211 int
00212 TimerInfo::getSizeOfInfo() const
00213 {
00214     return snd_timer_info_sizeof();
00215 }
00216 
00222 long
00223 TimerInfo::getTicks()
00224 {
00225     return snd_timer_info_get_ticks(m_Info);
00226 }
00227 
00231 TimerId::TimerId()
00232 {
00233     snd_timer_id_malloc(&m_Info);
00234 }
00235 
00240 TimerId::TimerId(const snd_timer_id_t *other)
00241 {
00242     snd_timer_id_malloc(&m_Info);
00243     snd_timer_id_copy(m_Info, other);
00244     if (getCard() < 0)
00245         setCard(0);
00246     if (getDevice() < 0)
00247         setDevice(0);
00248     if (getSubdevice() < 0)
00249         setSubdevice(0);
00250 }
00251 
00256 TimerId::TimerId(const TimerId& other)
00257 {
00258     snd_timer_id_malloc(&m_Info);
00259     snd_timer_id_copy(m_Info, other.m_Info);
00260     if (getCard() < 0)
00261         setCard(0);
00262     if (getDevice() < 0)
00263         setDevice(0);
00264     if (getSubdevice() < 0)
00265         setSubdevice(0);
00266 }
00267 
00276 TimerId::TimerId(int cls, int scls, int card, int dev, int sdev)
00277 {
00278     snd_timer_id_malloc(&m_Info);
00279     setClass(cls);
00280     setSlaveClass(scls);
00281     setCard(card);
00282     setDevice(dev);
00283     setSubdevice(sdev);
00284 }
00285 
00289 TimerId::~TimerId()
00290 {
00291     snd_timer_id_free(m_Info);
00292 }
00293 
00298 TimerId*
00299 TimerId::clone()
00300 {
00301     return new TimerId(m_Info);
00302 }
00303 
00309 TimerId&
00310 TimerId::operator=(const TimerId& other)
00311 {
00312     snd_timer_id_copy(m_Info, other.m_Info);
00313     if (getCard() < 0)
00314     setCard(0);
00315     if (getDevice() < 0)
00316     setDevice(0);
00317     if (getSubdevice() < 0)
00318     setSubdevice(0);
00319     return *this;
00320 }
00321 
00332 void
00333 TimerId::setClass(int devclass)
00334 {
00335     snd_timer_id_set_class(m_Info, devclass);
00336 }
00337 
00343 int
00344 TimerId::getClass()
00345 {
00346     return snd_timer_id_get_class(m_Info);
00347 }
00348 
00353 void
00354 TimerId::setSlaveClass(int devsclass)
00355 {
00356     snd_timer_id_set_sclass(m_Info, devsclass);
00357 }
00358 
00363 int
00364 TimerId::getSlaveClass()
00365 {
00366     return snd_timer_id_get_sclass(m_Info);
00367 }
00368 
00373 void
00374 TimerId::setCard(int card)
00375 {
00376     snd_timer_id_set_card(m_Info, card);
00377 }
00378 
00383 int
00384 TimerId::getCard()
00385 {
00386     return snd_timer_id_get_card(m_Info);
00387 }
00388 
00393 void
00394 TimerId::setDevice(int device)
00395 {
00396     snd_timer_id_set_device(m_Info, device);
00397 }
00398 
00403 int
00404 TimerId::getDevice()
00405 {
00406     return snd_timer_id_get_device(m_Info);
00407 }
00408 
00413 void
00414 TimerId::setSubdevice(int subdevice)
00415 {
00416     snd_timer_id_set_subdevice (m_Info, subdevice);
00417 }
00418 
00423 int
00424 TimerId::getSubdevice()
00425 {
00426     return snd_timer_id_get_subdevice(m_Info);
00427 }
00428 
00433 int
00434 TimerId::getSizeOfInfo() const
00435 {
00436     return snd_timer_id_sizeof();
00437 }
00438 
00444 TimerQuery::TimerQuery(const QString& deviceName, int openMode)
00445 {
00446     CHECK_WARNING( snd_timer_query_open( &m_Info,
00447                                          deviceName.toLocal8Bit().data(),
00448                                          openMode ));
00449     readTimers();
00450 }
00451 
00458 TimerQuery::TimerQuery( const QString& deviceName, int openMode,
00459                         snd_config_t* conf )
00460 {
00461     CHECK_WARNING( snd_timer_query_open_lconf( &m_Info,
00462                                                deviceName.toLocal8Bit().data(),
00463                                                openMode, conf ));
00464     readTimers();
00465 }
00466 
00470 TimerQuery::~TimerQuery()
00471 {
00472     freeTimers();
00473     snd_timer_query_close(m_Info);
00474 }
00475 
00479 void
00480 TimerQuery::readTimers()
00481 {
00482     TimerId tid;
00483     snd_timer_id_set_class(tid.m_Info, SND_TIMER_CLASS_NONE);
00484     for(;;)
00485     {
00486         int rc = snd_timer_query_next_device(m_Info, tid.m_Info);
00487         if ((rc < 0) || (tid.getClass() < 0)) {
00488             break;
00489         }
00490         m_timers.append(tid);
00491     }
00492 }
00493 
00497 void
00498 TimerQuery::freeTimers()
00499 {
00500     m_timers.clear();
00501 }
00502 
00507 TimerGlobalInfo&
00508 TimerQuery::getGlobalInfo()
00509 {
00510     snd_timer_query_info(m_Info, m_GlobalInfo.m_Info);
00511     return m_GlobalInfo;
00512 }
00513 
00518 void
00519 TimerQuery::setGlobalParams(snd_timer_gparams_t* params)
00520 {
00521     snd_timer_query_params(m_Info, params);
00522 }
00523 
00528 void
00529 TimerQuery::getGlobalParams(snd_timer_gparams_t* params)
00530 {
00531     snd_timer_query_params(m_Info, params);
00532 }
00533 
00538 void
00539 TimerQuery::getGlobalStatus(snd_timer_gstatus_t *status)
00540 {
00541     snd_timer_query_status(m_Info, status);
00542 }
00543 
00547 TimerGlobalInfo::TimerGlobalInfo()
00548 {
00549     snd_timer_ginfo_malloc(&m_Info);
00550 }
00551 
00556 TimerGlobalInfo::TimerGlobalInfo(const snd_timer_ginfo_t* other)
00557 {
00558     snd_timer_ginfo_malloc(&m_Info);
00559     snd_timer_ginfo_copy(m_Info, other);
00560 }
00561 
00566 TimerGlobalInfo::TimerGlobalInfo(const TimerGlobalInfo& other)
00567 {
00568     snd_timer_ginfo_malloc(&m_Info);
00569     snd_timer_ginfo_copy(m_Info, other.m_Info);
00570 }
00571 
00575 TimerGlobalInfo::~TimerGlobalInfo()
00576 {
00577     snd_timer_ginfo_free(m_Info);
00578 }
00579 
00584 TimerGlobalInfo*
00585 TimerGlobalInfo::clone()
00586 {
00587     return new TimerGlobalInfo(m_Info);
00588 }
00589 
00595 TimerGlobalInfo&
00596 TimerGlobalInfo::operator=(const TimerGlobalInfo& other)
00597 {
00598     snd_timer_ginfo_copy(m_Info, other.m_Info);
00599     return *this;
00600 }
00601 
00606 void
00607 TimerGlobalInfo::setTimerId(const TimerId& tid)
00608 {
00609     m_Id = tid;
00610     snd_timer_ginfo_set_tid (m_Info, m_Id.m_Info);
00611 }
00612 
00617 TimerId&
00618 TimerGlobalInfo::getTimerId()
00619 {
00620     m_Id = TimerId(snd_timer_ginfo_get_tid (m_Info));
00621     return m_Id;
00622 }
00623 
00628 unsigned int
00629 TimerGlobalInfo::getFlags()
00630 {
00631     return snd_timer_ginfo_get_flags (m_Info);
00632 }
00633 
00638 int
00639 TimerGlobalInfo::getCard()
00640 {
00641     return snd_timer_ginfo_get_card (m_Info);
00642 }
00643 
00648 QString
00649 TimerGlobalInfo::getId()
00650 {
00651     return QString(snd_timer_ginfo_get_id (m_Info));
00652 }
00653 
00658 QString
00659 TimerGlobalInfo::getName()
00660 {
00661     return QString(snd_timer_ginfo_get_name (m_Info));
00662 }
00663 
00668 unsigned long
00669 TimerGlobalInfo::getResolution()
00670 {
00671     return snd_timer_ginfo_get_resolution (m_Info);
00672 }
00673 
00678 unsigned long
00679 TimerGlobalInfo::getMinResolution()
00680 {
00681     return snd_timer_ginfo_get_resolution_min (m_Info);
00682 }
00683 
00688 unsigned long
00689 TimerGlobalInfo::getMaxResolution()
00690 {
00691     return snd_timer_ginfo_get_resolution_max(m_Info);
00692 }
00693 
00698 unsigned int
00699 TimerGlobalInfo::getClients()
00700 {
00701     return snd_timer_ginfo_get_clients(m_Info);
00702 }
00703 
00708 int
00709 TimerGlobalInfo::getSizeOfInfo() const
00710 {
00711     return snd_timer_ginfo_sizeof();
00712 }
00713 
00717 TimerParams::TimerParams()
00718 {
00719     snd_timer_params_malloc (&m_Info);
00720 }
00721 
00726 TimerParams::TimerParams(const snd_timer_params_t *other)
00727 {
00728     snd_timer_params_malloc (&m_Info);
00729     snd_timer_params_copy (m_Info, other);
00730 }
00731 
00736 TimerParams::TimerParams(const TimerParams& other)
00737 {
00738     snd_timer_params_malloc (&m_Info);
00739     snd_timer_params_copy (m_Info, other.m_Info);
00740 }
00741 
00746 TimerParams::~TimerParams()
00747 {
00748     snd_timer_params_free (m_Info);
00749 }
00750 
00755 TimerParams*
00756 TimerParams::clone()
00757 {
00758     return new TimerParams(m_Info);
00759 }
00760 
00766 TimerParams&
00767 TimerParams::operator=(const TimerParams& other)
00768 {
00769     snd_timer_params_copy (m_Info, other.m_Info);
00770     return *this;
00771 }
00772 
00777 void
00778 TimerParams::setAutoStart(bool auto_start)
00779 {
00780     snd_timer_params_set_auto_start (m_Info, auto_start ? 1 : 0);
00781 }
00782 
00787 bool
00788 TimerParams::getAutoStart()
00789 {
00790     return (snd_timer_params_get_auto_start (m_Info) != 0);
00791 }
00792 
00797 void
00798 TimerParams::setExclusive(bool exclusive)
00799 {
00800     snd_timer_params_set_exclusive (m_Info, exclusive ? 1 : 0);
00801 }
00802 
00807 bool
00808 TimerParams::getExclusive()
00809 {
00810     return (snd_timer_params_get_exclusive (m_Info) != 0);
00811 }
00812 
00817 void
00818 TimerParams::setEarlyEvent(bool early_event)
00819 {
00820     snd_timer_params_set_early_event (m_Info, early_event ? 1 : 0);
00821 }
00822 
00827 bool
00828 TimerParams::getEarlyEvent()
00829 {
00830     return (snd_timer_params_get_early_event (m_Info) != 0);
00831 }
00832 
00837 void
00838 TimerParams::setTicks(long ticks)
00839 {
00840     snd_timer_params_set_ticks (m_Info, ticks);
00841 }
00842 
00847 long
00848 TimerParams::getTicks()
00849 {
00850     return snd_timer_params_get_ticks (m_Info);
00851 }
00852 
00857 void
00858 TimerParams::setQueueSize(long queue_size)
00859 {
00860     snd_timer_params_set_queue_size (m_Info, queue_size);
00861 }
00862 
00867 long
00868 TimerParams::getQueueSize()
00869 {
00870     return snd_timer_params_get_queue_size (m_Info);
00871 }
00872 
00877 void
00878 TimerParams::setFilter(unsigned int filter)
00879 {
00880     snd_timer_params_set_filter (m_Info, filter);
00881 }
00882 
00887 unsigned int
00888 TimerParams::getFilter()
00889 {
00890     return snd_timer_params_get_filter (m_Info);
00891 }
00892 
00897 int
00898 TimerParams::getSizeOfInfo() const
00899 {
00900     return snd_timer_params_sizeof();
00901 }
00902 
00906 TimerStatus::TimerStatus()
00907 {
00908     snd_timer_status_malloc (&m_Info);
00909 }
00910 
00915 TimerStatus::TimerStatus(const snd_timer_status_t *other)
00916 {
00917     snd_timer_status_malloc (&m_Info);
00918     snd_timer_status_copy (m_Info, other);
00919 }
00920 
00925 TimerStatus::TimerStatus(const TimerStatus& other)
00926 {
00927     snd_timer_status_malloc (&m_Info);
00928     snd_timer_status_copy (m_Info, other.m_Info);
00929 }
00930 
00934 TimerStatus::~TimerStatus()
00935 {
00936     snd_timer_status_free (m_Info);
00937 }
00938 
00943 TimerStatus*
00944 TimerStatus::clone()
00945 {
00946     return new TimerStatus(m_Info);
00947 }
00948 
00954 TimerStatus&
00955 TimerStatus::operator=(const TimerStatus& other)
00956 {
00957     snd_timer_status_copy (m_Info, other.m_Info);
00958     return *this;
00959 }
00960 
00965 snd_htimestamp_t
00966 TimerStatus::getTimestamp()
00967 {
00968     return snd_timer_status_get_timestamp (m_Info);
00969 }
00970 
00975 long
00976 TimerStatus::getResolution()
00977 {
00978     return snd_timer_status_get_resolution (m_Info);
00979 }
00980 
00985 long
00986 TimerStatus::getLost()
00987 {
00988     return snd_timer_status_get_lost (m_Info);
00989 }
00990 
00995 long
00996 TimerStatus::getOverrun()
00997 {
00998     return snd_timer_status_get_overrun (m_Info);
00999 }
01000 
01005 long
01006 TimerStatus::getQueue()
01007 {
01008     return snd_timer_status_get_queue (m_Info);
01009 }
01010 
01015 int
01016 TimerStatus::getSizeOfInfo() const
01017 {
01018     return snd_timer_status_sizeof();
01019 }
01020 
01032 Timer::Timer( const QString& deviceName, int openMode, QObject* parent )
01033     : QObject(parent),
01034     m_asyncHandler(NULL),
01035     m_handler(NULL),
01036     m_thread(NULL),
01037     m_deviceName(deviceName)
01038 {
01039     CHECK_ERROR( snd_timer_open( &m_Info, m_deviceName.toLocal8Bit().data(),
01040                                  openMode ));
01041 }
01042 
01055 Timer::Timer( const QString& deviceName, int openMode, snd_config_t* conf,
01056               QObject* parent )
01057     : QObject(parent),
01058     m_asyncHandler(NULL),
01059     m_handler(NULL),
01060     m_thread(NULL),
01061     m_deviceName(deviceName)
01062 {
01063     CHECK_ERROR( snd_timer_open_lconf( &m_Info,
01064                                        m_deviceName.toLocal8Bit().data(),
01065                                        openMode, conf ));
01066 }
01067 
01079 Timer::Timer( TimerId& id, int openMode, QObject* parent )
01080     : QObject(parent),
01081     m_asyncHandler(NULL),
01082     m_handler(NULL),
01083     m_thread(NULL)
01084 {
01085     m_deviceName = QString("hw:CLASS=%1,SCLASS=%2,CARD=%3,DEV=%4,SUBDEV=%5")
01086     .arg(id.getClass())
01087     .arg(id.getSlaveClass())
01088     .arg(id.getCard())
01089     .arg(id.getDevice())
01090     .arg(id.getSubdevice());
01091     CHECK_ERROR( snd_timer_open( &m_Info,
01092                                  m_deviceName.toLocal8Bit().data(),
01093                                  openMode ));
01094 }
01095 
01111 Timer::Timer( int cls, int scls, int card, int dev, int sdev,
01112               int openMode, QObject* parent )
01113     : QObject(parent),
01114     m_asyncHandler(NULL),
01115     m_handler(NULL),
01116     m_thread(NULL)
01117 {
01118     m_deviceName = QString("hw:CLASS=%1,SCLASS=%2,CARD=%3,DEV=%4,SUBDEV=%5")
01119         .arg(cls)
01120         .arg(scls)
01121         .arg(card)
01122         .arg(dev)
01123         .arg(sdev);
01124     CHECK_ERROR( snd_timer_open( &m_Info,
01125                                  m_deviceName.toLocal8Bit().data(),
01126                                  openMode ));
01127 }
01128 
01132 Timer::~Timer()
01133 {
01134     stopEvents();
01135     if (m_thread != NULL)
01136         delete m_thread;
01137     CHECK_WARNING(snd_timer_close(m_Info));
01138 }
01139 
01145 void
01146 Timer::addAsyncTimerHandler(snd_async_callback_t callback, void *private_data)
01147 {
01148     CHECK_WARNING(snd_async_add_timer_handler(&m_asyncHandler, m_Info, callback, private_data));
01149 }
01150 
01155 snd_timer_t*
01156 Timer::getTimerHandle()
01157 {
01158     return snd_async_handler_get_timer(m_asyncHandler);
01159 }
01160 
01165 int
01166 Timer::getPollDescriptorsCount()
01167 {
01168     return snd_timer_poll_descriptors_count(m_Info);
01169 }
01170 
01176 void
01177 Timer::pollDescriptors(struct pollfd *pfds, unsigned int space)
01178 {
01179     CHECK_WARNING(snd_timer_poll_descriptors(m_Info, pfds, space));
01180 }
01181 
01188 void
01189 Timer::pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
01190 {
01191     CHECK_WARNING(snd_timer_poll_descriptors_revents(m_Info, pfds, nfds, revents));
01192 }
01193 
01198 TimerInfo&
01199 Timer::getTimerInfo()
01200 {
01201     snd_timer_info (m_Info, m_TimerInfo.m_Info);
01202     return m_TimerInfo;
01203 }
01204 
01209 void
01210 Timer::setTimerParams(const TimerParams& params)
01211 {
01212     CHECK_WARNING( snd_timer_params(m_Info, params.m_Info) );
01213 }
01214 
01219 TimerStatus&
01220 Timer::getTimerStatus()
01221 {
01222     CHECK_WARNING( snd_timer_status(m_Info, m_TimerStatus.m_Info) );
01223     return m_TimerStatus;
01224 }
01225 
01229 void
01230 Timer::start()
01231 {
01232     CHECK_WARNING(snd_timer_start(m_Info));
01233 }
01234 
01238 void
01239 Timer::stop()
01240 {
01241     CHECK_WARNING(snd_timer_stop(m_Info));
01242 }
01243 
01247 void
01248 Timer::continueRunning()
01249 {
01250     CHECK_WARNING(snd_timer_continue(m_Info));
01251 }
01252 
01259 ssize_t
01260 Timer::read(void *buffer, size_t size)
01261 {
01262     return snd_timer_read(m_Info, buffer, size);
01263 }
01264 
01273 void
01274 Timer::doEvents()
01275 {
01276     snd_timer_tread_t tr;
01277     while ( read(&tr, sizeof(tr)) == sizeof(tr) ) {
01278         int msecs = ((tr.tstamp.tv_sec - m_last_time.tv_sec) * 1000) +
01279                     round((tr.tstamp.tv_nsec - m_last_time.tv_nsec) / 1000000.0);
01280         m_last_time = tr.tstamp;
01281         if ( m_handler != NULL )
01282             m_handler->handleTimerEvent(tr.val, msecs);
01283         else
01284             emit timerExpired(tr.val, msecs);
01285     }
01286 }
01287 
01291 void Timer::startEvents()
01292 {
01293     m_last_time = getTimerStatus().getTimestamp();
01294     if (m_thread == NULL) {
01295         m_thread = new TimerInputThread(this, 500);
01296         m_thread->start();
01297     }
01298 }
01299 
01303 void Timer::stopEvents()
01304 {
01305     int counter = 0;
01306     if (m_thread != NULL) {
01307         m_thread->stop();
01308         while (!m_thread->wait(500) && (counter < 10)) {
01309             counter++;
01310         }
01311         if (!m_thread->isFinished()) {
01312             m_thread->terminate();
01313         }
01314         delete m_thread;
01315     }
01316 }
01317 
01324 TimerId
01325 Timer::bestGlobalTimerId()
01326 {
01327     TimerId id;
01328     snd_timer_t* timer;
01329     snd_timer_info_t* info;
01330     long res, best_res = LONG_MAX;
01331     char timername[64];
01332     int test_devs[] = {
01333           SND_TIMER_GLOBAL_SYSTEM
01334         , SND_TIMER_GLOBAL_RTC
01335 #ifdef SND_TIMER_GLOBAL_HPET
01336         , SND_TIMER_GLOBAL_HPET
01337 #endif
01338 #ifdef SND_TIMER_GLOBAL_HRTIMER
01339         , SND_TIMER_GLOBAL_HRTIMER
01340 #endif
01341     };
01342     int max_global_timers = sizeof(test_devs)/sizeof(int);
01343     int clas = SND_TIMER_CLASS_GLOBAL;
01344     int scls = SND_TIMER_SCLASS_NONE;
01345     int card = 0;
01346     int dev  = SND_TIMER_GLOBAL_SYSTEM;
01347     int sdev = 0;
01348     int err = 0;
01349     int is_slave = 0;
01350     int i;
01351     snd_timer_info_alloca(&info);
01352     // default system timer
01353     id.setClass(clas);
01354     id.setSlaveClass(scls);
01355     id.setCard(card);
01356     id.setDevice(dev);
01357     id.setSubdevice(sdev);
01358     // select a non slave timer with the lowest resolution value
01359     for( i = 0; i < max_global_timers; ++i )
01360     {
01361         dev = test_devs[i];
01362         sprintf( timername, "hw:CLASS=%i,SCLASS=%i,CARD=%i,DEV=%i,SUBDEV=%i",
01363                  clas, scls, card, dev, sdev );
01364         err = snd_timer_open(&timer, timername, SND_TIMER_OPEN_NONBLOCK);
01365         if (err < 0) continue;
01366         err = snd_timer_info(timer, info);
01367         if (err == 0) {
01368             is_slave = snd_timer_info_is_slave(info);
01369             res = snd_timer_info_get_resolution(info);
01370             if ((is_slave == 0) && (best_res > res)) {
01371                 best_res = res;
01372                 id.setDevice(dev);
01373             }
01374         }
01375         snd_timer_close(timer);
01376     }
01377     return id;
01378 }
01379 
01387 Timer*
01388 Timer::bestGlobalTimer(int openMode, QObject* parent)
01389 {
01390     TimerId id = bestGlobalTimerId();
01391     return new Timer(id, openMode, parent);
01392 }
01393 
01397 void
01398 Timer::TimerInputThread::run()
01399 {
01400     int err, count;
01401     struct pollfd *fds;
01402     if (m_timer == NULL) return;
01403 
01404     count = m_timer->getPollDescriptorsCount();
01405     fds = (pollfd *) calloc(count, sizeof(struct pollfd));
01406     if (fds == NULL) {
01407         qWarning() << "allocation error!";
01408         return;
01409     }
01410     fds->events = POLLIN;
01411     fds->revents = 0;
01412 
01413     try {
01414         while (!stopped() && (m_timer != NULL)) {
01415             m_timer->pollDescriptors(fds, count);
01416             if ((err = poll(fds, count, m_Wait)) < 0) {
01417                 qWarning() << "poll error " << err << "(" << strerror(err) << ")";
01418                 return;
01419             }
01420             if (err == 0) {
01421                 qWarning() << "timer time out";
01422                 return;
01423             }
01424             m_timer->doEvents();
01425         }
01426     } catch (...) {
01427         qWarning() << "exception in input thread";
01428     }
01429     free(fds);
01430 }
01431 
01436 bool
01437 Timer::TimerInputThread::stopped()
01438 {
01439     QReadLocker locker(&m_mutex);
01440     return m_Stopped;
01441 }
01442 
01446 void
01447 Timer::TimerInputThread::stop()
01448 {
01449     QWriteLocker locker(&m_mutex);
01450     m_Stopped = true;
01451 }
01452 
01453 } /* namespace drumstick */