--- qsampler/trunk/src/qsamplerChannelStrip.ui.h 2004/06/05 11:37:06 109 +++ qsampler/trunk/src/qsamplerChannelStrip.ui.h 2005/05/29 16:28:01 590 @@ -2,7 +2,7 @@ // // ui.h extension file, included from the uic-generated form implementation. /**************************************************************************** - Copyright (C) 2004, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2004-2005, rncbc aka Rui Nuno Capela. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -22,8 +22,12 @@ #include #include +#include #include #include +#include +#include +#include #include @@ -32,26 +36,17 @@ #include "config.h" +// Channel status/usage usage limit control. +#define QSAMPLER_ERROR_LIMIT 3 + // Kind of constructor. void qsamplerChannelStrip::init (void) { // Initialize locals. - m_pMainForm = NULL; - m_iChannelID = 0; - -// m_sEngineName = "(No engine)"; -// m_sInstrumentFile = "(No instrument)"; - m_iInstrumentNr = 0; - m_sMidiDriver = "ALSA"; // DEPRECATED. - m_iMidiDevice = 0; - m_iMidiPort = 0; - m_iMidiChannel = 0; - m_sAudioDriver = "ALSA"; // DEPRECATED. - m_iAudioDevice = 0; - m_fVolume = 0.0; - + m_pChannel = NULL; m_iDirtyChange = 0; + m_iErrorCount = 0; // Try to restore normal window positioning. adjustSize(); @@ -61,442 +56,351 @@ // Kind of destructor. void qsamplerChannelStrip::destroy (void) { + // Destroy existing channel descriptor. + if (m_pChannel) + delete m_pChannel; + m_pChannel = NULL; } -// Channel strip setup formal initializer. -void qsamplerChannelStrip::setup ( qsamplerMainForm *pMainForm, int iChannelID ) +// Drag'n'drop file handler. +bool qsamplerChannelStrip::decodeDragFile ( const QMimeSource *pEvent, QString& sInstrumentFile ) { - m_iDirtyChange = 0; - m_pMainForm = pMainForm; - - setChannelID(iChannelID); + if (m_pChannel == NULL) + return false; + if (QTextDrag::canDecode(pEvent)) { + QString sText; + if (QTextDrag::decode(pEvent, sText)) { + QStringList files = QStringList::split('\n', sText); + for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++) { + *iter = QUrl((*iter).stripWhiteSpace().replace(QRegExp("^file:"), QString::null)).path(); + if (qsamplerChannel::isInstrumentFile(*iter)) { + sInstrumentFile = *iter; + return true; + } + } + } + } + // Fail. + return false; } -// The global options settings delegated property. -qsamplerOptions *qsamplerChannelStrip::options (void) +// Window drag-n-drop event handlers. +void qsamplerChannelStrip::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent ) { - if (m_pMainForm == NULL) - return NULL; - - return m_pMainForm->options(); + QString sInstrumentFile; + pDragEnterEvent->accept(decodeDragFile(pDragEnterEvent, sInstrumentFile)); } -// The client descriptor delegated property. -lscp_client_t *qsamplerChannelStrip::client (void) +void qsamplerChannelStrip::dropEvent ( QDropEvent* pDropEvent ) { - if (m_pMainForm == NULL) - return NULL; + QString sInstrumentFile; - return m_pMainForm->client(); + if (decodeDragFile(pDropEvent, sInstrumentFile)) { + // Go and set the dropped instrument filename... + m_pChannel->setInstrument(sInstrumentFile, 0); + // Open up the channel dialog. + channelSetup(); + } } -// Channel-ID (aka Sammpler-Channel) accessors. -int qsamplerChannelStrip::channelID (void) +// Channel strip setup formal initializer. +void qsamplerChannelStrip::setup ( qsamplerChannel *pChannel ) { - return m_iChannelID; -} + // Destroy any previous channel descriptor; + // (remember that once setup we own it!) + if (m_pChannel) + delete m_pChannel; -void qsamplerChannelStrip::setChannelID ( int iChannelID ) -{ - m_iChannelID = iChannelID; + // Set the new one... + m_pChannel = pChannel; + // Stabilize this around. updateChannelInfo(); -} - -// Engine name accessors. -QString& qsamplerChannelStrip::engineName (void) -{ - return m_sEngineName; + // We'll accept drops from now on... + if (m_pChannel) + setAcceptDrops(true); } -bool qsamplerChannelStrip::loadEngine ( const QString& sEngineName ) +// Channel secriptor accessor. +qsamplerChannel *qsamplerChannelStrip::channel (void) { - if (client() == NULL) - return false; - - if (::lscp_load_engine(client(), sEngineName.latin1(), m_iChannelID) != LSCP_OK) { - appendMessagesClient("lscp_load_engine"); - return false; - } - - m_sEngineName = sEngineName; - return true; + return m_pChannel; } -// Instrument filename accessors. -QString& qsamplerChannelStrip::instrumentFile (void) -{ - return m_sInstrumentFile; -} - -// Instrument index accessors. -int qsamplerChannelStrip::instrumentNr (void) +// Messages view font accessors. +QFont qsamplerChannelStrip::displayFont (void) { - return m_iInstrumentNr; + return EngineNameTextLabel->font(); } -bool qsamplerChannelStrip::loadInstrument ( const QString& sInstrumentFile, int iInstrumentNr ) +void qsamplerChannelStrip::setDisplayFont ( const QFont & font ) { - if (client() == NULL) - return false; - - if (::lscp_load_instrument(client(), sInstrumentFile.latin1(), iInstrumentNr, m_iChannelID) != LSCP_OK) { - appendMessagesClient("lscp_load_instrument"); - return false; - } - - m_sInstrumentFile = sInstrumentFile; - m_iInstrumentNr = iInstrumentNr; - return true; + EngineNameTextLabel->setFont(font); + MidiPortChannelTextLabel->setFont(font); + InstrumentNameTextLabel->setFont(font); + InstrumentStatusTextLabel->setFont(font); } -// MIDI driver type accessors (DEPRECATED). -QString& qsamplerChannelStrip::midiDriver (void) +// Channel display background effect. +void qsamplerChannelStrip::setDisplayEffect ( bool bDisplayEffect ) { - return m_sMidiDriver; + QPixmap pm; + if (bDisplayEffect) + pm = QPixmap::fromMimeSource("displaybg1.png"); + setDisplayBackground(pm); } -bool qsamplerChannelStrip::setMidiDriver ( const QString& sMidiDriver ) + +// Update main display background pixmap. +void qsamplerChannelStrip::setDisplayBackground ( const QPixmap& pm ) { - if (client() == NULL) - return false; + // Set the main origin... + ChannelInfoFrame->setPaletteBackgroundPixmap(pm); - if (::lscp_set_channel_midi_type(client(), m_iChannelID, sMidiDriver.latin1()) != LSCP_OK) { - appendMessagesClient("lscp_set_channel_midi_type"); - return false; + // Iterate for every child text label... + QObjectList *pList = ChannelInfoFrame->queryList("QLabel"); + if (pList) { + for (QLabel *pLabel = (QLabel *) pList->first(); pLabel; pLabel = (QLabel *) pList->next()) + pLabel->setPaletteBackgroundPixmap(pm); + delete pList; } - m_sMidiDriver = sMidiDriver; - return true; + // And this standalone too. + StreamVoiceCountTextLabel->setPaletteBackgroundPixmap(pm); } -// MIDI device accessors. -int qsamplerChannelStrip::midiDevice (void) +// Maximum volume slider accessors. +void qsamplerChannelStrip::setMaxVolume ( int iMaxVolume ) { - return m_iMidiDevice; -} - -bool qsamplerChannelStrip::setMidiDevice ( int iMidiDevice ) -{ - if (client() == NULL) - return false; - -// FIXME: call this when LSCP becomes stable. -// if (::lscp_set_channel_midi_device(client(), m_iChannelID, iMidiDevice) != LSCP_OK) { -// appendMessagesClient("lscp_set_channel_midi_device"); -// return false; -// } - - m_iMidiDevice = iMidiDevice; - return true; + m_iDirtyChange++; + VolumeSlider->setRange(0, iMaxVolume); + VolumeSpinBox->setRange(0, iMaxVolume); + m_iDirtyChange--; } -// MIDI port number accessor. -int qsamplerChannelStrip::midiPort (void) -{ - return m_iMidiPort; -} - -bool qsamplerChannelStrip::setMidiPort ( int iMidiPort ) +// Channel setup dialog slot. +bool qsamplerChannelStrip::channelSetup (void) { - if (client() == NULL) - return false; + if (m_pChannel == NULL) + return false; + + // Invoke the channel setup dialog. + bool bResult = m_pChannel->channelSetup(this); + // Notify that this channel has changed. + if (bResult) + emit channelChanged(this); -// FIXME: call this when LSCP becomes stable. -// if (::lscp_set_channel_midi_port(client(), m_iChannelID, iMidiPort) != LSCP_OK) { -// appendMessagesClient("lscp_set_channel_midi_port"); -// return false; -// } - - m_iMidiPort = iMidiPort; - return true; + return bResult; } -// MIDI channel accessor. -int qsamplerChannelStrip::midiChannel (void) +// Channel reset slot. +bool qsamplerChannelStrip::channelReset (void) { - return m_iMidiChannel; -} + if (m_pChannel == NULL) + return false; -bool qsamplerChannelStrip::setMidiChannel ( int iMidiChannel ) -{ - if (client() == NULL) - return false; + // Invoke the channel reset method. + bool bResult = m_pChannel->channelReset(); + // Notify that this channel has changed. + if (bResult) + emit channelChanged(this); -// FIXME: call this when LSCP becomes stable. -// if (::lscp_set_channel_midi_channel(client(), m_iChannelID, iMidiChannel) != LSCP_OK) { -// appendMessagesClient("lscp_set_channel_midi_channel"); -// return false; -// } - - m_iMidiChannel = iMidiChannel; - return true; + return bResult; } -// Audio device accessor. -int qsamplerChannelStrip::audioDevice (void) +// Update the channel instrument name. +bool qsamplerChannelStrip::updateInstrumentName ( bool bForce ) { - return m_iAudioDevice; -} + if (m_pChannel == NULL) + return false; -bool qsamplerChannelStrip::setAudioDevice ( int iAudioDevice ) -{ - if (client() == NULL) - return false; + // Do we refresh the actual name? + if (bForce) + m_pChannel->updateInstrumentName(); -// FIXME: call this when LSCP becomes stable. -// if (::lscp_set_channel_audio_device(client(), m_iChannelID, iAudioDevice) != LSCP_OK) { -// appendMessagesClient("lscp_set_channel_audio_device"); -// return false; -// } + // Instrument name... + if (m_pChannel->instrumentName().isEmpty()) { + if (m_pChannel->instrumentStatus() >= 0) + InstrumentNameTextLabel->setText(' ' + qsamplerChannel::loadingInstrument()); + else + InstrumentNameTextLabel->setText(' ' + qsamplerChannel::noInstrumentName()); + } else + InstrumentNameTextLabel->setText(' ' + m_pChannel->instrumentName()); - m_iAudioDevice = iAudioDevice; - return true; + return true; } -// Audio driver type accessors (DEPRECATED). -QString& qsamplerChannelStrip::audioDriver (void) -{ - return m_sAudioDriver; -} - -bool qsamplerChannelStrip::setAudioDriver ( const QString& sAudioDriver ) +// Do the dirty volume change. +bool qsamplerChannelStrip::updateChannelVolume (void) { - if (client() == NULL) - return false; - - if (::lscp_set_channel_audio_type(client(), m_iChannelID, sAudioDriver.latin1()) != LSCP_OK) { - appendMessagesClient("lscp_set_channel_audio_type"); + if (m_pChannel == NULL) return false; - } - - m_sAudioDriver = sAudioDriver; - return true; -} - -// Channel volume accessors. -float qsamplerChannelStrip::volume (void) -{ - return m_fVolume; -} + // Convert... +#ifdef CONFIG_ROUND + int iVolume = (int) ::round(100.0 * m_pChannel->volume()); +#else + double fIPart = 0.0; + double fFPart = ::modf(100.0 * m_pChannel->volume(), &fIPart); + int iVolume = (int) fIPart; + if (fFPart >= +0.5) + iVolume++; + else + if (fFPart <= -0.5) + iVolume--; +#endif -bool qsamplerChannelStrip::setVolume ( float fVolume ) -{ - if (client() == NULL) - return false; + // And clip... + if (iVolume < 0) + iVolume = 0; - if (::lscp_set_channel_volume(client(), m_iChannelID, fVolume) != LSCP_OK) { - appendMessagesClient("lscp_set_channel_volume"); - return false; - } + // Flag it here, to avoid infinite recursion. + m_iDirtyChange++; + VolumeSlider->setValue(iVolume); + VolumeSpinBox->setValue(iVolume); + m_iDirtyChange--; - m_fVolume = fVolume; return true; } -// Messages view font accessors. -QFont qsamplerChannelStrip::displayFont (void) -{ - return EngineNameTextLabel->font(); -} - -void qsamplerChannelStrip::setDisplayFont ( const QFont & font ) -{ - EngineNameTextLabel->setFont(font); - InstrumentNameTextLabel->setFont(font); - MidiPortChannelTextLabel->setFont(font); -} - -// Channel setup dialog. -void qsamplerChannelStrip::channelSetup (void) +// Update whole channel info state. +bool qsamplerChannelStrip::updateChannelInfo (void) { - qsamplerChannelForm *pChannelForm = new qsamplerChannelForm(this); - if (pChannelForm) { - pChannelForm->setup(this); - if (pChannelForm->exec()) { - updateChannelInfo(); - emit channelChanged(this); - } - delete pChannelForm; - } -} + if (m_pChannel == NULL) + return false; + // Check for error limit/recycle... + if (m_iErrorCount > QSAMPLER_ERROR_LIMIT) + return true; -// Update whole channel info state. -void qsamplerChannelStrip::updateChannelInfo (void) -{ // Update strip caption. - QString sText = tr("Channel %1").arg(m_iChannelID); + QString sText = m_pChannel->channelName(); setCaption(sText); ChannelSetupPushButton->setText(sText); // Check if we're up and connected. - if (client() == NULL) - return; - - // Read channel information. - lscp_channel_info_t *pChannelInfo = ::lscp_get_channel_info(client(), m_iChannelID); - if (pChannelInfo == NULL) { - appendMessagesClient("lscp_get_channel_info"); - // appendMessagesError(tr("Could not get channel information.\n\nSorry.")); - } else { - // Cache in channel information. - m_sEngineName = pChannelInfo->engine_name; - m_sInstrumentFile = pChannelInfo->instrument_file; - m_iInstrumentNr = pChannelInfo->instrument_nr; - m_iMidiDevice = pChannelInfo->midi_device; - m_iMidiPort = pChannelInfo->midi_port; - m_iMidiChannel = pChannelInfo->midi_channel; - m_iAudioDevice = pChannelInfo->audio_device; - m_fVolume = pChannelInfo->volume; - } + if (m_pChannel->client() == NULL) + return false; - // Set some proper display values. + // Read actual channel information. + m_pChannel->updateChannelInfo(); // Engine name... - if (m_sEngineName.isEmpty()) - EngineNameTextLabel->setText(tr("(No engine)")); + if (m_pChannel->engineName().isEmpty()) + EngineNameTextLabel->setText(' ' + qsamplerChannel::noEngineName()); else - EngineNameTextLabel->setText(m_sEngineName); + EngineNameTextLabel->setText(' ' + m_pChannel->engineName()); - // Instrument name... - if (m_sInstrumentFile.isEmpty()) - InstrumentNameTextLabel->setText(tr("(No instrument)")); - else - InstrumentNameTextLabel->setText(QString("%1 [%2]") - .arg(QFileInfo(m_sInstrumentFile).fileName()).arg(m_iInstrumentNr)); + // Instrument name... + updateInstrumentName(false); // MIDI Port/Channel... - MidiPortChannelTextLabel->setText(QString("%1 / %2") - .arg(m_iMidiPort).arg(m_iMidiChannel)); - - // And update the both GUI volume elements. - updateChannelVolume(); -} - - -// Do the dirty volume change. -void qsamplerChannelStrip::updateChannelVolume (void) -{ - // Convert... -#ifdef CONFIG_ROUND - int iVolume = (int) ::round(100.0 * m_fVolume); -#else - double fIPart = 0.0; - double fFPart = ::modf(100.0 * m_fVolume, &fIPart); - int iVolume = (int) fIPart; - if (fFPart >= +0.5) - iVolume++; + if (m_pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL) + MidiPortChannelTextLabel->setText(QString("%1 / *").arg(m_pChannel->midiPort())); else - if (fFPart <= -0.5) - iVolume--; -#endif - - // And clip... - if (iVolume > 100) - iVolume = 100; - else if (iVolume < 0) - iVolume = 0; + MidiPortChannelTextLabel->setText(QString("%1 / %2").arg(m_pChannel->midiPort()).arg(m_pChannel->midiChannel() + 1)); - // Flag it here, to avoid infinite recursion. - m_iDirtyChange++; - VolumeSlider->setValue(iVolume); - VolumeSpinBox->setValue(iVolume); - m_iDirtyChange--; + // Instrument status... + int iInstrumentStatus = m_pChannel->instrumentStatus(); + if (iInstrumentStatus < 0) { + InstrumentStatusTextLabel->setPaletteForegroundColor(Qt::red); + InstrumentStatusTextLabel->setText(tr("ERR%1").arg(iInstrumentStatus)); + m_iErrorCount++; + return false; + } + // All seems normal... + InstrumentStatusTextLabel->setPaletteForegroundColor(iInstrumentStatus < 100 ? Qt::yellow : Qt::green); + InstrumentStatusTextLabel->setText(QString::number(iInstrumentStatus) + '%'); + m_iErrorCount = 0; + + // And update the both GUI volume elements; + // return success if, and only if, intrument is fully loaded... + return updateChannelVolume() && (iInstrumentStatus == 100); } // Update whole channel usage state. -void qsamplerChannelStrip::updateChannelUsage (void) +bool qsamplerChannelStrip::updateChannelUsage (void) { - if (client() == NULL) - return; + if (m_pChannel == NULL) + return false; + if (m_pChannel->client() == NULL) + return false; + + // This only makes sense on fully loaded channels... + if (m_pChannel->instrumentStatus() < 100) + return false; // Get current channel voice count. - int iVoiceCount = ::lscp_get_channel_voice_count(client(), m_iChannelID); + int iVoiceCount = ::lscp_get_channel_voice_count(m_pChannel->client(), m_pChannel->channelID()); // Get current stream count. - int iStreamCount = ::lscp_get_channel_stream_count(client(), m_iChannelID); + int iStreamCount = ::lscp_get_channel_stream_count(m_pChannel->client(), m_pChannel->channelID()); // Get current channel buffer fill usage. // As benno has suggested this is the percentage usage // of the least filled buffer stream... - int iStreamUsage = 0; - if (iStreamCount > 0) { - lscp_buffer_fill_t *pBufferFill = ::lscp_get_channel_buffer_fill(client(), LSCP_USAGE_PERCENTAGE, m_iChannelID); - if (pBufferFill) { - for (int iStream = 0; iStream < iStreamCount; iStream++) { - if (iStreamUsage > (int) pBufferFill[iStream].stream_usage || iStream == 0) - iStreamUsage = pBufferFill[iStream].stream_usage; - } - } - } + int iStreamUsage = ::lscp_get_channel_stream_usage(m_pChannel->client(), m_pChannel->channelID());; + // Update the GUI elements... StreamUsageProgressBar->setProgress(iStreamUsage); StreamVoiceCountTextLabel->setText(QString("%1 / %2").arg(iStreamCount).arg(iVoiceCount)); + + // We're clean. + return true; } // Volume change slot. void qsamplerChannelStrip::volumeChanged ( int iVolume ) { + if (m_pChannel == NULL) + return; + // Avoid recursion. if (m_iDirtyChange > 0) return; // Convert and clip. float fVolume = (float) iVolume / 100.0; - if (fVolume > 1.0) - fVolume = 1.0; - else if (fVolume < 0.0) + if (fVolume < 0.001) fVolume = 0.0; // Update the GUI elements. - if (setVolume(fVolume)) { + if (m_pChannel->setVolume(fVolume)) { updateChannelVolume(); emit channelChanged(this); } } -// Redirected messages output methods. -void qsamplerChannelStrip::appendMessages( const QString& s ) +// Context menu event handler. +void qsamplerChannelStrip::contextMenuEvent( QContextMenuEvent *pEvent ) { - m_pMainForm->appendMessages(s); -} - -void qsamplerChannelStrip::appendMessagesColor( const QString& s, const QString& c ) -{ - m_pMainForm->appendMessagesColor(s, c); -} + if (m_pChannel == NULL) + return; -void qsamplerChannelStrip::appendMessagesText( const QString& s ) -{ - m_pMainForm->appendMessagesText(s); + // We'll just show up the main form's edit menu (thru qsamplerChannel). + m_pChannel->contextMenuEvent(pEvent); } -void qsamplerChannelStrip::appendMessagesError( const QString& s ) -{ - m_pMainForm->appendMessagesError(s); -} -void qsamplerChannelStrip::appendMessagesClient( const QString& s ) +// Error count hackish accessors. +void qsamplerChannelStrip::resetErrorCount (void) { - m_pMainForm->appendMessagesClient(s); + m_iErrorCount = 0; } // end of qsamplerChannelStrip.ui.h -