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

Contents of /qsampler/trunk/src/qsamplerInstrumentList.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 980 - (show annotations) (download)
Sun Dec 17 22:29:29 2006 UTC (13 years, 2 months ago) by capela
File size: 16038 byte(s)
* Revised and extended MIDI instrument mapping feature; this time
  two (2) MIDI maps are being implicitly created, ones designated
  as 'Chromatic' (0) and another as 'Drum Kits' (1), which can be
  assigned to each sampler channel. (ATTN: this commit elevates the
  requirements for liblscp >= 0.5.0, also on todays CVS and pending
  proper release very soon).

1 // qsamplerInstrumentList.cpp
2 //
3 /****************************************************************************
4 Copyright (C) 2003-2005, rncbc aka Rui Nuno Capela. All rights reserved.
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 *****************************************************************************/
21
22 #include "qsamplerAbout.h"
23 #include "qsamplerInstrumentList.h"
24
25 #include "qsamplerInstrument.h"
26 #include "qsamplerInstrumentForm.h"
27
28 #include "qsamplerMainForm.h"
29
30 #include <qaction.h>
31 #include <qfileinfo.h>
32 #include <qpopupmenu.h>
33
34 // Needed for lroundf()
35 #include <math.h>
36
37 #ifndef CONFIG_ROUND
38 static inline long lroundf ( float x )
39 {
40 if (x >= 0.0f)
41 return long(x + 0.5f);
42 else
43 return long(x - 0.5f);
44 }
45 #endif
46
47
48 //----------------------------------------------------------------------
49 // class qsamplerInstrumentGroup -- custom group list view item.
50 //
51
52 // Constructors.
53 qsamplerInstrumentGroup::qsamplerInstrumentGroup (
54 qsamplerInstrumentList *pListView, const QString& sName,
55 QListViewItem *pItemAfter )
56 : QListViewItem(pListView, pItemAfter ? pItemAfter : pListView->lastItem())
57 {
58 QListViewItem::setRenameEnabled(0, true);
59
60 QListViewItem::setPixmap(0, QPixmap::fromMimeSource("itemGroup.png"));
61 QListViewItem::setText(0, sName);
62 }
63
64
65 qsamplerInstrumentGroup::qsamplerInstrumentGroup (
66 qsamplerInstrumentGroup *pGroupItem, const QString& sName )
67 : QListViewItem(pGroupItem, sName)
68 {
69 QListViewItem::setRenameEnabled(0, true);
70
71 QListViewItem::setPixmap(0, QPixmap::fromMimeSource("itemGroup.png"));
72 }
73
74
75 // Default destructor.
76 qsamplerInstrumentGroup::~qsamplerInstrumentGroup (void)
77 {
78 }
79
80
81 // Instance accessors.
82 void qsamplerInstrumentGroup::setName ( const QString& sName )
83 {
84 QListViewItem::setText(0, sName);
85 }
86
87
88 QString qsamplerInstrumentGroup::name (void) const
89 {
90 return QListViewItem::text(0);
91 }
92
93
94 qsamplerInstrumentGroup *qsamplerInstrumentGroup::groupItem (void) const
95 {
96 QListViewItem *pParent = QListViewItem::parent();
97 while (pParent && pParent->rtti() != qsamplerInstrumentList::Group)
98 pParent = pParent->parent();
99 return static_cast<qsamplerInstrumentGroup *> (pParent);
100 }
101
102
103 qsamplerInstrumentList *qsamplerInstrumentGroup::listView (void) const
104 {
105 return static_cast<qsamplerInstrumentList *> (QListViewItem::listView());
106 }
107
108
109 // To show up whether its open or not.
110 void qsamplerInstrumentGroup::setOpen ( bool bOpen )
111 {
112 // Set the proper pixmap of this...
113 if (rtti() == qsamplerInstrumentList::Group) {
114 QListViewItem::setPixmap(0, QPixmap::fromMimeSource(
115 bOpen ? "itemGroupOpen.png" : "itemGroup.png"));
116 }
117 // Open it up...
118 QListViewItem::setOpen(bOpen);
119
120 // All ancestors should be also visible.
121 if (bOpen && QListViewItem::parent())
122 QListViewItem::parent()->setOpen(true);
123 }
124
125
126 // To virtually distinguish between list view items.
127 int qsamplerInstrumentGroup::rtti (void) const
128 {
129 return qsamplerInstrumentList::Group;
130 }
131
132
133 //----------------------------------------------------------------------
134 // class qsamplerInstrumentItem -- custom file list view item.
135 //
136
137 // Constructors.
138 qsamplerInstrumentItem::qsamplerInstrumentItem (
139 qsamplerInstrumentList *pListView,
140 qsamplerInstrument *pInstrument,
141 QListViewItem *pItemAfter )
142 : qsamplerInstrumentGroup(pListView, pInstrument->name(), pItemAfter)
143 {
144 m_pInstrument = pInstrument;
145
146 update();
147 }
148
149 qsamplerInstrumentItem::qsamplerInstrumentItem (
150 qsamplerInstrumentGroup *pGroupItem,
151 qsamplerInstrument *pInstrument )
152 : qsamplerInstrumentGroup(pGroupItem, pInstrument->name())
153 {
154 m_pInstrument = pInstrument;
155
156 update();
157 }
158
159
160 // Default destructor.
161 qsamplerInstrumentItem::~qsamplerInstrumentItem (void)
162 {
163 if (m_pInstrument)
164 delete m_pInstrument;
165 }
166
167
168 // To virtually distinguish between list view items.
169 int qsamplerInstrumentItem::rtti (void) const
170 {
171 return qsamplerInstrumentList::Item;
172 }
173
174
175 // Payload accessor.
176 qsamplerInstrument *qsamplerInstrumentItem::instrument (void) const
177 {
178 return m_pInstrument;
179 }
180
181
182 // Item refreshment.
183 void qsamplerInstrumentItem::update (void)
184 {
185 QListViewItem::setPixmap(0, QPixmap::fromMimeSource("itemFile.png"));
186
187 const QString s = "-";
188 if (m_pInstrument) {
189 setText(0, m_pInstrument->name());
190 setText(1, QString::number(m_pInstrument->map()));
191 setText(2, QString::number(m_pInstrument->bank()));
192 setText(3, QString::number(m_pInstrument->prog() + 1));
193 setText(4, m_pInstrument->engineName());
194 setText(5, QFileInfo(m_pInstrument->instrumentFile()).fileName());
195 setText(6, QString::number(m_pInstrument->instrumentNr()));
196 setText(7, QString::number(::lroundf(100.0f * m_pInstrument->volume())));
197 QString sLoadMode = s;
198 switch (m_pInstrument->loadMode()) {
199 case 3:
200 sLoadMode = QObject::tr("Persistent");
201 break;
202 case 2:
203 sLoadMode = QObject::tr("On Demand Hold");
204 break;
205 case 1:
206 sLoadMode = QObject::tr("On Demand");
207 break;
208 }
209 setText(8, sLoadMode);
210 } else {
211 for (int i = 0; i < listView()->columns(); i++)
212 setText(i, s);
213 }
214 }
215
216
217 //----------------------------------------------------------------------------
218 // qsamplerInstrumentList -- MIDI instrument list view.
219 //
220
221 // Constructor.
222 qsamplerInstrumentList::qsamplerInstrumentList (
223 QWidget *pParent, const char *pszName )
224 : QListView(pParent, pszName)
225 {
226 // QListView::setRootIsDecorated(true);
227 QListView::setResizeMode(QListView::NoColumn);
228 // QListView::setAcceptDrops(true);
229 QListView::setDragAutoScroll(true);
230 QListView::setSizePolicy(
231 QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
232 // QListView::setShowToolTips(false);
233 QListView::setSortColumn(-1);
234
235 QListView::addColumn(tr("Name"));
236 QListView::addColumn(tr("Map"));
237 QListView::addColumn(tr("Bank"));
238 QListView::addColumn(tr("Prog"));
239 QListView::addColumn(tr("Engine"));
240 QListView::addColumn(tr("File"));
241 QListView::addColumn(tr("Nr"));
242 QListView::addColumn(tr("Vol"));
243 QListView::addColumn(tr("Mode"));
244
245 QListView::setColumnAlignment(1, Qt::AlignHCenter); // Map
246 QListView::setColumnAlignment(2, Qt::AlignHCenter); // Bank
247 QListView::setColumnAlignment(3, Qt::AlignHCenter); // Prog
248 QListView::setColumnAlignment(6, Qt::AlignHCenter); // Nr
249 QListView::setColumnAlignment(7, Qt::AlignHCenter); // Vol
250
251 QListView::setColumnWidth(0, 120); // Name
252 QListView::setColumnWidth(5, 240); // File
253
254 m_pNewGroupAction = new QAction(tr("New &Group"), tr("Ctrl+G"), this);
255 m_pNewItemAction = new QAction(tr("New &Instrument..."), tr("Ctrl+I"), this);
256 m_pEditItemAction = new QAction(tr("&Edit..."), tr("Ctrl+E"), this);
257 m_pRenameAction = new QAction(tr("&Rename"), tr("Ctrl+R"), this);
258 m_pDeleteAction = new QAction(tr("&Delete"), tr("Ctrl+D"), this);
259 m_pRefreshAction = new QAction(tr("Re&fresh"), tr("Ctrl+F"), this);
260
261 QObject::connect(m_pNewGroupAction,
262 SIGNAL(activated()),
263 SLOT(newGroupSlot()));
264 QObject::connect(m_pNewItemAction,
265 SIGNAL(activated()),
266 SLOT(newItemSlot()));
267 QObject::connect(m_pEditItemAction,
268 SIGNAL(activated()),
269 SLOT(editItemSlot()));
270 QObject::connect(m_pRenameAction,
271 SIGNAL(activated()),
272 SLOT(renameSlot()));
273 QObject::connect(m_pDeleteAction,
274 SIGNAL(activated()),
275 SLOT(deleteSlot()));
276 QObject::connect(m_pRefreshAction,
277 SIGNAL(activated()),
278 SLOT(refresh()));
279
280 QObject::connect(this,
281 SIGNAL(selectionChanged()),
282 SLOT(selectionChangedSlot()));
283 QObject::connect(this,
284 SIGNAL(doubleClicked(QListViewItem*, const QPoint&, int)),
285 SLOT(activatedSlot(QListViewItem*)));
286 QObject::connect(this,
287 SIGNAL(returnPressed(QListViewItem*)),
288 SLOT(activatedSlot(QListViewItem*)));
289 QObject::connect(this,
290 SIGNAL(itemRenamed(QListViewItem*,int)),
291 SLOT(renamedSlot(QListViewItem*)));
292
293 selectionChangedSlot();
294 }
295
296
297 // Default destructor.
298 qsamplerInstrumentList::~qsamplerInstrumentList (void)
299 {
300 delete m_pNewGroupAction;
301 delete m_pNewItemAction;
302 delete m_pEditItemAction;
303 delete m_pRenameAction;
304 delete m_pDeleteAction;
305 }
306
307
308 // Add a new instrument item, optionally under a given group.
309 qsamplerInstrumentItem *qsamplerInstrumentList::addItem (
310 qsamplerInstrument *pInstrument,
311 qsamplerInstrumentGroup *pParentGroup )
312 {
313 qsamplerInstrumentItem *pItem = findItem(pInstrument);
314 if (pItem == NULL) {
315 if (pParentGroup)
316 pItem = new qsamplerInstrumentItem(pParentGroup, pInstrument);
317 else
318 pItem = new qsamplerInstrumentItem(this, pInstrument);
319 }
320 QListView::setSelected(pItem, true);
321 return pItem;
322 }
323
324
325 // Add a new instrument group, optionally under another group.
326 qsamplerInstrumentGroup *qsamplerInstrumentList::addGroup (
327 const QString& sName, qsamplerInstrumentGroup *pParentGroup )
328 {
329 qsamplerInstrumentGroup *pGroup = findGroup(sName);
330 if (pGroup == NULL) {
331 if (pParentGroup)
332 pGroup = new qsamplerInstrumentGroup(pParentGroup, sName);
333 else
334 pGroup = new qsamplerInstrumentGroup(this, sName);
335 }
336 QListView::setSelected(pGroup, true);
337 return pGroup;
338 }
339
340
341 // Find a group item, given its name.
342 qsamplerInstrumentGroup *qsamplerInstrumentList::findGroup (
343 const QString& sName ) const
344 {
345 // Iterate all over the place to search for the group.
346 QListViewItemIterator iter((QListView *) this);
347 while (iter.current()) {
348 QListViewItem *pItem = iter.current();
349 if (pItem->rtti() == Group && pItem->text(0) == sName)
350 return static_cast<qsamplerInstrumentGroup *> (pItem);
351 ++iter;
352 }
353 // Not found.
354 return NULL;
355 }
356
357
358 // Find a file item, given its name.
359 qsamplerInstrumentItem *qsamplerInstrumentList::findItem (
360 qsamplerInstrument *pInstrument ) const
361 {
362 if (pInstrument == NULL)
363 return NULL;
364
365 // Iterate all over the place to search for the group.
366 QListViewItemIterator iter((QListView *) this);
367 while (iter.current()) {
368 QListViewItem *pListItem = iter.current();
369 if (pListItem->rtti() == Item) {
370 qsamplerInstrumentItem *pItem
371 = static_cast<qsamplerInstrumentItem *> (pListItem);
372 if (pItem && pItem->instrument()
373 && pItem->instrument()->map() == pInstrument->map()
374 && pItem->instrument()->bank() == pInstrument->bank()
375 && pItem->instrument()->prog() == pInstrument->prog())
376 return pItem;
377 }
378 ++iter;
379 }
380 // Not found.
381 return NULL;
382 }
383
384
385 // Find and return the nearest group item...
386 qsamplerInstrumentGroup *qsamplerInstrumentList::groupItem (
387 QListViewItem *pItem ) const
388 {
389 while (pItem && pItem->rtti() != Group)
390 pItem = pItem->parent();
391 return static_cast<qsamplerInstrumentGroup *> (pItem);
392 }
393
394
395 // Add a new group item below the current one.
396 void qsamplerInstrumentList::newGroupSlot (void)
397 {
398 qsamplerInstrumentGroup *pParentGroup
399 = groupItem(QListView::selectedItem());
400 qsamplerInstrumentGroup *pNewGroup
401 = addGroup(tr("New Group"), pParentGroup);
402 if (pParentGroup)
403 pParentGroup->setOpen(true);
404 if (pNewGroup)
405 pNewGroup->startRename(0);
406
407 selectionChangedSlot();
408 }
409
410
411 // Add a new instrument item below the current one.
412 void qsamplerInstrumentList::newItemSlot (void)
413 {
414 qsamplerInstrument *pInstrument = new qsamplerInstrument();
415
416 qsamplerInstrumentForm form(this);
417 form.setup(pInstrument);
418 if (!form.exec()) {
419 delete pInstrument;
420 return;
421 }
422
423 // Check it there's already one instrument item
424 // with the very same key (bank, program);
425 // if yes, just remove it without prejudice...
426 qsamplerInstrumentItem *pItem = findItem(pInstrument);
427 if (pItem)
428 delete pItem;
429
430 pInstrument->mapInstrument();
431 emit instrumentsChanged();
432
433 qsamplerInstrumentGroup *pParentGroup
434 = groupItem(QListView::selectedItem());
435 addItem(pInstrument, pParentGroup);
436 if (pParentGroup)
437 pParentGroup->setOpen(true);
438
439 selectionChangedSlot();
440 }
441
442
443 // Edit current item below the current one.
444 void qsamplerInstrumentList::editItemSlot (void)
445 {
446 QListViewItem *pListItem = QListView::selectedItem();
447 if (pListItem == NULL)
448 return;
449 if (pListItem->rtti() == Item) {
450 qsamplerInstrumentItem *pItem
451 = static_cast<qsamplerInstrumentItem *> (pListItem);
452 if (pItem && pItem->instrument()) {
453 qsamplerInstrumentForm form(this);
454 form.setup(pItem->instrument());
455 if (form.exec()) {
456 pItem->instrument()->mapInstrument();
457 emit instrumentsChanged();
458 pItem->update();
459 }
460 }
461 }
462
463 selectionChangedSlot();
464 }
465
466
467 // Rename current group/item.
468 void qsamplerInstrumentList::renameSlot (void)
469 {
470 QListViewItem *pListItem = QListView::selectedItem();
471 if (pListItem)
472 pListItem->startRename(0);
473
474 selectionChangedSlot();
475 }
476
477
478 // Remove current group/item.
479 void qsamplerInstrumentList::deleteSlot (void)
480 {
481 QListViewItem *pListItem = QListView::selectedItem();
482 if (pListItem) {
483 if (pListItem->rtti() == Item) {
484 qsamplerInstrumentItem *pItem
485 = static_cast<qsamplerInstrumentItem *> (pListItem);
486 if (pItem && pItem->instrument()) {
487 pItem->instrument()->unmapInstrument();
488 emit instrumentsChanged();
489 }
490 }
491 delete pListItem;
492 }
493
494 selectionChangedSlot();
495 }
496
497
498 // In-place selection slot.
499 void qsamplerInstrumentList::selectionChangedSlot (void)
500 {
501 qsamplerMainForm *pMainForm = qsamplerMainForm::getInstance();
502 QListViewItem *pListItem = QListView::selectedItem();
503 bool bEnabled = (pMainForm && pMainForm->client());
504 m_pNewItemAction->setEnabled(bEnabled);
505 bEnabled = (bEnabled && pListItem != NULL);
506 m_pEditItemAction->setEnabled(bEnabled && pListItem->rtti() == Item);
507 m_pRenameAction->setEnabled(bEnabled);
508 m_pDeleteAction->setEnabled(bEnabled);
509 }
510
511
512 // In-place activation slot.
513 void qsamplerInstrumentList::activatedSlot ( QListViewItem *pListItem )
514 {
515 // FIXME: Hope the list view item is the one selected.
516 if (pListItem->rtti() == Item)
517 editItemSlot();
518 }
519
520
521 // In-place aliasing slot.
522 void qsamplerInstrumentList::renamedSlot ( QListViewItem *pListItem )
523 {
524 if (pListItem->rtti() == Item) {
525 qsamplerInstrumentItem *pItem
526 = static_cast<qsamplerInstrumentItem *> (pListItem);
527 if (pItem && pItem->instrument()) {
528 pItem->instrument()->setName(pListItem->text(0));
529 pItem->instrument()->mapInstrument();
530 emit instrumentsChanged();
531 pItem->update();
532 }
533 }
534 }
535
536
537 // Context menu request event handler.
538 void qsamplerInstrumentList::contextMenuEvent (
539 QContextMenuEvent *pContextMenuEvent )
540 {
541 if (!m_pNewItemAction->isEnabled())
542 return;
543
544 QPopupMenu menu(this);
545
546 // Construct context menu.
547 m_pNewItemAction->addTo(&menu);
548 // m_pNewGroupAction->addTo(&menu);
549 menu.insertSeparator();
550 m_pEditItemAction->addTo(&menu);
551 m_pRenameAction->addTo(&menu);
552 m_pDeleteAction->addTo(&menu);
553 menu.insertSeparator();
554 m_pRefreshAction->addTo(&menu);
555
556 menu.exec(pContextMenuEvent->globalPos());
557 }
558
559
560 // General reloader.
561 void qsamplerInstrumentList::refresh (void)
562 {
563 clear();
564
565 qsamplerMainForm *pMainForm = qsamplerMainForm::getInstance();
566 if (pMainForm == NULL)
567 return;
568 if (pMainForm->client() == NULL)
569 return;
570
571 qsamplerInstrumentItem *pItem = NULL;
572 lscp_midi_instrument_t *pInstrs
573 = ::lscp_list_midi_instruments(pMainForm->client(), LSCP_MIDI_MAP_ALL);
574 for (int iInstr = 0; pInstrs && pInstrs[iInstr].prog >= 0; ++iInstr) {
575 int iMap = pInstrs[iInstr].map;
576 int iBank = pInstrs[iInstr].bank;
577 int iProg = pInstrs[iInstr].prog;
578 qsamplerInstrument *pInstrument
579 = new qsamplerInstrument(iMap, iBank, iProg);
580 if (pInstrument->getInstrument())
581 pItem = new qsamplerInstrumentItem(this, pInstrument, pItem);
582 }
583
584 if (pInstrs == NULL && ::lscp_client_get_errno(pMainForm->client())) {
585 pMainForm->appendMessagesClient("lscp_list_midi_instruments");
586 pMainForm->appendMessagesError(tr("Could not get current list of MIDI instrument mappings.\n\nSorry."));
587 }
588
589 selectionChangedSlot();
590 }
591
592
593 // end of qsamplerInstrumentList.cpp
594

  ViewVC Help
Powered by ViewVC