// qsamplerDeviceStatusForm.cpp
//
/****************************************************************************
Copyright (C) 2010-2020, rncbc aka Rui Nuno Capela. All rights reserved.
Copyright (C) 2008,2019 Christian Schoenebeck
This program 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 2
of the License, or (at your option) any later version.
This program 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*****************************************************************************/
#include "qsamplerAbout.h"
#include "qsamplerDeviceStatusForm.h"
#include "qsamplerMainForm.h"
#include <QGridLayout>
#if QT_VERSION < QT_VERSION_CHECK(4, 5, 0)
namespace Qt {
const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000);
}
#endif
namespace QSampler {
//-------------------------------------------------------------------------
// QSampler::MidiActivityLED -- Graphical indicator for MIDI activity.
//
// MIDI activity pixmap common resources.
int MidiActivityLED::g_iMidiActivityRefCount = 0;
QPixmap *MidiActivityLED::g_pMidiActivityLedOn = nullptr;
QPixmap *MidiActivityLED::g_pMidiActivityLedOff = nullptr;
MidiActivityLED::MidiActivityLED ( QString sText, QWidget *pParent )
: QLabel(sText, pParent)
{
if (++g_iMidiActivityRefCount == 1) {
g_pMidiActivityLedOn = new QPixmap(":/images/ledon1.png");
g_pMidiActivityLedOff = new QPixmap(":/images/ledoff1.png");
}
setPixmap(*g_pMidiActivityLedOff);
#ifndef CONFIG_EVENT_DEVICE_MIDI
setToolTip("MIDI Activity disabled");
#endif
m_timer.setSingleShot(true);
QObject::connect(&m_timer,
SIGNAL(timeout()),
SLOT(midiActivityLedOff())
);
}
MidiActivityLED::~MidiActivityLED (void)
{
if (--g_iMidiActivityRefCount == 0) {
if (g_pMidiActivityLedOn)
delete g_pMidiActivityLedOn;
g_pMidiActivityLedOn = nullptr;
if (g_pMidiActivityLedOff)
delete g_pMidiActivityLedOff;
g_pMidiActivityLedOff = nullptr;
}
}
void MidiActivityLED::midiActivityLedOn (void)
{
setPixmap(*g_pMidiActivityLedOn);
m_timer.start(100);
}
void MidiActivityLED::midiActivityLedOff (void)
{
setPixmap(*g_pMidiActivityLedOff);
}
//-------------------------------------------------------------------------
// QSampler::DeviceStatusForm -- Device status informations window.
//
std::map<int, DeviceStatusForm *> DeviceStatusForm::g_instances;
DeviceStatusForm::DeviceStatusForm (
int DeviceID, QWidget *pParent, Qt::WindowFlags wflags )
: QWidget(pParent, wflags)
{
m_pDevice = new Device(Device::Midi, DeviceID);
setLayout(new QGridLayout(/*this*/));
updateGUIPorts(); // build the GUI
m_pVisibleAction = new QAction(this);
m_pVisibleAction->setCheckable(true);
m_pVisibleAction->setChecked(false);
m_pVisibleAction->setText(m_pDevice->deviceName());
m_pVisibleAction->setToolTip(
QString("MIDI Device ID: ") +
QString::number(m_pDevice->deviceID())
);
QObject::connect(m_pVisibleAction,
SIGNAL(toggled(bool)),
SLOT(setVisible(bool))
);
setWindowTitle(tr("%1 Status").arg(m_pDevice->deviceName()));
}
void DeviceStatusForm::updateGUIPorts (void)
{
// refresh device informations
m_pDevice->setDevice(m_pDevice->deviceType(), m_pDevice->deviceID());
DevicePortList ports = m_pDevice->ports();
// clear the GUI
QGridLayout *pLayout = static_cast<QGridLayout *> (layout());
for (int i = pLayout->count() - 1; i >= 0; --i) {
QLayoutItem *pItem = pLayout->itemAt(i);
if (pItem) {
pLayout->removeItem(pItem);
if (pItem->widget())
delete pItem->widget();
delete pItem;
}
}
m_midiActivityLEDs.clear();
// rebuild the GUI
for (int i = 0; i < ports.size(); ++i) {
MidiActivityLED *pLED = new MidiActivityLED();
m_midiActivityLEDs.push_back(pLED);
pLayout->addWidget(pLED, i, 0);
QLabel *pLabel = new QLabel(
m_pDevice->deviceTypeName()
+ ' ' + m_pDevice->driverName()
+ ' ' + ports[i]->portName());
pLayout->addWidget(pLabel, i, 1, Qt::AlignLeft);
}
}
DeviceStatusForm::~DeviceStatusForm (void)
{
if (m_pDevice) delete m_pDevice;
}
QAction* DeviceStatusForm::visibleAction (void)
{
return m_pVisibleAction;
}
void DeviceStatusForm::closeEvent ( QCloseEvent *pCloseEvent )
{
m_pVisibleAction->setChecked(false);
pCloseEvent->accept();
}
void DeviceStatusForm::midiArrived ( int iPort )
{
if (uint(iPort) >= m_midiActivityLEDs.size())
return;
m_midiActivityLEDs[iPort]->midiActivityLedOn();
}
DeviceStatusForm *DeviceStatusForm::getInstance ( int iDeviceID )
{
std::map<int, DeviceStatusForm *>::iterator iter
= g_instances.find(iDeviceID);
return ((iter != g_instances.end()) ? iter->second : nullptr);
}
const std::map<int, DeviceStatusForm *>& DeviceStatusForm::getInstances (void)
{
return g_instances;
}
void DeviceStatusForm::deleteAllInstances (void)
{
std::map<int, DeviceStatusForm *>::iterator iter = g_instances.begin();
for ( ; iter != g_instances.end(); ++iter) {
iter->second->hide();
delete iter->second;
}
g_instances.clear();
}
void DeviceStatusForm::onDevicesChanged (void)
{
MainForm* pMainForm = MainForm::getInstance();
if (pMainForm && pMainForm->client()) {
std::set<int> deviceIDs
= Device::getDeviceIDs(pMainForm->client(), Device::Midi);
// hide and delete status forms whose device has been destroyed
std::map<int, DeviceStatusForm *>::iterator iter = g_instances.begin();
while (iter != g_instances.end()) {
if (deviceIDs.find(iter->first) == deviceIDs.end()) {
iter->second->hide();
delete iter->second;
// postfix increment here to avoid iterator invalidation (crash)
g_instances.erase(iter++);
} else ++iter;
}
// create status forms for new devices
std::set<int>::iterator it = deviceIDs.begin();
for ( ; it != deviceIDs.end(); ++it) {
if (g_instances.find(*it) == g_instances.end()) {
// What style do we create these forms?
Qt::WindowFlags wflags = Qt::Window
| Qt::CustomizeWindowHint
| Qt::WindowTitleHint
| Qt::WindowSystemMenuHint
| Qt::WindowMinMaxButtonsHint
| Qt::WindowCloseButtonHint;
Options *pOptions = pMainForm->options();
if (pOptions && pOptions->bKeepOnTop)
wflags |= Qt::Tool;
// Create the form, giving it the device id.
DeviceStatusForm *pStatusForm
= new DeviceStatusForm(*it, nullptr, wflags);
g_instances[*it] = pStatusForm;
}
}
}
}
void DeviceStatusForm::onDeviceChanged ( int iDeviceID )
{
DeviceStatusForm *pStatusForm
= DeviceStatusForm::getInstance(iDeviceID);
if (pStatusForm)
pStatusForm->updateGUIPorts();
}
} // namespace QSampler
// end of qsamplerDeviceStatusForm.cpp