26 #include <QReadLocker>
27 #include <QWriteLocker>
28 #if defined(RTKIT_SUPPORT)
29 #include <QDBusConnection>
30 #include <QDBusInterface>
31 #include <sys/types.h>
32 #include <sys/syscall.h>
33 #include <sys/resource.h>
38 #define RLIMIT_RTTIME 15
41 #ifndef SCHED_RESET_ON_FORK
42 #define SCHED_RESET_ON_FORK 0x40000000
45 #ifndef DEFAULT_INPUT_TIMEOUT
46 #define DEFAULT_INPUT_TIMEOUT 500
342 void setRealtimePriority();
348 QReadWriteLock m_mutex;
368 m_eventsEnabled(false),
370 m_NeedRefreshClientList(true),
371 m_OpenMode(SND_SEQ_OPEN_DUPLEX),
372 m_DeviceName(
"default"),
392 if (m_Thread != NULL)
408 m_Thread->m_RealTime = enable;
421 return m_Thread->m_RealTime;
447 const bool blockMode)
449 CHECK_ERROR( snd_seq_open( &m_SeqHandle, deviceName.toLocal8Bit().data(),
450 openMode, blockMode ? 0 : SND_SEQ_NONBLOCK ) );
451 CHECK_WARNING( snd_seq_get_client_info( m_SeqHandle, m_Info.m_Info ) );
452 m_DeviceName = deviceName;
453 m_OpenMode = openMode;
454 m_BlockMode = blockMode;
479 const QString deviceName,
481 const bool blockMode )
484 deviceName.toLocal8Bit().data(),
486 blockMode ? 0 : SND_SEQ_NONBLOCK,
488 CHECK_WARNING( snd_seq_get_client_info(m_SeqHandle, m_Info.m_Info));
489 m_DeviceName = deviceName;
490 m_OpenMode = openMode;
491 m_BlockMode = blockMode;
504 if (m_SeqHandle != NULL) {
522 return snd_seq_get_output_buffer_size(m_SeqHandle);
537 CHECK_WARNING(snd_seq_set_output_buffer_size(m_SeqHandle, newSize));
552 return snd_seq_get_input_buffer_size(m_SeqHandle);
567 CHECK_WARNING(snd_seq_set_input_buffer_size(m_SeqHandle, newSize));
583 if (m_BlockMode != newValue)
585 m_BlockMode = newValue;
586 if (m_SeqHandle != NULL)
588 CHECK_WARNING(snd_seq_nonblock(m_SeqHandle, m_BlockMode ? 0 : 1));
614 return snd_seq_type(m_SeqHandle);
642 snd_seq_event_t* evp = NULL;
644 err = snd_seq_event_input(m_SeqHandle, &evp);
645 if ((err >= 0) && (evp != NULL)) {
648 case SND_SEQ_EVENT_NOTE:
652 case SND_SEQ_EVENT_NOTEON:
656 case SND_SEQ_EVENT_NOTEOFF:
660 case SND_SEQ_EVENT_KEYPRESS:
664 case SND_SEQ_EVENT_CONTROLLER:
665 case SND_SEQ_EVENT_CONTROL14:
666 case SND_SEQ_EVENT_REGPARAM:
667 case SND_SEQ_EVENT_NONREGPARAM:
671 case SND_SEQ_EVENT_PGMCHANGE:
675 case SND_SEQ_EVENT_CHANPRESS:
679 case SND_SEQ_EVENT_PITCHBEND:
683 case SND_SEQ_EVENT_SYSEX:
687 case SND_SEQ_EVENT_PORT_SUBSCRIBED:
688 case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
692 case SND_SEQ_EVENT_PORT_CHANGE:
693 case SND_SEQ_EVENT_PORT_EXIT:
694 case SND_SEQ_EVENT_PORT_START:
696 m_NeedRefreshClientList =
true;
699 case SND_SEQ_EVENT_CLIENT_CHANGE:
700 case SND_SEQ_EVENT_CLIENT_EXIT:
701 case SND_SEQ_EVENT_CLIENT_START:
703 m_NeedRefreshClientList =
true;
706 case SND_SEQ_EVENT_SONGPOS:
707 case SND_SEQ_EVENT_SONGSEL:
708 case SND_SEQ_EVENT_QFRAME:
709 case SND_SEQ_EVENT_TIMESIGN:
710 case SND_SEQ_EVENT_KEYSIGN:
714 case SND_SEQ_EVENT_SETPOS_TICK:
715 case SND_SEQ_EVENT_SETPOS_TIME:
716 case SND_SEQ_EVENT_QUEUE_SKEW:
720 case SND_SEQ_EVENT_TEMPO:
729 if (m_handler != NULL) {
733 if (m_eventsEnabled) {
734 QObjectList::Iterator it;
735 for(it=m_listeners.begin(); it!=m_listeners.end(); ++it) {
737 QApplication::postEvent(sub, event->clone());
747 while (snd_seq_event_input_pending(m_SeqHandle, 0) > 0);
759 m_Thread->start( m_Thread->m_RealTime ?
760 QThread::TimeCriticalPriority : QThread::InheritPriority );
771 if (m_Thread->isRunning()) {
773 while (!m_Thread->wait(500) && (counter < 10)) {
776 if (!m_Thread->isFinished()) {
777 m_Thread->terminate();
793 while (snd_seq_query_next_client(m_SeqHandle, cInfo.m_Info) >= 0) {
795 m_ClientList.append(cInfo);
797 m_NeedRefreshClientList =
false;
806 m_ClientList.clear();
816 if (m_NeedRefreshClientList)
829 snd_seq_get_client_info(m_SeqHandle, m_Info.m_Info);
844 snd_seq_set_client_info(m_SeqHandle, m_Info.m_Info);
853 if (m_SeqHandle != NULL) {
854 snd_seq_set_client_info(m_SeqHandle, m_Info.m_Info);
876 ClientInfoList::Iterator it;
877 if (m_NeedRefreshClientList)
879 for (it = m_ClientList.begin(); it != m_ClientList.end(); ++it) {
880 if ((*it).getClientId() == clientId) {
881 return (*it).getName();
894 if (newName != m_Info.
getName()) {
929 if (m_SeqHandle != NULL) {
930 CHECK_ERROR(snd_seq_create_port(m_SeqHandle, port->m_Info.m_Info));
931 m_Ports.push_back(port);
942 if (m_SeqHandle != NULL) {
950 MidiPortList::iterator it;
951 for(it = m_Ports.begin(); it != m_Ports.end(); ++it)
967 if (m_SeqHandle != NULL) {
968 MidiPortList::iterator it;
969 for (it = m_Ports.begin(); it != m_Ports.end(); ++it) {
970 CHECK_ERROR(snd_seq_delete_port(m_SeqHandle, (*it)->getPortInfo()->getPort()));
971 (*it)->setMidiClient(NULL);
984 snd_seq_set_client_event_filter(m_SeqHandle, evtype);
1052 npfds = snd_seq_poll_descriptors_count(m_SeqHandle, POLLOUT);
1053 pfds = (pollfd*) alloca(npfds *
sizeof(pollfd));
1054 snd_seq_poll_descriptors(m_SeqHandle, pfds, npfds, POLLOUT);
1055 while (snd_seq_event_output(m_SeqHandle, ev->
getHandle()) < 0)
1057 poll(pfds, npfds, timeout);
1080 npfds = snd_seq_poll_descriptors_count(m_SeqHandle, POLLOUT);
1081 pfds = (pollfd*) alloca(npfds *
sizeof(pollfd));
1082 snd_seq_poll_descriptors(m_SeqHandle, pfds, npfds, POLLOUT);
1083 while (snd_seq_event_output_direct(m_SeqHandle, ev->
getHandle()) < 0)
1085 poll(pfds, npfds, timeout);
1122 npfds = snd_seq_poll_descriptors_count(m_SeqHandle, POLLOUT);
1123 pfds = (pollfd*) alloca(npfds *
sizeof(pollfd));
1124 snd_seq_poll_descriptors(m_SeqHandle, pfds, npfds, POLLOUT);
1125 while (snd_seq_drain_output(m_SeqHandle) < 0)
1127 poll(pfds, npfds, timeout);
1140 snd_seq_sync_output_queue(m_SeqHandle);
1151 if (m_Queue == NULL) {
1164 if (m_Queue != NULL) {
1180 if (m_Queue != NULL) {
1183 m_Queue =
new MidiQueue(
this, queueName,
this);
1197 if (m_Queue != NULL) {
1200 m_Queue =
new MidiQueue(
this, queue_id,
this);
1214 if (m_Queue != NULL) {
1218 if ( queue_id >= 0) {
1219 m_Queue =
new MidiQueue(
this, queue_id,
this);
1233 if (m_Queue != NULL) {
1236 queue->setParent(
this);
1250 snd_seq_queue_info_t* qinfo;
1251 snd_seq_queue_info_alloca(&qinfo);
1253 for ( q = 0; q < max; ++q ) {
1254 err = snd_seq_get_queue_info(m_SeqHandle, q, qinfo);
1273 ClientInfoList::ConstIterator itc;
1274 PortInfoList::ConstIterator itp;
1276 if (m_NeedRefreshClientList)
1279 for (itc = m_ClientList.constBegin(); itc != m_ClientList.constEnd(); ++itc) {
1281 if ((ci.
getClientId() == SND_SEQ_CLIENT_SYSTEM) ||
1285 for(itp = lstPorts.constBegin(); itp != lstPorts.constEnd(); ++itp) {
1288 if ( ((filter & cap) != 0) &&
1289 ((SND_SEQ_PORT_CAP_NO_EXPORT & cap) == 0) ) {
1303 m_InputsAvail.clear();
1304 m_OutputsAvail.clear();
1305 m_InputsAvail =
filterPorts( SND_SEQ_PORT_CAP_READ |
1306 SND_SEQ_PORT_CAP_SUBS_READ );
1307 m_OutputsAvail =
filterPorts( SND_SEQ_PORT_CAP_WRITE |
1308 SND_SEQ_PORT_CAP_SUBS_WRITE );
1318 m_NeedRefreshClientList =
true;
1320 return m_InputsAvail;
1330 m_NeedRefreshClientList =
true;
1332 return m_OutputsAvail;
1344 m_listeners.append(listener);
1355 m_listeners.removeAll(listener);
1367 if (bEnabled != m_eventsEnabled) {
1368 m_eventsEnabled = bEnabled;
1379 snd_seq_system_info(m_SeqHandle, m_sysInfo.m_Info);
1390 snd_seq_get_client_pool(m_SeqHandle, m_poolInfo.m_Info);
1402 CHECK_WARNING(snd_seq_set_client_pool(m_SeqHandle, m_poolInfo.m_Info));
1432 CHECK_WARNING(snd_seq_set_client_pool_input(m_SeqHandle, size));
1442 CHECK_WARNING(snd_seq_set_client_pool_output(m_SeqHandle, size));
1452 CHECK_WARNING(snd_seq_set_client_pool_output_room(m_SeqHandle, size));
1510 CHECK_WARNING(snd_seq_remove_events(m_SeqHandle, spec->m_Info));
1520 snd_seq_event_t* ev;
1521 if (
CHECK_WARNING(snd_seq_extract_output(m_SeqHandle, &ev) == 0)) {
1535 return snd_seq_event_output_pending(m_SeqHandle);
1554 return snd_seq_event_input_pending(m_SeqHandle, fetch ? 1 : 0);
1566 return snd_seq_query_named_queue(m_SeqHandle, name.toLocal8Bit().data());
1577 return snd_seq_poll_descriptors_count(m_SeqHandle, events);
1597 return snd_seq_poll_descriptors(m_SeqHandle, pfds, space, events);
1609 unsigned short revents;
1610 CHECK_WARNING( snd_seq_poll_descriptors_revents( m_SeqHandle,
1623 return snd_seq_name(m_SeqHandle);
1648 return CHECK_WARNING( snd_seq_create_simple_port( m_SeqHandle,
1649 name, caps, type ));
1659 CHECK_WARNING( snd_seq_delete_simple_port( m_SeqHandle, port ));
1671 CHECK_WARNING( snd_seq_connect_from(m_SeqHandle, myport, client, port ));
1683 CHECK_WARNING( snd_seq_connect_to(m_SeqHandle, myport, client, port ));
1695 CHECK_WARNING( snd_seq_disconnect_from(m_SeqHandle, myport, client, port ));
1707 CHECK_WARNING( snd_seq_disconnect_to(m_SeqHandle, myport, client, port ));
1725 QString testClient, testPort;
1726 ClientInfoList::ConstIterator cit;
1727 int pos = straddr.indexOf(
':');
1729 testClient = straddr.left(pos);
1730 testPort = straddr.mid(pos+1);
1732 testClient = straddr;
1735 addr.client = testClient.toInt(&ok);
1737 addr.port = testPort.toInt(&ok);
1739 if (m_NeedRefreshClientList)
1741 for ( cit = m_ClientList.constBegin();
1742 cit != m_ClientList.constEnd(); ++cit ) {
1744 if (testClient.compare(ci.
getName(), Qt::CaseInsensitive) == 0) {
1746 addr.port = testPort.toInt(&ok);
1761 QReadLocker locker(&m_mutex);
1771 QWriteLocker locker(&m_mutex);
1775 #if defined(RTKIT_SUPPORT)
1776 static pid_t _gettid(
void) {
1777 return (pid_t) ::syscall(SYS_gettid);
1782 MidiClient::SequencerInputThread::setRealtimePriority()
1784 struct sched_param p;
1785 int rt, policy = SCHED_RR | SCHED_RESET_ON_FORK;
1786 quint32 priority = 6;
1787 #if defined(RTKIT_SUPPORT)
1791 struct rlimit old_limit, new_limit;
1792 long long max_rttime;
1795 ::memset(&p, 0,
sizeof(p));
1796 p.sched_priority = priority;
1797 rt = ::pthread_setschedparam(::pthread_self(), policy, &p);
1799 #if defined(RTKIT_SUPPORT)
1800 const QString rtkit_service =
1801 QLatin1String(
"org.freedesktop.RealtimeKit1");
1802 const QString rtkit_path =
1803 QLatin1String(
"/org/freedesktop/RealtimeKit1");
1804 const QString rtkit_iface = rtkit_service;
1806 QDBusConnection bus = QDBusConnection::systemBus();
1807 QDBusInterface realtimeKit(rtkit_service, rtkit_path, rtkit_iface, bus);
1808 QVariant maxRTPrio = realtimeKit.property(
"MaxRealtimePriority");
1809 max_prio = maxRTPrio.toUInt(&ok);
1811 qWarning() <<
"invalid property RealtimeKit.MaxRealtimePriority";
1814 if (priority > max_prio)
1815 priority = max_prio;
1816 QVariant maxRTNSec = realtimeKit.property(
"RTTimeNSecMax");
1817 max_rttime = maxRTNSec.toLongLong(&ok);
1818 if (!ok || max_rttime < 0) {
1819 qWarning() <<
"invalid property RealtimeKit.RTTimeNSecMax";
1822 new_limit.rlim_cur = new_limit.rlim_max = max_rttime;
1823 rt = ::getrlimit(RLIMIT_RTTIME, &old_limit);
1825 qWarning() <<
"getrlimit() failed. err=" << rt << ::strerror(rt);
1828 rt = ::setrlimit(RLIMIT_RTTIME, &new_limit);
1830 qWarning() <<
"setrlimit() failed, err=" << rt << ::strerror(rt);
1833 QDBusMessage reply = realtimeKit.call(
"MakeThreadRealtime", thread, priority);
1834 if (reply.type() == QDBusMessage::ErrorMessage )
1835 qWarning() <<
"error returned by RealtimeKit.MakeThreadRealtime:"
1836 << reply.errorMessage();
1838 qWarning() <<
"pthread_setschedparam() failed, err="
1839 << rt << ::strerror(rt);
1852 if ( priority() == TimeCriticalPriority )
1853 setRealtimePriority();
1855 if (m_MidiClient != NULL) {
1856 npfd = snd_seq_poll_descriptors_count(m_MidiClient->getHandle(), POLLIN);
1857 pfd = (pollfd *) alloca(npfd *
sizeof(pollfd));
1860 snd_seq_poll_descriptors(m_MidiClient->getHandle(), pfd, npfd, POLLIN);
1861 while (!stopped() && (m_MidiClient != NULL))
1863 int rt = poll(pfd, npfd, m_Wait);
1865 m_MidiClient->doEvents();
1871 qWarning() <<
"exception in input thread";
1881 snd_seq_client_info_malloc(&m_Info);
1890 snd_seq_client_info_malloc(&m_Info);
1891 snd_seq_client_info_copy(m_Info, other.m_Info);
1892 m_Ports = other.m_Ports;
1901 snd_seq_client_info_malloc(&m_Info);
1902 snd_seq_client_info_copy(m_Info, other);
1912 snd_seq_client_info_malloc(&m_Info);
1913 snd_seq_get_any_client_info(seq->
getHandle(),
id, m_Info);
1922 snd_seq_client_info_free(m_Info);
1943 snd_seq_client_info_copy(m_Info, other.m_Info);
1944 m_Ports = other.m_Ports;
1955 return snd_seq_client_info_get_client(m_Info);
1962 snd_seq_client_type_t
1965 return snd_seq_client_info_get_type(m_Info);
1975 return QString(snd_seq_client_info_get_name(m_Info));
1985 return (snd_seq_client_info_get_broadcast_filter(m_Info) != 0);
1995 return (snd_seq_client_info_get_error_bounce(m_Info) != 0);
2003 const unsigned char*
2006 return snd_seq_client_info_get_event_filter(m_Info);
2016 return snd_seq_client_info_get_num_ports(m_Info);
2026 return snd_seq_client_info_get_event_lost(m_Info);
2036 snd_seq_client_info_set_client(m_Info, client);
2046 snd_seq_client_info_set_name(m_Info, name.toLocal8Bit().data());
2056 snd_seq_client_info_set_broadcast_filter(m_Info, val ? 1 : 0);
2066 snd_seq_client_info_set_error_bounce(m_Info, val ? 1 : 0);
2077 snd_seq_client_info_set_event_filter(m_Info, filter);
2092 while (snd_seq_query_next_port(seq->
getHandle(), info.m_Info) >= 0) {
2094 m_Ports.append(info);
2125 return snd_seq_client_info_sizeof();
2128 #if SND_LIB_VERSION > 0x010010
2135 ClientInfo::addFilter(
int eventType)
2137 snd_seq_client_info_event_filter_add(m_Info, eventType);
2146 ClientInfo::isFiltered(
int eventType)
2148 return (snd_seq_client_info_event_filter_check(m_Info, eventType) != 0);
2155 ClientInfo::clearFilter()
2157 snd_seq_client_info_event_filter_clear(m_Info);
2165 ClientInfo::removeFilter(
int eventType)
2167 snd_seq_client_info_event_filter_del(m_Info, eventType);
2176 snd_seq_system_info_malloc(&m_Info);
2185 snd_seq_system_info_malloc(&m_Info);
2186 snd_seq_system_info_copy(m_Info, other.m_Info);
2195 snd_seq_system_info_malloc(&m_Info);
2196 snd_seq_system_info_copy(m_Info, other);
2205 snd_seq_system_info_malloc(&m_Info);
2206 snd_seq_system_info(seq->
getHandle(), m_Info);
2214 snd_seq_system_info_free(m_Info);
2235 snd_seq_system_info_copy(m_Info, other.m_Info);
2245 return snd_seq_system_info_get_clients(m_Info);
2254 return snd_seq_system_info_get_ports(m_Info);
2263 return snd_seq_system_info_get_queues(m_Info);
2272 return snd_seq_system_info_get_channels(m_Info);
2281 return snd_seq_system_info_get_cur_queues(m_Info);
2290 return snd_seq_system_info_get_cur_clients(m_Info);
2299 return snd_seq_system_info_sizeof();
2307 snd_seq_client_pool_malloc(&m_Info);
2316 snd_seq_client_pool_malloc(&m_Info);
2317 snd_seq_client_pool_copy(m_Info, other.m_Info);
2326 snd_seq_client_pool_malloc(&m_Info);
2327 snd_seq_client_pool_copy(m_Info, other);
2336 snd_seq_client_pool_malloc(&m_Info);
2337 snd_seq_get_client_pool(seq->
getHandle(), m_Info);
2345 snd_seq_client_pool_free(m_Info);
2365 snd_seq_client_pool_copy(m_Info, other.m_Info);
2376 return snd_seq_client_pool_get_client(m_Info);
2386 return snd_seq_client_pool_get_input_free(m_Info);
2396 return snd_seq_client_pool_get_input_pool(m_Info);
2406 return snd_seq_client_pool_get_output_free(m_Info);
2416 return snd_seq_client_pool_get_output_pool(m_Info);
2427 return snd_seq_client_pool_get_output_room(m_Info);
2437 snd_seq_client_pool_set_input_pool(m_Info, size);
2447 snd_seq_client_pool_set_output_pool(m_Info, size);
2459 snd_seq_client_pool_set_output_room(m_Info, size);
2469 return snd_seq_client_pool_sizeof();
2472 #if SND_LIB_VERSION > 0x010004
2479 getRuntimeALSALibraryVersion()
2481 return QString(snd_asoundlib_version());
2490 getRuntimeALSALibraryNumber()
2492 QRegExp rx(
"(\\d+)");
2493 QString str = getRuntimeALSALibraryVersion();
2495 int pos = 0, result = 0, j = 0;
2496 while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
2497 int v = rx.cap(1).toInt(&ok);
2502 pos += rx.matchedLength();
2507 #endif // SND_LIB_VERSION > 0x010004
2517 QRegExp rx(
".*Driver Version ([\\d\\.]+).*");
2519 QFile f(
"/proc/asound/version");
2520 if (f.open(QFile::ReadOnly)) {
2521 QTextStream str(&f);
2522 if (rx.exactMatch(str.readLine().trimmed()))
2536 QRegExp rx(
"(\\d+)");
2539 int pos = 0, result = 0, j = 0;
2540 while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
2541 int v = rx.cap(1).toInt(&ok);
2546 pos += rx.matchedLength();