/[svn]/qsampler/trunk/src/qsamplerDeviceStatusForm.cpp
ViewVC logotype

Annotation of /qsampler/trunk/src/qsamplerDeviceStatusForm.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3667 - (hide annotations) (download)
Sun Dec 22 13:29:09 2019 UTC (4 years, 4 months ago) by schoenebeck
File size: 7095 byte(s)
* Fixed crash when a device disappeared on server side
  (caused by iterator invalidation).

1 schoenebeck 1698 // qsamplerDeviceStatusForm.cpp
2     //
3     /****************************************************************************
4 capela 3555 Copyright (C) 2010-2019, rncbc aka Rui Nuno Capela. All rights reserved.
5 schoenebeck 1698 Copyright (C) 2008, Christian Schoenebeck
6    
7     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License
9     as published by the Free Software Foundation; either version 2
10     of the License, or (at your option) any later version.
11    
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     GNU General Public License for more details.
16    
17 capela 2459 You should have received a copy of the GNU General Public License along
18     with this program; if not, write to the Free Software Foundation, Inc.,
19     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 schoenebeck 1698
21     *****************************************************************************/
22    
23     #include "qsamplerAbout.h"
24     #include "qsamplerDeviceStatusForm.h"
25 capela 2038
26 schoenebeck 1698 #include "qsamplerMainForm.h"
27    
28     #include <QGridLayout>
29    
30 capela 3520 #if QT_VERSION < QT_VERSION_CHECK(4, 5, 0)
31 capela 2042 namespace Qt {
32     const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000);
33     }
34     #endif
35 schoenebeck 1698
36 capela 2042
37 schoenebeck 1698 namespace QSampler {
38    
39 schoenebeck 1699 //-------------------------------------------------------------------------
40     // QSampler::MidiActivityLED -- Graphical indicator for MIDI activity.
41     //
42    
43 capela 2038 // MIDI activity pixmap common resources.
44     int MidiActivityLED::g_iMidiActivityRefCount = 0;
45 capela 3555 QPixmap *MidiActivityLED::g_pMidiActivityLedOn = nullptr;
46     QPixmap *MidiActivityLED::g_pMidiActivityLedOff = nullptr;
47 capela 2038
48    
49     MidiActivityLED::MidiActivityLED ( QString sText, QWidget *pParent )
50     : QLabel(sText, pParent)
51     {
52     if (++g_iMidiActivityRefCount == 1) {
53 capela 2074 g_pMidiActivityLedOn = new QPixmap(":/images/ledon1.png");
54     g_pMidiActivityLedOff = new QPixmap(":/images/ledoff1.png");
55 capela 2038 }
56    
57     setPixmap(*g_pMidiActivityLedOff);
58     #ifndef CONFIG_EVENT_DEVICE_MIDI
59     setToolTip("MIDI Activity disabled");
60 schoenebeck 1698 #endif
61 capela 2038 m_timer.setSingleShot(true);
62    
63     QObject::connect(&m_timer,
64     SIGNAL(timeout()),
65     SLOT(midiActivityLedOff())
66 schoenebeck 1698 );
67     }
68    
69 capela 2038 MidiActivityLED::~MidiActivityLED (void)
70     {
71     if (--g_iMidiActivityRefCount == 0) {
72     if (g_pMidiActivityLedOn)
73     delete g_pMidiActivityLedOn;
74 capela 3555 g_pMidiActivityLedOn = nullptr;
75 capela 2038 if (g_pMidiActivityLedOff)
76     delete g_pMidiActivityLedOff;
77 capela 3555 g_pMidiActivityLedOff = nullptr;
78 capela 2038 }
79 schoenebeck 1698 }
80    
81 capela 2038
82     void MidiActivityLED::midiActivityLedOn (void)
83     {
84     setPixmap(*g_pMidiActivityLedOn);
85     m_timer.start(100);
86 schoenebeck 1698 }
87    
88 capela 2038
89     void MidiActivityLED::midiActivityLedOff (void)
90     {
91     setPixmap(*g_pMidiActivityLedOff);
92     }
93    
94    
95 schoenebeck 1699 //-------------------------------------------------------------------------
96     // QSampler::DeviceStatusForm -- Device status informations window.
97     //
98 schoenebeck 1698
99 capela 2038 std::map<int, DeviceStatusForm *> DeviceStatusForm::g_instances;
100 schoenebeck 1698
101 capela 2038
102 schoenebeck 1698 DeviceStatusForm::DeviceStatusForm (
103 capela 2038 int DeviceID, QWidget *pParent, Qt::WindowFlags wflags )
104     : QWidget(pParent, wflags)
105 schoenebeck 1698 {
106     m_pDevice = new Device(Device::Midi, DeviceID);
107    
108 capela 2038 setLayout(new QGridLayout(/*this*/));
109 schoenebeck 1699 updateGUIPorts(); // build the GUI
110 schoenebeck 1698
111     m_pVisibleAction = new QAction(this);
112     m_pVisibleAction->setCheckable(true);
113     m_pVisibleAction->setChecked(false);
114     m_pVisibleAction->setText(m_pDevice->deviceName());
115     m_pVisibleAction->setToolTip(
116     QString("MIDI Device ID: ") +
117     QString::number(m_pDevice->deviceID())
118     );
119 capela 2038
120     QObject::connect(m_pVisibleAction,
121     SIGNAL(toggled(bool)),
122     SLOT(setVisible(bool))
123 schoenebeck 1698 );
124    
125 capela 2038 setWindowTitle(tr("%1 Status").arg(m_pDevice->deviceName()));
126 schoenebeck 1698 }
127    
128 capela 2038
129     void DeviceStatusForm::updateGUIPorts (void)
130     {
131 schoenebeck 1699 // refresh device informations
132     m_pDevice->setDevice(m_pDevice->deviceType(), m_pDevice->deviceID());
133     DevicePortList ports = m_pDevice->ports();
134    
135     // clear the GUI
136 capela 2038 QGridLayout *pLayout = static_cast<QGridLayout *> (layout());
137 schoenebeck 1699 for (int i = pLayout->count() - 1; i >= 0; --i) {
138 capela 2038 QLayoutItem *pItem = pLayout->itemAt(i);
139     if (pItem) {
140     pLayout->removeItem(pItem);
141     if (pItem->widget())
142     delete pItem->widget();
143     delete pItem;
144     }
145 schoenebeck 1699 }
146    
147 capela 2038 m_midiActivityLEDs.clear();
148    
149 schoenebeck 1699 // rebuild the GUI
150     for (int i = 0; i < ports.size(); ++i) {
151 capela 2038 MidiActivityLED *pLED = new MidiActivityLED();
152     m_midiActivityLEDs.push_back(pLED);
153 capela 2039 pLayout->addWidget(pLED, i, 0);
154     QLabel *pLabel = new QLabel(
155     m_pDevice->deviceTypeName()
156     + ' ' + m_pDevice->driverName()
157     + ' ' + ports[i]->portName());
158     pLayout->addWidget(pLabel, i, 1, Qt::AlignLeft);
159 schoenebeck 1699 }
160     }
161    
162 capela 2038
163     DeviceStatusForm::~DeviceStatusForm (void)
164     {
165 schoenebeck 1698 if (m_pDevice) delete m_pDevice;
166     }
167    
168 capela 2038
169     QAction* DeviceStatusForm::visibleAction (void)
170     {
171 schoenebeck 1698 return m_pVisibleAction;
172     }
173    
174 capela 2038 void DeviceStatusForm::closeEvent ( QCloseEvent *pCloseEvent )
175     {
176 schoenebeck 1698 m_pVisibleAction->setChecked(false);
177 capela 2038
178     pCloseEvent->accept();
179 schoenebeck 1698 }
180    
181 capela 2038
182     void DeviceStatusForm::midiArrived ( int iPort )
183     {
184     if (uint(iPort) >= m_midiActivityLEDs.size())
185     return;
186    
187     m_midiActivityLEDs[iPort]->midiActivityLedOn();
188 schoenebeck 1698 }
189    
190 capela 2038
191     DeviceStatusForm *DeviceStatusForm::getInstance ( int iDeviceID )
192     {
193     std::map<int, DeviceStatusForm *>::iterator iter
194     = g_instances.find(iDeviceID);
195 capela 3555 return ((iter != g_instances.end()) ? iter->second : nullptr);
196 schoenebeck 1698 }
197    
198 capela 2038
199     const std::map<int, DeviceStatusForm *>& DeviceStatusForm::getInstances (void)
200     {
201     return g_instances;
202 schoenebeck 1698 }
203    
204 capela 2038 void DeviceStatusForm::deleteAllInstances (void)
205     {
206     std::map<int, DeviceStatusForm *>::iterator iter = g_instances.begin();
207     for ( ; iter != g_instances.end(); ++iter) {
208 schoenebeck 1699 iter->second->hide();
209     delete iter->second;
210     }
211 capela 2038
212     g_instances.clear();
213 schoenebeck 1699 }
214    
215 capela 2038
216     void DeviceStatusForm::onDevicesChanged (void)
217     {
218 schoenebeck 1698 MainForm* pMainForm = MainForm::getInstance();
219     if (pMainForm && pMainForm->client()) {
220 capela 2038 std::set<int> deviceIDs
221     = Device::getDeviceIDs(pMainForm->client(), Device::Midi);
222 schoenebeck 1698 // hide and delete status forms whose device has been destroyed
223 capela 2038 std::map<int, DeviceStatusForm *>::iterator iter = g_instances.begin();
224 schoenebeck 3667 while (iter != g_instances.end()) {
225 schoenebeck 1698 if (deviceIDs.find(iter->first) == deviceIDs.end()) {
226     iter->second->hide();
227     delete iter->second;
228 schoenebeck 3667 // postfix increment here to avoid iterator invalidation (crash)
229     g_instances.erase(iter++);
230     } else ++iter;
231 schoenebeck 1698 }
232     // create status forms for new devices
233 capela 2038 std::set<int>::iterator it = deviceIDs.begin();
234 capela 2039 for ( ; it != deviceIDs.end(); ++it) {
235 capela 2038 if (g_instances.find(*it) == g_instances.end()) {
236     // What style do we create these forms?
237     Qt::WindowFlags wflags = Qt::Window
238     | Qt::CustomizeWindowHint
239     | Qt::WindowTitleHint
240     | Qt::WindowSystemMenuHint
241     | Qt::WindowMinMaxButtonsHint
242     | Qt::WindowCloseButtonHint;
243     Options *pOptions = pMainForm->options();
244     if (pOptions && pOptions->bKeepOnTop)
245     wflags |= Qt::Tool;
246     // Create the form, giving it the device id.
247     DeviceStatusForm *pStatusForm
248 capela 3555 = new DeviceStatusForm(*it, nullptr, wflags);
249 capela 2038 g_instances[*it] = pStatusForm;
250 schoenebeck 1698 }
251     }
252     }
253     }
254    
255 capela 2038
256     void DeviceStatusForm::onDeviceChanged ( int iDeviceID )
257     {
258     DeviceStatusForm *pStatusForm
259     = DeviceStatusForm::getInstance(iDeviceID);
260     if (pStatusForm)
261     pStatusForm->updateGUIPorts();
262 schoenebeck 1699 }
263    
264 capela 2038
265 schoenebeck 1698 } // namespace QSampler
266    
267     // end of qsamplerDeviceStatusForm.cpp

  ViewVC Help
Powered by ViewVC