--- qsampler/trunk/src/qsamplerChannelStrip.ui.h 2004/06/08 18:40:06 118 +++ qsampler/trunk/src/qsamplerChannelStrip.ui.h 2005/02/20 19:13:33 395 @@ -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,9 +22,11 @@ #include #include +#include #include #include #include +#include #include @@ -33,26 +35,18 @@ #include "config.h" +// Channel status/usage usage limit control. +#define QSAMPLER_ERROR_LIMIT 3 +#define QSAMPLER_ERROR_CYCLE 33 + // 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.8; - + m_pChannel = NULL; m_iDirtyChange = 0; + m_iErrorCount = 0; // Try to restore normal window positioning. adjustSize(); @@ -62,343 +56,235 @@ // 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; + if (m_pChannel == NULL) + return false; - setChannelID(iChannelID); + 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 = (*iter).stripWhiteSpace().replace(QRegExp("^file:"), QString::null); + 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) -{ - return m_iChannelID; -} - -void qsamplerChannelStrip::setChannelID ( int iChannelID ) +// Channel strip setup formal initializer. +void qsamplerChannelStrip::setup ( qsamplerChannel *pChannel ) { - m_iChannelID = iChannelID; + // Destroy any previous channel descriptor; + // (remember that once setup we own it!) + if (m_pChannel) + delete m_pChannel; + // 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) -{ - return m_iInstrumentNr; -} - -bool qsamplerChannelStrip::loadInstrument ( const QString& sInstrumentFile, int iInstrumentNr ) -{ - 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; -} - - -// MIDI driver type accessors (DEPRECATED). -QString& qsamplerChannelStrip::midiDriver (void) -{ - return m_sMidiDriver; -} - -bool qsamplerChannelStrip::setMidiDriver ( const QString& sMidiDriver ) -{ - if (client() == NULL) - return false; - - if (::lscp_set_channel_midi_type(client(), m_iChannelID, sMidiDriver.latin1()) != LSCP_OK) { - appendMessagesClient("lscp_set_channel_midi_type"); - return false; - } - - m_sMidiDriver = sMidiDriver; - return true; -} - - -// MIDI device accessors. -int qsamplerChannelStrip::midiDevice (void) +// Messages view font accessors. +QFont qsamplerChannelStrip::displayFont (void) { - return m_iMidiDevice; + return EngineNameTextLabel->font(); } -bool qsamplerChannelStrip::setMidiDevice ( int iMidiDevice ) +void qsamplerChannelStrip::setDisplayFont ( const QFont & font ) { - 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; + EngineNameTextLabel->setFont(font); + MidiPortChannelTextLabel->setFont(font); + InstrumentNameTextLabel->setFont(font); + InstrumentStatusTextLabel->setFont(font); } -// MIDI port number accessor. -int qsamplerChannelStrip::midiPort (void) -{ - return m_iMidiPort; -} - -bool qsamplerChannelStrip::setMidiPort ( int iMidiPort ) +// Channel display background effect. +void qsamplerChannelStrip::setDisplayEffect ( bool bDisplayEffect ) { - if (client() == NULL) - return false; - -// 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; + QPixmap pm; + if (bDisplayEffect) + pm = QPixmap::fromMimeSource("displaybg1.png"); + setDisplayBackground(pm); } -// MIDI channel accessor. -int qsamplerChannelStrip::midiChannel (void) +// Update main display background pixmap. +void qsamplerChannelStrip::setDisplayBackground ( const QPixmap& pm ) { - return m_iMidiChannel; -} - -bool qsamplerChannelStrip::setMidiChannel ( int iMidiChannel ) -{ - if (client() == NULL) - return false; + // Set the main origin... + ChannelInfoFrame->setPaletteBackgroundPixmap(pm); -// 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; + // 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; + } + + // And this standalone too. + StreamVoiceCountTextLabel->setPaletteBackgroundPixmap(pm); } -// Audio device accessor. -int qsamplerChannelStrip::audioDevice (void) -{ - return m_iAudioDevice; -} - -bool qsamplerChannelStrip::setAudioDevice ( int iAudioDevice ) +// Maximum volume slider accessors. +void qsamplerChannelStrip::setMaxVolume ( int iMaxVolume ) { - if (client() == NULL) - return false; - -// 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; -// } - - m_iAudioDevice = iAudioDevice; - return true; + m_iDirtyChange++; + VolumeSlider->setRange(0, iMaxVolume); + VolumeSpinBox->setRange(0, iMaxVolume); + m_iDirtyChange--; } -// Audio driver type accessors (DEPRECATED). -QString& qsamplerChannelStrip::audioDriver (void) -{ - return m_sAudioDriver; -} - -bool qsamplerChannelStrip::setAudioDriver ( const QString& sAudioDriver ) +// Channel setup dialog slot. +bool qsamplerChannelStrip::channelSetup (void) { - if (client() == NULL) - return false; + // Invoke the channel setup dialog. + bool bResult = m_pChannel->channelSetup(this); - if (::lscp_set_channel_audio_type(client(), m_iChannelID, sAudioDriver.latin1()) != LSCP_OK) { - appendMessagesClient("lscp_set_channel_audio_type"); - return false; - } + if (bResult) { + // Reset the error/cycle. + m_iErrorCount = 0; + // Notify that thie channel has changed. + emit channelChanged(this); + } - m_sAudioDriver = sAudioDriver; - return true; + return bResult; } -// Channel volume accessors. -float qsamplerChannelStrip::volume (void) +// Update the channel instrument name. +bool qsamplerChannelStrip::updateInstrumentName ( bool bForce ) { - return m_fVolume; -} - -bool qsamplerChannelStrip::setVolume ( float fVolume ) -{ - if (client() == NULL) - return false; - - if (::lscp_set_channel_volume(client(), m_iChannelID, fVolume) != LSCP_OK) { - appendMessagesClient("lscp_set_channel_volume"); - return false; - } - - m_fVolume = fVolume; - return true; -} + if (m_pChannel == NULL) + return false; + // Do we refersh the actual name? + if (bForce) + m_pChannel->updateInstrumentName(); -// 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); -} + // Instrument name... + if (m_pChannel->instrumentName().isEmpty()) + InstrumentNameTextLabel->setText(' ' + qsamplerChannel::noInstrumentName()); + else + InstrumentNameTextLabel->setText(' ' + m_pChannel->instrumentName()); -// Channel setup dialog. -void qsamplerChannelStrip::channelSetup (void) -{ - qsamplerChannelForm *pChannelForm = new qsamplerChannelForm(this); - if (pChannelForm) { - pChannelForm->setup(this); - if (pChannelForm->exec()) { - updateChannelInfo(); - emit channelChanged(this); - } - delete pChannelForm; - } + return true; } // Update whole channel info state. -void qsamplerChannelStrip::updateChannelInfo (void) +bool qsamplerChannelStrip::updateChannelInfo (void) { + if (m_pChannel == NULL) + return false; + // 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); + + // Instrument status... + int iInstrumentStatus = m_pChannel->instrumentStatus(); + if (iInstrumentStatus < 0) { + InstrumentStatusTextLabel->setPaletteForegroundColor(Qt::red); + InstrumentStatusTextLabel->setText(tr("ERR%1").arg(iInstrumentStatus)); + } else { + InstrumentStatusTextLabel->setPaletteForegroundColor(iInstrumentStatus < 100 ? Qt::yellow : Qt::green); + InstrumentStatusTextLabel->setText(QString::number(iInstrumentStatus) + "%"); + } // MIDI Port/Channel... - MidiPortChannelTextLabel->setText(QString("%1 / %2") - .arg(m_iMidiPort).arg(m_iMidiChannel)); - + if (m_pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL) + MidiPortChannelTextLabel->setText(QString("%1 / *").arg(m_pChannel->midiPort())); + else + MidiPortChannelTextLabel->setText(QString("%1 / %2").arg(m_pChannel->midiPort()).arg(m_pChannel->midiChannel() + 1)); + // And update the both GUI volume elements. - updateChannelVolume(); + return updateChannelVolume(); } // Do the dirty volume change. -void qsamplerChannelStrip::updateChannelVolume (void) +bool qsamplerChannelStrip::updateChannelVolume (void) { + if (m_pChannel == NULL) + return false; + // Convert... #ifdef CONFIG_ROUND - int iVolume = (int) ::round(100.0 * m_fVolume); + int iVolume = (int) ::round(100.0 * m_pChannel->volume()); #else double fIPart = 0.0; - double fFPart = ::modf(100.0 * m_fVolume, &fIPart); + double fFPart = ::modf(100.0 * m_pChannel->volume(), &fIPart); int iVolume = (int) fIPart; if (fFPart >= +0.5) iVolume++; @@ -408,9 +294,7 @@ #endif // And clip... - if (iVolume > 100) - iVolume = 100; - else if (iVolume < 0) + if (iVolume < 0) iVolume = 0; // Flag it here, to avoid infinite recursion. @@ -418,95 +302,96 @@ VolumeSlider->setValue(iVolume); VolumeSpinBox->setValue(iVolume); m_iDirtyChange--; + + return true; } // 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; + // Check for error limit/recycle... + if (m_iErrorCount > QSAMPLER_ERROR_LIMIT) + m_iErrorCount -= QSAMPLER_ERROR_CYCLE; + if (m_iErrorCount < 0) { + m_iErrorCount++; + return false; + } + + // Update whole channel status info, + // if instrument load is still pending... + if (m_pChannel->instrumentStatus() < 100) { + // grab the whole sampler channel data... + updateChannelInfo(); + // Check (updated) status again... + int iInstrumentStatus = m_pChannel->instrumentStatus(); + if (iInstrumentStatus < 100) { + if (iInstrumentStatus < 0) + m_iErrorCount++; + return false; + } + // Once we get a complete instrument load, + // we'll try an implied channel reset... + m_pChannel->resetChannel(); + // Reset error count. + m_iErrorCount = 0; + } + // 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 ) -{ - m_pMainForm->appendMessages(s); -} - -void qsamplerChannelStrip::appendMessagesColor( const QString& s, const QString& c ) -{ - m_pMainForm->appendMessagesColor(s, c); -} - -void qsamplerChannelStrip::appendMessagesText( const QString& s ) -{ - m_pMainForm->appendMessagesText(s); -} - -void qsamplerChannelStrip::appendMessagesError( const QString& s ) -{ - m_pMainForm->appendMessagesError(s); -} - -void qsamplerChannelStrip::appendMessagesClient( const QString& s ) -{ - m_pMainForm->appendMessagesClient(s); -} - - // Context menu event handler. void qsamplerChannelStrip::contextMenuEvent( QContextMenuEvent *pEvent ) { - // We'll just show up the main form's edit menu. - m_pMainForm->stabilizeForm(); - m_pMainForm->editMenu->exec(pEvent->globalPos()); + if (m_pChannel == NULL) + return; + + // We'll just show up the main form's edit menu (thru qsamplerChannel). + m_pChannel->contextMenuEvent(pEvent); } // end of qsamplerChannelStrip.ui.h -