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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 980 - (hide annotations) (download)
Sun Dec 17 22:29:29 2006 UTC (17 years, 4 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 capela 971 // 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 capela 972 #ifndef CONFIG_ROUND
38 capela 980 static inline long lroundf ( float x )
39 capela 971 {
40 capela 980 if (x >= 0.0f)
41     return long(x + 0.5f);
42     else
43     return long(x - 0.5f);
44 capela 971 }
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 capela 980 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 capela 971 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 capela 980 setText(8, sLoadMode);
210 capela 971 } 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 capela 980 QListView::addColumn(tr("Map"));
237 capela 971 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 capela 980 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 capela 971
251 capela 980 QListView::setColumnWidth(0, 120); // Name
252     QListView::setColumnWidth(5, 240); // File
253 capela 971
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 capela 980 && pItem->instrument()->map() == pInstrument->map()
374 capela 971 && pItem->instrument()->bank() == pInstrument->bank()
375 capela 980 && pItem->instrument()->prog() == pInstrument->prog())
376 capela 971 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 capela 980 pInstrument->mapInstrument();
431 capela 971 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 capela 980 pItem->instrument()->mapInstrument();
457 capela 971 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 capela 980 pItem->instrument()->unmapInstrument();
488 capela 971 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 capela 980 pItem->instrument()->mapInstrument();
530 capela 971 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 capela 980 = ::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 capela 971 qsamplerInstrument *pInstrument
579 capela 980 = new qsamplerInstrument(iMap, iBank, iProg);
580     if (pInstrument->getInstrument())
581 capela 971 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