drumstick 2.9.0
C++ MIDI libraries using Qt objects, idioms, and style.
sysinfo.cpp

Prints information about the ALSA sequencer subsystem.

Prints information about the ALSA sequencer subsystem

/*
MIDI Sequencer C++ library
Copyright (C) 2006-2023, Pedro Lopez-Cabanillas <plcl@users.sf.net>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QCommandLineParser>
#include <QStringList>
#include <QTextStream>
#include <QIODevice>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
#define right Qt::right
#define left Qt::left
#define endl Qt::endl
#define hex Qt::hex
#define dec Qt::dec
#endif
QString PGM_NAME = QStringLiteral("drumstick-sysinfo");
QString PGM_DESCRIPTION = QStringLiteral("ALSA Sequencer System Info");
QTextStream cout(stdout, QIODevice::WriteOnly);
QTextStream cerr(stderr, QIODevice::WriteOnly);
using namespace drumstick::ALSA;
void queryTimers()
{
cout << endl << "ALSA Timers" << endl;
TimerQuery* query = new TimerQuery("hw", 0);
cout << "type___ Name________________ c/s/C/D/S Freq." << endl;
TimerIdList lst = query->getTimers();
TimerIdList::ConstIterator it;
for( it = lst.constBegin(); it != lst.constEnd(); ++it )
{
TimerId id = *it;
try {
Timer* timer = new Timer(id, SND_TIMER_OPEN_NONBLOCK);
TimerInfo info = timer->getTimerInfo();
cout << qSetFieldWidth(8) << left << info.getId()
<< qSetFieldWidth(20) << left << info.getName().leftJustified(20, ' ', true)
<< qSetFieldWidth(0) << " "
<< id.getClass() << "/" << id.getSlaveClass() << "/"
<< id.getCard() << "/" << id.getDevice() << "/"
<< id.getSubdevice() << " ";
if( info.isSlave() ) {
cout << "SLAVE";
} else {
long freq = info.getFrequency();
cout << freq << " Hz";
}
cout << endl;
delete timer;
} catch (const SequencerError& err) {
cerr << "Error opening timer:" << err.qstrError();
}
}
delete query;
}
void queryQueues(MidiClient* c)
{
cout << endl << "ALSA Queues" << endl;
cout << "id Queue_Name__________ Timer_Name__________ owner status "
<< " state PPQ Tempo BPM Ticks Time" << endl;
QList<int> queues = c->getAvailableQueues();
foreach( int q, queues ) {
MidiQueue* queue = new MidiQueue(c, q);
if (queue != nullptr) {
QueueInfo qinfo = queue->getInfo();
QueueStatus qsts = queue->getStatus();
QueueTempo qtmp = queue->getTempo();
QueueTimer qtmr = queue->getTimer();
TimerId tid(qtmr.getId());
QString tname;
try {
Timer* timer = new Timer(tid, SND_TIMER_OPEN_NONBLOCK);
TimerInfo tinfo = timer->getTimerInfo();
tname = tinfo.getName();
delete timer;
} catch (...) {
tname = "inaccessible";
}
cout << qSetFieldWidth(3) << left << qinfo.getId()
<< qSetFieldWidth(20) << qinfo.getName().leftJustified(20, ' ', true)
<< qSetFieldWidth(0) << " "
<< qSetFieldWidth(20) << tname.leftJustified(20, ' ', true)
<< qSetFieldWidth(6) << right << qinfo.getOwner()
<< qSetFieldWidth(7) << (qinfo.isLocked() ? "locked" : "free")
<< qSetFieldWidth(8) << (qsts.isRunning() ? "running" : "stopped")
<< qSetFieldWidth(4) << qtmp.getPPQ()
<< qSetFieldWidth(7) << qtmp.getRealBPM()
<< qSetFieldWidth(4) << qtmp.getNominalBPM()
<< qSetFieldWidth(8) << qsts.getTickTime()
<< qSetFieldWidth(0) << " " << qsts.getClockTime()
<< endl;
delete queue;
}
}
}
QString clientTypeName(snd_seq_client_type_t ctype)
{
if (ctype == SND_SEQ_USER_CLIENT)
return "User";
if (ctype == SND_SEQ_KERNEL_CLIENT)
return "Kernel";
return "Unknown";
}
QString portTypeNames(int ptype)
{
QStringList lst;
if ((ptype & SND_SEQ_PORT_TYPE_HARDWARE) != 0)
lst << "Hardware";
if ((ptype & SND_SEQ_PORT_TYPE_SOFTWARE) != 0)
lst << "Software";
if ((ptype & SND_SEQ_PORT_TYPE_PORT) != 0)
lst << "Port";
if ((ptype & SND_SEQ_PORT_TYPE_DIRECT_SAMPLE) != 0)
lst << "Direct Sample";
if ((ptype & SND_SEQ_PORT_TYPE_MIDI_GENERIC) != 0)
lst << "MIDI Generic";
if ((ptype & SND_SEQ_PORT_TYPE_MIDI_GM) != 0)
lst << "GM";
if ((ptype & SND_SEQ_PORT_TYPE_MIDI_GM2) != 0)
lst << "GM2";
if ((ptype & SND_SEQ_PORT_TYPE_MIDI_GS) != 0)
lst << "GS";
if ((ptype & SND_SEQ_PORT_TYPE_MIDI_MT32) != 0)
lst << "MT32";
if ((ptype & SND_SEQ_PORT_TYPE_MIDI_XG) != 0)
lst << "XG";
if ((ptype & SND_SEQ_PORT_TYPE_SAMPLE) != 0)
lst << "Sample";
if ((ptype & SND_SEQ_PORT_TYPE_SPECIFIC) != 0)
lst << "Specific";
if ((ptype & SND_SEQ_PORT_TYPE_SYNTH) != 0)
lst << "Synth";
if ((ptype & SND_SEQ_PORT_TYPE_APPLICATION) != 0)
lst << "Application";
if ((ptype & SND_SEQ_PORT_TYPE_SYNTHESIZER) != 0)
lst << "Synthesizer";
return " (" + lst.join(", ") + ")";
}
QString subsNames(SubscribersList& subs)
{
QStringList lst;
foreach( Subscriber s, subs ) {
QString sname = QString("%1:%2").arg(static_cast<int>(s.getAddr()->client))
.arg(static_cast<int>(s.getAddr()->port));
lst << sname;
}
return lst.join(", ");
}
void queryClients(MidiClient* c)
{
cout << endl << "ALSA Sequencer clients" << endl;
foreach( ClientInfo cinfo, clients ) {
PortInfoList plist = cinfo.getPorts();
cout << "Client " << qSetFieldWidth(4) << left << cinfo.getClientId()
<< qSetFieldWidth(0) << " : \"" << cinfo.getName() << "\" ["
<< clientTypeName(cinfo.getClientType())
<< "]" << endl;
foreach( PortInfo pinfo, plist ) {
cout << " Port " << qSetFieldWidth(4) << right << pinfo.getPort()
<< qSetFieldWidth(0) << " : \"" << pinfo.getName() << "\""
<< (pinfo.getType() != 0 ? portTypeNames(pinfo.getType()) : "")
<< endl;
if ( from.count() > 0 )
cout << " Connected From: " << subsNames(from) << endl;
if ( to.count() > 0 )
cout << " Connecting To: " << subsNames(to) << endl;
}
}
}
void systemInfo()
{
MidiClient* client = new MidiClient();
client->open();
client->setClientName(PGM_NAME);
SystemInfo info = client->getSystemInfo();
cout << PGM_DESCRIPTION << ", version: "<< QStringLiteral(QT_STRINGIFY(VERSION)) << endl;
cout << "Compiled ALSA library: " << getCompiledALSALibraryVersion() << endl;
cout << "Runtime ALSA library: "
<< getRuntimeALSALibraryVersion() << endl;
cout << "Runtime ALSA drivers: "
cout << "Numeric ALSA compiled library: "
<< hex << SND_LIB_VERSION << endl;
cout << "Numeric ALSA runtime library: "
<< getRuntimeALSALibraryNumber() << endl;
cout << "Numeric ALSA runtime driver: "
cout << "Max Clients: " << dec << info.getMaxClients() << endl;
cout << "Max Ports: " << info.getMaxPorts() << endl;
cout << "Max Queues: " << info.getMaxQueues() << endl;
cout << "Max Channels: " << info.getMaxChannels() << endl;
cout << "Current Queues: " << info.getCurrentQueues() << endl;
cout << "Current Clients: " << info.getCurrentClients() << endl;
queryTimers();
if (info.getCurrentQueues() > 0)
queryQueues(client);
if (info.getCurrentClients() > 0)
queryClients(client);
delete client;
}
int main(int argc, char **argv)
{
const QString ERRORSTR = QStringLiteral("Fatal error from the ALSA sequencer. "
"This usually happens when the kernel doesn't have ALSA support, "
"or the device node (/dev/snd/seq) doesn't exists, "
"or the kernel module (snd_seq) is not loaded. "
"Please check your ALSA/MIDI configuration.");
QCoreApplication app(argc, argv);
QCoreApplication::setApplicationName(PGM_NAME);
QCoreApplication::setApplicationVersion(QStringLiteral(QT_STRINGIFY(VERSION)));
QCommandLineParser parser;
parser.setApplicationDescription(PGM_DESCRIPTION);
auto helpOption = parser.addHelpOption();
auto versionOption = parser.addVersionOption();
parser.process(app);
if (parser.isSet(versionOption) || parser.isSet(helpOption)) {
return 0;
}
try {
systemInfo();
} catch (const SequencerError& ex) {
cerr << ERRORSTR << " Returned error was: " << ex.qstrError() << endl;
} catch (...) {
cerr << ERRORSTR << endl;
}
return 0;
}
Classes managing ALSA Sequencer clients.
Classes managing ALSA Sequencer queues.
Classes managing ALSA Timers.
Client information.
Definition: alsaclient.h:71
Client management.
Definition: alsaclient.h:219
Queue management.
Definition: alsaqueue.h:201
QueueTimer & getTimer()
Gets a QueueTimer object reference.
Definition: alsaqueue.cpp:801
QueueStatus & getStatus()
Gets a QueueStatus object reference.
Definition: alsaqueue.cpp:781
QueueInfo & getInfo()
Gets a QueueInfo object reference.
Definition: alsaqueue.cpp:771
QueueTempo & getTempo()
Gets a QueueTempo object reference.
Definition: alsaqueue.cpp:791
Port information container.
Definition: alsaport.h:52
unsigned int getType()
Gets the port type.
Definition: alsaport.cpp:213
SubscribersList getReadSubscribers() const
Gets the list of read subscribers.
Definition: alsaport.cpp:424
int getPort()
Gets the port number.
Definition: alsaport.cpp:159
QString getName()
Gets the port name.
Definition: alsaport.cpp:191
SubscribersList getWriteSubscribers() const
Gets the list of write subscribers.
Definition: alsaport.cpp:434
Queue information container.
Definition: alsaqueue.h:60
bool isLocked()
Returns the locking status of the queue.
Definition: alsaqueue.cpp:153
int getOwner()
Gets the owner's client id of the queue.
Definition: alsaqueue.cpp:144
int getId()
Gets the queue's numeric identifier.
Definition: alsaqueue.cpp:126
QString getName()
Gets the queue name.
Definition: alsaqueue.cpp:135
Queue status container.
Definition: alsaqueue.h:93
bool isRunning()
Gets the queue's running state.
Definition: alsaqueue.cpp:329
snd_seq_tick_time_t getTickTime()
Gets the musical time (ticks) of the queue.
Definition: alsaqueue.cpp:311
double getClockTime()
Gets the clock time in seconds of the queue.
Definition: alsaqueue.cpp:338
Queue tempo container.
Definition: alsaqueue.h:130
float getRealBPM()
Gets the queue's real BPM tempo in beats per minute.
Definition: alsaqueue.cpp:509
float getNominalBPM()
Gets the queue's nominal BPM tempo (in beats per minute)
Definition: alsaqueue.cpp:496
int getPPQ()
Gets the PPQ (parts per quarter note) resolution of the queue.
Definition: alsaqueue.cpp:415
Queue timer container.
Definition: alsaqueue.h:170
const snd_timer_id_t * getId()
Gets the timer identifier record.
Definition: alsaqueue.cpp:631
Exception class for ALSA Sequencer errors.
Subscriber container class.
Definition: subscription.h:58
const snd_seq_addr_t * getAddr()
Gets the subscriber's address.
System information.
Definition: alsaclient.h:128
ALSA Timer identifier container.
Definition: alsatimer.h:96
ALSA Timer information container.
Definition: alsatimer.h:64
bool isSlave()
Check if the timer is slave (depends on another device)
Definition: alsatimer.cpp:150
QString getId()
Gets the string identifier.
Definition: alsatimer.cpp:170
QString getName()
Gets the timer name.
Definition: alsatimer.cpp:180
long getFrequency()
Gets the timer frequency in Hz.
Definition: alsatimer.cpp:200
ALSA Timer inquiry helper.
Definition: alsatimer.h:171
TimerIdList getTimers() const
Gets the list of available timers.
Definition: alsatimer.h:180
ALSA Timer management.
Definition: alsatimer.h:284
TimerInfo & getTimerInfo()
Gets the timer info object.
Definition: alsatimer.cpp:1209
int getMaxQueues()
Get the system's maximum number of queues.
int getCurrentQueues()
Get the system's current number of queues.
int getMaxPorts()
Get the system's maximum number of ports.
int getMaxChannels()
Get the system's maximum number of channels.
SystemInfo & getSystemInfo()
Gets a SystemInfo instance with the updated state of the system.
snd_seq_client_type_t getClientType()
Gets the client's type.
int getRuntimeALSADriverNumber()
Gets the runtime ALSA drivers version number.
QList< int > getAvailableQueues()
Get a list of the existing queues.
void setClientName(QString const &newName)
Changes the public name of the ALSA sequencer client.
Definition: alsaclient.cpp:842
QList< ClientInfo > ClientInfoList
List of sequencer client information.
Definition: alsaclient.h:119
int getCurrentClients()
Get the system's current number of clients.
ClientInfoList getAvailableClients()
Gets the list of clients from the ALSA sequencer.
Definition: alsaclient.cpp:764
QString getRuntimeALSADriverVersion()
Gets the runtime ALSA drivers version string.
QString getName()
Gets the client's name.
int getClientId()
Gets the client's numeric identifier.
QString getCompiledALSALibraryVersion()
ALSA library version at build time.
void open(const QString deviceName="default", const int openMode=SND_SEQ_OPEN_DUPLEX, const bool blockMode=false)
Open the sequencer device.
Definition: alsaclient.cpp:395
int getMaxClients()
Get the system's maximum number of clients.
PortInfoList getPorts() const
Gets the ports list.
QString qstrError() const
Gets the human readable error message from the error code.
QList< PortInfo > PortInfoList
List of port information objects.
Definition: alsaport.h:117
QList< Subscriber > SubscribersList
List of subscribers.
Definition: subscription.h:138
QList< TimerId > TimerIdList
List of timer identifiers.
Definition: alsatimer.h:129
Drumstick ALSA library wrapper.
Definition: alsaclient.cpp:68
SequencerError Exception class.
Classes managing ALSA sequencer subscriptions.