From 3aaa7ac6c45d0d63c1fa5a439ac9ab4eb7870e10 Mon Sep 17 00:00:00 2001 From: Garrett Date: Sun, 2 Nov 2014 21:27:30 -0800 Subject: [PATCH] Coding style fixes --- plugins/CMakeLists.txt | 2 +- .../{gig_player => GigPlayer}/CMakeLists.txt | 2 +- .../GigPlayer.cpp} | 373 ++++++++++------ .../gig_player.h => GigPlayer/GigPlayer.h} | 81 ++-- plugins/GigPlayer/PatchesDialog.cpp | 414 ++++++++++++++++++ .../PatchesDialog.h} | 36 +- .../PatchesDialog.ui} | 4 +- plugins/{gig_player => GigPlayer}/artwork.png | Bin .../fileselect_off.png | Bin .../fileselect_on.png | Bin plugins/{gig_player => GigPlayer}/logo.png | Bin .../{gig_player => GigPlayer}/patches_off.png | Bin .../{gig_player => GigPlayer}/patches_on.png | Bin plugins/gig_player/patches_dialog.cpp | 385 ---------------- 14 files changed, 720 insertions(+), 577 deletions(-) rename plugins/{gig_player => GigPlayer}/CMakeLists.txt (59%) rename plugins/{gig_player/gig_player.cpp => GigPlayer/GigPlayer.cpp} (73%) rename plugins/{gig_player/gig_player.h => GigPlayer/GigPlayer.h} (79%) create mode 100644 plugins/GigPlayer/PatchesDialog.cpp rename plugins/{gig_player/patches_dialog.h => GigPlayer/PatchesDialog.h} (66%) rename plugins/{gig_player/patches_dialog.ui => GigPlayer/PatchesDialog.ui} (98%) rename plugins/{gig_player => GigPlayer}/artwork.png (100%) rename plugins/{gig_player => GigPlayer}/fileselect_off.png (100%) rename plugins/{gig_player => GigPlayer}/fileselect_on.png (100%) rename plugins/{gig_player => GigPlayer}/logo.png (100%) rename plugins/{gig_player => GigPlayer}/patches_off.png (100%) rename plugins/{gig_player => GigPlayer}/patches_on.png (100%) delete mode 100644 plugins/gig_player/patches_dialog.cpp diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index bd073e6a2..91a1664f7 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -25,7 +25,7 @@ ADD_SUBDIRECTORY(peak_controller_effect) IF(NOT LMMS_BUILD_APPLE) ADD_SUBDIRECTORY(sf2_player) ENDIF() -ADD_SUBDIRECTORY(gig_player) +ADD_SUBDIRECTORY(GigPlayer) ADD_SUBDIRECTORY(sfxr) ADD_SUBDIRECTORY(sid) ADD_SUBDIRECTORY(SpectrumAnalyzer) diff --git a/plugins/gig_player/CMakeLists.txt b/plugins/GigPlayer/CMakeLists.txt similarity index 59% rename from plugins/gig_player/CMakeLists.txt rename to plugins/GigPlayer/CMakeLists.txt index 2eb71eca5..4be4dff82 100644 --- a/plugins/gig_player/CMakeLists.txt +++ b/plugins/GigPlayer/CMakeLists.txt @@ -8,6 +8,6 @@ if(LMMS_HAVE_GIG) LINK_DIRECTORIES(${GIG_LIBRARY_DIRS}) LINK_LIBRARIES(${GIG_LIBRARIES}) - BUILD_PLUGIN(gigplayer gig_player.cpp gig_player.h patches_dialog.cpp patches_dialog.h patches_dialog.ui MOCFILES gig_player.h patches_dialog.h UICFILES patches_dialog.ui EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") + BUILD_PLUGIN(gigplayer GigPlayer.cpp GigPlayer.h PatchesDialog.cpp PatchesDialog.h PatchesDialog.ui MOCFILES GigPlayer.h PatchesDialog.h UICFILES PatchesDialog.ui EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") endif(LMMS_HAVE_GIG) diff --git a/plugins/gig_player/gig_player.cpp b/plugins/GigPlayer/GigPlayer.cpp similarity index 73% rename from plugins/gig_player/gig_player.cpp rename to plugins/GigPlayer/GigPlayer.cpp index 11ed3c213..0eea3a6d0 100644 --- a/plugins/gig_player/gig_player.cpp +++ b/plugins/GigPlayer/GigPlayer.cpp @@ -1,5 +1,5 @@ /* - * gig_player.cpp - a gig player using libgig (based on sf2 player plugin) + * GigPlayer.cpp - a GIG player using libgig (based on Sf2 player plugin) * * Copyright (c) 2008 Paul Giblock * Copyright (c) 2009-2014 Tobias Doerffel @@ -35,15 +35,16 @@ #include #include "FileDialog.h" -#include "gig_player.h" +#include "GigPlayer.h" #include "engine.h" #include "InstrumentTrack.h" #include "InstrumentPlayHandle.h" #include "NotePlayHandle.h" #include "knob.h" #include "song.h" +#include "config_mgr.h" -#include "patches_dialog.h" +#include "PatchesDialog.h" #include "tooltip.h" #include "LcdSpinBox.h" @@ -69,6 +70,8 @@ Plugin::Descriptor PLUGIN_EXPORT gigplayer_plugin_descriptor = } + + struct GIGPluginData { int midiNote; @@ -76,14 +79,15 @@ struct GIGPluginData -gigInstrument::gigInstrument( InstrumentTrack * _instrument_track ) : + +GigInstrument::GigInstrument( InstrumentTrack * _instrument_track ) : Instrument( _instrument_track, &gigplayer_plugin_descriptor ), m_srcState( NULL ), m_instance( NULL ), m_instrument( NULL ), m_filename( "" ), - m_bankNum( 0, 0, 999, this, tr("Bank") ), - m_patchNum( 0, 0, 127, this, tr("Patch") ), + m_bankNum( 0, 0, 999, this, tr( "Bank" ) ), + m_patchNum( 0, 0, 127, this, tr( "Patch" ) ), m_gain( 1.0f, 0.0f, 5.0f, 0.01f, this, tr( "Gain" ) ), m_sampleData( NULL ), m_sampleDataSize( 0 ), @@ -107,21 +111,27 @@ gigInstrument::gigInstrument( InstrumentTrack * _instrument_track ) : -gigInstrument::~gigInstrument() + +GigInstrument::~GigInstrument() { if( m_sampleData != NULL ) + { delete[] m_sampleData; + } engine::mixer()->removePlayHandles( instrumentTrack() ); freeInstance(); if( m_srcState != NULL ) + { src_delete( m_srcState ); + } } -void gigInstrument::saveSettings( QDomDocument & _doc, QDomElement & _this ) + +void GigInstrument::saveSettings( QDomDocument & _doc, QDomElement & _this ) { _this.setAttribute( "src", m_filename ); m_patchNum.saveSettings( _doc, _this, "patch" ); @@ -132,7 +142,8 @@ void gigInstrument::saveSettings( QDomDocument & _doc, QDomElement & _this ) -void gigInstrument::loadSettings( const QDomElement & _this ) + +void GigInstrument::loadSettings( const QDomElement & _this ) { openFile( _this.attribute( "src" ), false ); m_patchNum.loadSettings( _this, "patch" ); @@ -145,7 +156,8 @@ void gigInstrument::loadSettings( const QDomElement & _this ) -void gigInstrument::loadFile( const QString & _file ) + +void GigInstrument::loadFile( const QString & _file ) { if( !_file.isEmpty() && QFileInfo( _file ).exists() ) { @@ -157,12 +169,17 @@ void gigInstrument::loadFile( const QString & _file ) -AutomatableModel * gigInstrument::childModel( const QString & _modelName ) + +AutomatableModel * GigInstrument::childModel( const QString & _modelName ) { if( _modelName == "bank" ) + { return &m_bankNum; + } else if( _modelName == "patch" ) + { return &m_patchNum; + } qCritical() << "requested unknown model " << _modelName; @@ -171,17 +188,19 @@ AutomatableModel * gigInstrument::childModel( const QString & _modelName ) -QString gigInstrument::nodeName() const + +QString GigInstrument::nodeName() const { return gigplayer_plugin_descriptor.name; } -void gigInstrument::freeInstance() + +void GigInstrument::freeInstance() { - QMutexLocker synthLock(&m_synthMutex); - QMutexLocker notesLock(&m_notesMutex); + QMutexLocker synthLock( &m_synthMutex ); + QMutexLocker notesLock( &m_notesMutex ); if( m_instance != NULL ) { @@ -198,7 +217,8 @@ void gigInstrument::freeInstance() -void gigInstrument::openFile( const QString & _gigFile, bool updateTrackName ) + +void GigInstrument::openFile( const QString & _gigFile, bool updateTrackName ) { emit fileLoading(); @@ -206,7 +226,7 @@ void gigInstrument::openFile( const QString & _gigFile, bool updateTrackName ) freeInstance(); { - QMutexLocker locker(&m_synthMutex); + QMutexLocker locker( &m_synthMutex ); try { @@ -222,7 +242,7 @@ void gigInstrument::openFile( const QString & _gigFile, bool updateTrackName ) emit fileChanged(); - if( updateTrackName ) + if( updateTrackName == true ) { instrumentTrack()->setName( QFileInfo( _gigFile ).baseName() ); updatePatch(); @@ -231,19 +251,23 @@ void gigInstrument::openFile( const QString & _gigFile, bool updateTrackName ) -void gigInstrument::updatePatch() + +void GigInstrument::updatePatch() { if( m_bankNum.value() >= 0 && m_patchNum.value() >= 0 ) + { getInstrument(); + } } -QString gigInstrument::getCurrentPatchName() -{ - QMutexLocker locker(&m_synthMutex); - if( !m_instance ) +QString GigInstrument::getCurrentPatchName() +{ + QMutexLocker locker( &m_synthMutex ); + + if( m_instance == NULL ) { return ""; } @@ -251,19 +275,21 @@ QString gigInstrument::getCurrentPatchName() int iBankSelected = m_bankNum.value(); int iProgSelected = m_patchNum.value(); - gig::Instrument* pInstrument = m_instance->gig.GetFirstInstrument(); + gig::Instrument * pInstrument = m_instance->gig.GetFirstInstrument(); - while( pInstrument ) + while( pInstrument != NULL ) { int iBank = pInstrument->MIDIBank; int iProg = pInstrument->MIDIProgram; if( iBank == iBankSelected && iProg == iProgSelected ) { - QString name = QString::fromStdString(pInstrument->pInfo->Name); + QString name = QString::fromStdString( pInstrument->pInfo->Name ); if( name == "" ) + { name = ""; + } return name; } @@ -276,14 +302,15 @@ QString gigInstrument::getCurrentPatchName() + // A key has been pressed -void gigInstrument::playNote( NotePlayHandle * _n, sampleFrame * ) +void GigInstrument::playNote( NotePlayHandle * _n, sampleFrame * ) { const float LOG440 = 2.643452676f; const f_cnt_t tfp = _n->totalFramesPlayed(); - int midiNote = (int)floor( 12.0 * ( log2( _n->unpitchedFrequency() ) - LOG440 ) - 4.0 ); + int midiNote = (int) floor( 12.0 * ( log2( _n->unpitchedFrequency() ) - LOG440 ) - 4.0 ); // out of range? if( midiNote <= 0 || midiNote >= 128 ) @@ -300,26 +327,27 @@ void gigInstrument::playNote( NotePlayHandle * _n, sampleFrame * ) const int baseVelocity = instrumentTrack()->midiPort()->baseVelocity(); const uint velocity = _n->midiVelocity( baseVelocity ); - QMutexLocker locker(&m_notesMutex); - m_notes.push_back(GigNote(midiNote, velocity)); + QMutexLocker locker( &m_notesMutex ); + m_notes.push_back( GigNote( midiNote, velocity ) ); } } + // Process the notes and output a certain number of frames (e.g. 256, set in // the preferences) -void gigInstrument::play( sampleFrame * _working_buffer ) +void GigInstrument::play( sampleFrame * _working_buffer ) { const fpp_t frames = engine::mixer()->framesPerPeriod(); // Initialize to zeros - std::memset(&_working_buffer[0][0], 0, DEFAULT_CHANNELS*frames*sizeof(float)); + std::memset( &_working_buffer[0][0], 0, DEFAULT_CHANNELS * frames * sizeof( float ) ); m_synthMutex.lock(); m_notesMutex.lock(); - if( !m_instance || !m_instrument ) + if( m_instance == NULL || m_instrument == NULL ) { m_synthMutex.unlock(); m_notesMutex.unlock(); @@ -331,7 +359,7 @@ void gigInstrument::play( sampleFrame * _working_buffer ) int newRate = engine::mixer()->processingSampleRate(); bool sampleError = false; bool sampleConvert = false; - sampleFrame* convertBuf = NULL; + sampleFrame * convertBuf = NULL; // How many frames we'll be grabbing from the sample int samples = frames; @@ -353,30 +381,37 @@ void gigInstrument::play( sampleFrame * _working_buffer ) // Notify each sample that the key has been released for( QList::iterator sample = note->samples.begin(); sample != note->samples.end(); ++sample ) + { sample->adsr.keyup(); + } // Add release samples if available - if( note->release ) - addSamples(*note, true); + if( note->release == true ) + { + addSamples( *note, true ); + } } } // Process notes in the KeyDown state, adding samples for the notes else if( note->state == KeyDown ) { note->state = PlayingKeyDown; - addSamples(*note, false); + addSamples( *note, false ); } for( QList::iterator sample = note->samples.begin(); sample != note->samples.end(); ++sample ) { // Delete ended samples - if( !sample->sample || sample->adsr.done() || sample->pos >= sample->sample->SamplesTotal-1 ) + if( sample->sample == NULL || sample->adsr.done() || + sample->pos >= sample->sample->SamplesTotal - 1 ) { - sample = note->samples.erase(sample); + sample = note->samples.erase( sample ); if( sample == note->samples.end() ) + { break; + } } // Verify all the samples have the same rate else @@ -389,7 +424,7 @@ void gigInstrument::play( sampleFrame * _working_buffer ) } else if( oldRate != currentRate ) { - qCritical() << "gigInstrument: not all samples are the same rate, not converting"; + qCritical() << "GigInstrument: not all samples are the same rate, not converting"; sampleError = true; } } @@ -398,26 +433,28 @@ void gigInstrument::play( sampleFrame * _working_buffer ) // Delete ended notes (either in the completed state or all the samples ended) if( note->state == Completed || note->samples.empty() ) { - note = m_notes.erase(note); + note = m_notes.erase( note ); if( note == m_notes.end() ) + { break; + } } } // If all samples have the same sample rate and it's not the output sample // rate, then we'll convert sample rates - if( oldRate != -1 && !sampleError && oldRate != newRate ) + if( oldRate != -1 && sampleError != true && oldRate != newRate ) { sampleConvert = true; // Read a different number of samples depending on the sample rate, but // resample it to always output the right number of frames - samples = frames*oldRate/newRate; + samples = frames * oldRate / newRate; // Buffer for the resampled data convertBuf = new sampleFrame[samples]; - std::memset(&convertBuf[0][0], 0, DEFAULT_CHANNELS*samples*sizeof(float)); + std::memset( &convertBuf[0][0], 0, DEFAULT_CHANNELS * samples * sizeof( float ) ); } // Recreate buffer if it is of a different size @@ -432,26 +469,30 @@ void gigInstrument::play( sampleFrame * _working_buffer ) for( QList::iterator note = m_notes.begin(); note != m_notes.end(); ++note ) { // Only process the notes if we're in a playing state - if( !(note->state == PlayingKeyDown || - note->state == PlayingKeyUp) ) + if( !( note->state == PlayingKeyDown || + note->state == PlayingKeyUp ) ) + { continue; + } for( QList::iterator sample = note->samples.begin(); sample != note->samples.end(); ++sample ) { - if( !sample->sample ) + if( sample->sample == NULL ) + { continue; + } // Set the position to where we currently are in the sample - sample->sample->SetPos(sample->pos); // Note: not thread safe + sample->sample->SetPos( sample->pos ); // Note: not thread safe // Load the next portion of the sample gig::buffer_t buf; unsigned long allocationsize = samples * sample->sample->FrameSize; buf.pStart = new int8_t[allocationsize]; - buf.Size = sample->sample->Read(buf.pStart, samples) * sample->sample->FrameSize; + buf.Size = sample->sample->Read( buf.pStart, samples ) * sample->sample->FrameSize; buf.NullExtensionSize = allocationsize - buf.Size; - std::memset((int8_t*)buf.pStart + buf.Size, 0, buf.NullExtensionSize); + std::memset( (int8_t*) buf.pStart + buf.Size, 0, buf.NullExtensionSize ); // Save the new position in the sample sample->pos = sample->sample->GetPos(); @@ -459,17 +500,17 @@ void gigInstrument::play( sampleFrame * _working_buffer ) // Convert from 16 or 24 bit into 32-bit float if( sample->sample->BitDepth == 24 ) // 24 bit { - uint8_t* pInt = static_cast( buf.pStart ); + uint8_t * pInt = static_cast( buf.pStart ); for( int i = 0; i < samples; ++i ) { - int32_t valueLeft = (pInt[3*sample->sample->Channels*i]<<8) | - (pInt[3*sample->sample->Channels*i+1]<<16) | - (pInt[3*sample->sample->Channels*i+2]<<24); + int32_t valueLeft = ( pInt[ 3 * sample->sample->Channels * i ] << 8 ) | + ( pInt[ 3 * sample->sample->Channels * i + 1 ] << 16 ) | + ( pInt[ 3 * sample->sample->Channels * i + 2 ] << 24 ); // Store the notes to this buffer before saving to output // so we can fade them out as needed - m_sampleData[i][0] = 1.0/0x100000000*sample->attenuation*valueLeft; + m_sampleData[i][0] = 1.0 / 0x100000000 * sample->attenuation * valueLeft; if( sample->sample->Channels == 1 ) { @@ -477,31 +518,35 @@ void gigInstrument::play( sampleFrame * _working_buffer ) } else { - int32_t valueRight = (pInt[3*sample->sample->Channels*i+3]<<8) | - (pInt[3*sample->sample->Channels*i+4]<<16) | - (pInt[3*sample->sample->Channels*i+5]<<24); + int32_t valueRight = ( pInt[ 3 * sample->sample->Channels * i + 3 ] << 8 ) | + ( pInt[ 3 * sample->sample->Channels * i + 4 ] << 16 ) | + ( pInt[ 3 * sample->sample->Channels * i + 5 ] << 24 ); - m_sampleData[i][1] = 1.0/0x100000000*sample->attenuation*valueRight; + m_sampleData[i][1] = 1.0 / 0x100000000 * sample->attenuation * valueRight; } } } else // 16 bit { - int16_t* pInt = static_cast( buf.pStart ); + int16_t * pInt = static_cast( buf.pStart ); for( int i = 0; i < samples; ++i ) { - m_sampleData[i][0] = 1.0/0x10000*pInt[sample->sample->Channels*i] * sample->attenuation; + m_sampleData[i][0] = 1.0 / 0x10000 * pInt[ sample->sample->Channels * i ] * sample->attenuation; if( sample->sample->Channels == 1 ) + { m_sampleData[i][1] = m_sampleData[i][0]; + } else - m_sampleData[i][1] = 1.0/0x10000*pInt[sample->sample->Channels*i+1] * sample->attenuation; + { + m_sampleData[i][1] = 1.0 / 0x10000 * pInt[ sample->sample->Channels * i + 1 ] * sample->attenuation; + } } } // Cleanup - delete[] (int8_t*)buf.pStart; + delete[] (int8_t*) buf.pStart; // Apply ADSR for( int i = 0; i < samples; ++i ) @@ -536,8 +581,10 @@ void gigInstrument::play( sampleFrame * _working_buffer ) { // If an error occured, it's better to render nothing than have some // screetching high-volume noise - if( !convertSampleRate(*convertBuf, *_working_buffer, samples, frames, oldRate, newRate) ) - std::memset(&_working_buffer[0][0], 0, 2*frames*sizeof(float)); // *2 for channels + if( !convertSampleRate( *convertBuf, *_working_buffer, samples, frames, oldRate, newRate ) ) + { + std::memset( &_working_buffer[0][0], 0, DEFAULT_CHANNELS * frames * sizeof( float ) ); + } delete[] convertBuf; } @@ -557,18 +604,23 @@ void gigInstrument::play( sampleFrame * _working_buffer ) + // A key has been released -void gigInstrument::deleteNotePluginData( NotePlayHandle * _n ) +void GigInstrument::deleteNotePluginData( NotePlayHandle * _n ) { GIGPluginData * pluginData = static_cast( _n->m_pluginData ); - QMutexLocker locker(&m_notesMutex); + QMutexLocker locker( &m_notesMutex ); // Mark the note as being released, but only if it was playing or was just // pressed (i.e., not if the key was already released) for( QList::iterator i = m_notes.begin(); i != m_notes.end(); ++i ) + { if( i->midiNote == pluginData->midiNote && ( i->state == KeyDown || i->state == PlayingKeyDown ) ) + { i->state = KeyUp; + } + } // TODO: not sample exact? What about in the middle of us writing out the sample? @@ -577,44 +629,50 @@ void gigInstrument::deleteNotePluginData( NotePlayHandle * _n ) -PluginView * gigInstrument::instantiateView( QWidget * _parent ) + +PluginView * GigInstrument::instantiateView( QWidget * _parent ) { - return new gigInstrumentView( this, _parent ); + return new GigInstrumentView( this, _parent ); } + // Add the desired samples (either the normal samples or the release samples) // to the GigNote // // Note: not thread safe since libgig stores current region position data in // the instrument object -void gigInstrument::addSamples(GigNote& note, bool wantReleaseSample) +void GigInstrument::addSamples( GigNote & note, bool wantReleaseSample ) { // Change key dimension, e.g. change samples based on what key is pressed // in a certain range. From LinuxSampler - if( !wantReleaseSample && + if( wantReleaseSample == true && note.midiNote >= m_instrument->DimensionKeyRange.low && note.midiNote <= m_instrument->DimensionKeyRange.high ) + { m_currentKeyDimension = float( note.midiNote - m_instrument->DimensionKeyRange.low ) / ( m_instrument->DimensionKeyRange.high - m_instrument->DimensionKeyRange.low + 1 ); + } gig::Region* pRegion = m_instrument->GetFirstRegion(); - while( pRegion ) + while( pRegion != NULL ) { Dimension dim = getDimensions( pRegion, note.velocity, wantReleaseSample ); - gig::DimensionRegion* pDimRegion = pRegion->GetDimensionRegionByValue( dim.DimValues ); - gig::Sample* pSample = pDimRegion->pSample; + gig::DimensionRegion * pDimRegion = pRegion->GetDimensionRegionByValue( dim.DimValues ); + gig::Sample * pSample = pDimRegion->pSample; // Does this note have release samples? Set this only on the original // notes and not when we get the release samples. - if( !wantReleaseSample ) + if( wantReleaseSample != true ) + { note.release = dim.release; + } - if( pSample && pSample->SamplesTotal != 0 ) + if( pSample != NULL && pSample->SamplesTotal != 0 ) { int keyLow = pRegion->KeyRange.low; int keyHigh = pRegion->KeyRange.high; @@ -626,14 +684,18 @@ void gigInstrument::addSamples(GigNote& note, bool wantReleaseSample) // TODO: sample panning? looping? crossfade different layers? - if( wantReleaseSample ) + if( wantReleaseSample == true ) + { // From LinuxSampler, not sure how it was created - attenuation *= 1 - 0.01053 * (256 >> pDimRegion->ReleaseTriggerDecay) * length; + attenuation *= 1 - 0.01053 * ( 256 >> pDimRegion->ReleaseTriggerDecay ) * length; + } else + { attenuation *= pDimRegion->SampleAttenuation; + } - note.samples.push_back(GigSample(pSample, attenuation, - ADSR(pDimRegion, pSample->SamplesPerSecond))); + note.samples.push_back( GigSample( pSample, attenuation, + ADSR( pDimRegion, pSample->SamplesPerSecond ) ) ); } } @@ -643,15 +705,18 @@ void gigInstrument::addSamples(GigNote& note, bool wantReleaseSample) + // Based on our input parameters, generate a "dimension" that specifies which // note we wish to select from the GIG file with libgig. libgig will use this // information to select the sample. -Dimension gigInstrument::getDimensions( gig::Region* pRegion, int velocity, bool release ) +Dimension GigInstrument::getDimensions( gig::Region * pRegion, int velocity, bool release ) { Dimension dim; - if( !pRegion ) + if( pRegion == NULL ) + { return dim; + } for( int i = pRegion->Dimensions - 1; i >= 0; --i ) { @@ -669,7 +734,7 @@ Dimension gigInstrument::getDimensions( gig::Region* pRegion, int velocity, bool dim.DimValues[i] = (uint) release; break; case gig::dimension_keyboard: - dim.DimValues[i] = (uint) (m_currentKeyDimension * pRegion->pDimensionDefinitions[i].zones); + dim.DimValues[i] = (uint) ( m_currentKeyDimension * pRegion->pDimensionDefinitions[i].zones ); break; case gig::dimension_roundrobin: case gig::dimension_roundrobinkeyboard: @@ -680,7 +745,7 @@ Dimension gigInstrument::getDimensions( gig::Region* pRegion, int velocity, bool // From LinuxSampler, untested m_RandomSeed = m_RandomSeed * 1103515245 + 12345; dim.DimValues[i] = uint( - m_RandomSeed / 4294967296.0f * pRegion->pDimensionDefinitions[i].bits); + m_RandomSeed / 4294967296.0f * pRegion->pDimensionDefinitions[i].bits ); break; case gig::dimension_samplechannel: case gig::dimension_channelaftertouch: @@ -719,27 +784,30 @@ Dimension gigInstrument::getDimensions( gig::Region* pRegion, int velocity, bool + // Get the selected instrument from the GIG file we opened if we haven't gotten // it already. This is based on the bank and patch numbers. -void gigInstrument::getInstrument() +void GigInstrument::getInstrument() { // Find instrument int iBankSelected = m_bankNum.value(); int iProgSelected = m_patchNum.value(); - QMutexLocker locker(&m_synthMutex); + QMutexLocker locker( &m_synthMutex ); - if( m_instance ) + if( m_instance != NULL ) { - gig::Instrument* pInstrument = m_instance->gig.GetFirstInstrument(); + gig::Instrument * pInstrument = m_instance->gig.GetFirstInstrument(); - while( pInstrument ) + while( pInstrument != NULL ) { int iBank = pInstrument->MIDIBank; int iProg = pInstrument->MIDIProgram; if( iBank == iBankSelected && iProg == iProgSelected ) + { break; + } pInstrument = m_instance->gig.GetNextInstrument(); } @@ -750,7 +818,8 @@ void gigInstrument::getInstrument() -bool gigInstrument::convertSampleRate( sampleFrame& oldBuf, sampleFrame& newBuf, + +bool GigInstrument::convertSampleRate( sampleFrame & oldBuf, sampleFrame & newBuf, int oldSize, int newSize, int oldRate, int newRate ) { SRC_DATA src_data; @@ -765,15 +834,15 @@ bool gigInstrument::convertSampleRate( sampleFrame& oldBuf, sampleFrame& newBuf, int error = src_process( m_srcState, &src_data ); m_srcMutex.unlock(); - if( error ) + if( error != 0 ) { - qCritical( "gigInstrument: error while resampling: %s", src_strerror( error ) ); + qCritical( "GigInstrument: error while resampling: %s", src_strerror( error ) ); return false; } if( src_data.output_frames_gen > newSize ) { - qCritical( "gigInstrument: not enough frames: %ld / %d", src_data.output_frames_gen, newSize ); + qCritical( "GigInstrument: not enough frames: %ld / %d", src_data.output_frames_gen, newSize ); return false; } @@ -782,23 +851,29 @@ bool gigInstrument::convertSampleRate( sampleFrame& oldBuf, sampleFrame& newBuf, -void gigInstrument::updateSampleRate() + +void GigInstrument::updateSampleRate() { - QMutexLocker locker(&m_srcMutex); + QMutexLocker locker( &m_srcMutex ); if( m_srcState != NULL ) + { src_delete( m_srcState ); + } int error; m_srcState = src_new( engine::mixer()->currentQualitySettings().libsrcInterpolation(), DEFAULT_CHANNELS, &error ); - if( m_srcState == NULL || error ) - qCritical( "error while creating libsamplerate data structure in gigInstrument::updateSampleRate()" ); + if( m_srcState == NULL || error != 0 ) + { + qCritical( "error while creating libsamplerate data structure in GigInstrument::updateSampleRate()" ); + } } + class gigKnob : public knob { public: @@ -811,10 +886,11 @@ public: -gigInstrumentView::gigInstrumentView( Instrument * _instrument, QWidget * _parent ) : + +GigInstrumentView::GigInstrumentView( Instrument * _instrument, QWidget * _parent ) : InstrumentView( _instrument, _parent ) { - gigInstrument* k = castModel(); + GigInstrument * k = castModel(); connect( &k->m_bankNum, SIGNAL( dataChanged() ), this, SLOT( updatePatchName() ) ); connect( &k->m_patchNum, SIGNAL( dataChanged() ), this, SLOT( updatePatchName() ) ); @@ -846,10 +922,10 @@ gigInstrumentView::gigInstrumentView( Instrument * _instrument, QWidget * _paren // LCDs m_bankNumLcd = new LcdSpinBox( 3, "21pink", this ); - m_bankNumLcd->move(111, 150); + m_bankNumLcd->move( 111, 150 ); m_patchNumLcd = new LcdSpinBox( 3, "21pink", this ); - m_patchNumLcd->move(161, 150); + m_patchNumLcd->move( 161, 150 ); // Next row m_filenameLabel = new QLabel( this ); @@ -859,7 +935,7 @@ gigInstrumentView::gigInstrumentView( Instrument * _instrument, QWidget * _paren // Gain m_gainKnob = new gigKnob( this ); - m_gainKnob->setHintText( tr("Gain") + " ", "" ); + m_gainKnob->setHintText( tr( "Gain" ) + " ", "" ); m_gainKnob->move( 32, 140 ); setAutoFillBackground( true ); @@ -873,15 +949,17 @@ gigInstrumentView::gigInstrumentView( Instrument * _instrument, QWidget * _paren -gigInstrumentView::~gigInstrumentView() + +GigInstrumentView::~GigInstrumentView() { } -void gigInstrumentView::modelChanged() + +void GigInstrumentView::modelChanged() { - gigInstrument * k = castModel(); + GigInstrument * k = castModel(); m_bankNumLcd->setModel( &k->m_bankNum ); m_patchNumLcd->setModel( &k->m_patchNum ); @@ -895,9 +973,10 @@ void gigInstrumentView::modelChanged() -void gigInstrumentView::updateFilename() + +void GigInstrumentView::updateFilename() { - gigInstrument * i = castModel(); + GigInstrument * i = castModel(); QFontMetrics fm( m_filenameLabel->font() ); QString file = i->m_filename.endsWith( ".gig", Qt::CaseInsensitive ) ? i->m_filename.left( i->m_filename.length() - 4 ) : @@ -912,9 +991,10 @@ void gigInstrumentView::updateFilename() -void gigInstrumentView::updatePatchName() + +void GigInstrumentView::updatePatchName() { - gigInstrument * i = castModel(); + GigInstrument * i = castModel(); QFontMetrics fm( font() ); QString patch = i->getCurrentPatchName(); m_patchLabel->setText( fm.elidedText( patch, Qt::ElideLeft, m_patchLabel->width() ) ); @@ -924,16 +1004,18 @@ void gigInstrumentView::updatePatchName() -void gigInstrumentView::invalidateFile() + +void GigInstrumentView::invalidateFile() { m_patchDialogButton->setEnabled( false ); } -void gigInstrumentView::showFileDialog() + +void GigInstrumentView::showFileDialog() { - gigInstrument * k = castModel(); + GigInstrument * k = castModel(); FileDialog ofd( NULL, tr( "Open GIG file" ) ); ofd.setFileMode( FileDialog::ExistingFiles ); @@ -979,18 +1061,20 @@ void gigInstrumentView::showFileDialog() -void gigInstrumentView::showPatchDialog() + +void GigInstrumentView::showPatchDialog() { - gigInstrument * k = castModel(); - patchesDialog pd( this ); + GigInstrument * k = castModel(); + PatchesDialog pd( this ); pd.setup( k->m_instance, 1, k->instrumentTrack()->name(), &k->m_bankNum, &k->m_patchNum, m_patchLabel ); pd.exec(); } + // Store information related to playing a sample from the GIG file -GigSample::GigSample( gig::Sample* pSample, float attenuation, const ADSR& adsr ) +GigSample::GigSample( gig::Sample * pSample, float attenuation, const ADSR & adsr ) : sample( pSample ), attenuation( attenuation ), adsr( adsr ), @@ -1000,35 +1084,37 @@ GigSample::GigSample( gig::Sample* pSample, float attenuation, const ADSR& adsr + // Create the ADSR envelope from the settings in the GIG file -ADSR::ADSR( gig::DimensionRegion* region, int sampleRate ) - : preattack(0), attack(0), decay1(0), decay2(0), infiniteSustain(false), - sustain(0), release(0), - amplitude(0), isAttack(true), isRelease(false), isDone(false), - attackPosition(0), attackLength(0), decayLength(0), - releasePosition(0), releaseLength(0) +ADSR::ADSR( gig::DimensionRegion * region, int sampleRate ) + : preattack( 0 ), attack( 0 ), decay1( 0 ), decay2( 0 ), infiniteSustain( false ), + sustain( 0 ), release( 0 ), + amplitude( 0 ), isAttack( true ), isRelease( false ), isDone( false ), + attackPosition( 0 ), attackLength( 0 ), decayLength( 0 ), + releasePosition( 0 ), releaseLength( 0 ) { - if( region ) + if( region != NULL ) { // Parameters from GIG file - preattack = 1.0*region->EG1PreAttack/1000; // EG1PreAttack is 0-1000 permille + preattack = 1.0 * region->EG1PreAttack / 1000; // EG1PreAttack is 0-1000 permille attack = region->EG1Attack; decay1 = region->EG1Decay1; decay2 = region->EG1Decay2; infiniteSustain = region->EG1InfiniteSustain; - sustain = 1.0*region->EG1Sustain/1000; // EG1Sustain is 0-1000 permille + sustain = 1.0 * region->EG1Sustain / 1000; // EG1Sustain is 0-1000 permille release = region->EG1Release; // Simple ADSR using positions in sample amplitude = preattack; - attackLength = attack*sampleRate; - decayLength = decay1*sampleRate; // TODO: ignoring decay2 for now - releaseLength = release*sampleRate; + attackLength = attack * sampleRate; + decayLength = decay1 * sampleRate; // TODO: ignoring decay2 for now + releaseLength = release * sampleRate; } } + // Next time we get the amplitude, we'll be releasing the note void ADSR::keyup() { @@ -1037,6 +1123,7 @@ void ADSR::keyup() + // Can we delete the sample now? bool ADSR::done() { @@ -1045,19 +1132,20 @@ bool ADSR::done() + // Return the current amplitude and increment internal positions double ADSR::value() { double currentAmplitude = amplitude; // If we're done, don't output any signal - if( isDone ) + if( isDone == true ) { return 0; } // If we're still in the attack phase, release from the current volume // instead of jumping to the sustain volume and fading out - else if( isAttack && isRelease ) + else if( isAttack == true && isRelease == true ) { sustain = amplitude; isAttack = false; @@ -1065,24 +1153,34 @@ double ADSR::value() // If we're in the attack phase, start at the preattack amplitude and // increase to the full before decreasing to sustain - if( isAttack ) + if( isAttack == true ) { if( attackPosition < attackLength ) - amplitude = preattack + (attack - preattack)/attackLength*attackPosition; - else if( attackPosition < attackLength+decayLength ) - amplitude = 1.0 - (1.0-sustain)/decayLength*(attackPosition-attackLength); + { + amplitude = preattack + ( attack - preattack ) / attackLength * attackPosition; + } + else if( attackPosition < attackLength + decayLength ) + { + amplitude = 1.0 - ( 1.0 - sustain ) / decayLength * ( attackPosition - attackLength ); + } else + { isAttack = false; + } ++attackPosition; } // If we're in the sustain phase, decrease from sustain to zero - else if( isRelease ) + else if( isRelease == true ) { if( releasePosition < releaseLength ) - amplitude = sustain*(1.0-1.0/releaseLength*releasePosition); + { + amplitude = sustain * ( 1.0 - 1.0 / releaseLength * releasePosition ); + } else + { isDone = true; + } ++releasePosition; } @@ -1092,13 +1190,14 @@ double ADSR::value() + extern "C" { // necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { - return new gigInstrument( static_cast( _data ) ); + return new GigInstrument( static_cast( _data ) ); } } diff --git a/plugins/gig_player/gig_player.h b/plugins/GigPlayer/GigPlayer.h similarity index 79% rename from plugins/gig_player/gig_player.h rename to plugins/GigPlayer/GigPlayer.h index 1218cceaa..51f2b2b7f 100644 --- a/plugins/gig_player/gig_player.h +++ b/plugins/GigPlayer/GigPlayer.h @@ -1,5 +1,5 @@ /* - * gig_player.h - a gig player using libgig (based on sf2 player plugin) + * GigPlayer.h - a GIG player using libgig (based on Sf2 player plugin) * * Copyright (c) 2008 Paul Giblock * Copyright (c) 2009-2014 Tobias Doerffel @@ -40,12 +40,13 @@ #include "SampleBuffer.h" #include "gig.h" -class gigInstrumentView; +class GigInstrumentView; class NotePlayHandle; -class patchesDialog; +class PatchesDialog; class QLabel; + // Load a GIG file using libgig class GigInstance { @@ -63,14 +64,18 @@ public: } ; + + // Stores options for the notes, e.g. velocity and release time struct Dimension { Dimension() : release( false ) { - for( int i = 0; i < 8; ++i) + for( int i = 0; i < 8; ++i ) + { DimValues[i] = 0; + } } uint DimValues[8]; @@ -78,6 +83,8 @@ struct Dimension } ; + + // Takes information from the GIG file for a certain note and provides the // amplitude (0-1) to multiply the signal by (internally incrementing the // position in the envelope when asking for the amplitude). @@ -104,38 +111,49 @@ class ADSR int releaseLength; public: - ADSR( gig::DimensionRegion* region, int sampleRate ); + ADSR( gig::DimensionRegion * region, int sampleRate ); void keyup(); // We will begin releasing starting now bool done(); // Is this sample done playing? double value(); // What's the current amplitude } ; + + // The sample from the GIG file with our current position in both the sample // and the envelope class GigSample { public: - GigSample( gig::Sample* pSample, float attenuation, const ADSR& adsr ); + GigSample( gig::Sample * pSample, float attenuation, const ADSR & adsr ); - gig::Sample* sample; + gig::Sample * sample; float attenuation; ADSR adsr; int pos; // Position in sample } ; + + // What portion of a note are we in? enum GigState { - KeyDown, // We just pressed the key - PlayingKeyDown, // The note is currently playing - KeyUp, // We just released the key - PlayingKeyUp, // The note is being released, e.g. a release sample is playing - Completed // The note is done playing, you can delete this note now + // We just pressed the key + KeyDown, + // The note is currently playing + PlayingKeyDown, + // We just released the key + KeyUp, + // The note is being released, e.g. a release sample is playing + PlayingKeyUp, + // The note is done playing, you can delete this note now + Completed } ; + + // Corresponds to a certain midi note pressed, but may contain multiple samples class GigNote { @@ -147,7 +165,8 @@ public: QList samples; GigNote( int midiNote, int velocity ) - : midiNote(midiNote), velocity(velocity), release(false), state(KeyDown) + : midiNote( midiNote ), velocity( velocity ), + release( false ), state( KeyDown ) { } } ; @@ -155,15 +174,15 @@ public: -class gigInstrument : public Instrument +class GigInstrument : public Instrument { Q_OBJECT - mapPropertyFromModel(int,getBank,setBank,m_bankNum); - mapPropertyFromModel(int,getPatch,setPatch,m_patchNum); + mapPropertyFromModel( int, getBank, setBank, m_bankNum ); + mapPropertyFromModel( int, getPatch, setPatch, m_patchNum ); public: - gigInstrument( InstrumentTrack * _instrument_track ); - virtual ~gigInstrument(); + GigInstrument( InstrumentTrack * _instrument_track ); + virtual ~GigInstrument(); virtual void play( sampleFrame * _working_buffer ); @@ -210,8 +229,8 @@ private: SRC_STATE * m_srcState; // The GIG file and instrument we're using - GigInstance* m_instance; - gig::Instrument* m_instrument; + GigInstance * m_instance; + gig::Instrument * m_instrument; // Part of the UI QString m_filename; @@ -230,7 +249,7 @@ private: QList m_notes; // Buffer for note samples - sampleFrame* m_sampleData; + sampleFrame * m_sampleData; unsigned int m_sampleDataSize; // Used when determining which samples to use @@ -246,17 +265,17 @@ private: // Create "dimension" to select desired samples from GIG file based on // parameters such as velocity - Dimension getDimensions( gig::Region* pRegion, int velocity, bool release ); + Dimension getDimensions( gig::Region * pRegion, int velocity, bool release ); // Add the desired samples to the note, either normal samples or release // samples - void addSamples( GigNote& note, bool wantReleaseSample ); + void addSamples( GigNote & note, bool wantReleaseSample ); // Convert sample rates - bool convertSampleRate( sampleFrame& oldBuf, sampleFrame& newBuf, + bool convertSampleRate( sampleFrame & oldBuf, sampleFrame & newBuf, int oldSize, int newSize, int oldRate, int newRate ); - friend class gigInstrumentView; + friend class GigInstrumentView; signals: void fileLoading(); @@ -267,13 +286,14 @@ signals: -class gigInstrumentView : public InstrumentView + +class GigInstrumentView : public InstrumentView { Q_OBJECT public: - gigInstrumentView( Instrument * _instrument, + GigInstrumentView( Instrument * _instrument, QWidget * _parent ); - virtual ~gigInstrumentView(); + virtual ~GigInstrumentView(); private: virtual void modelChanged(); @@ -287,9 +307,9 @@ private: QLabel * m_filenameLabel; QLabel * m_patchLabel; - knob * m_gainKnob; + knob * m_gainKnob; - static patchesDialog * s_patchDialog; + static PatchesDialog * s_patchDialog; protected slots: void invalidateFile(); @@ -300,5 +320,4 @@ protected slots: } ; - #endif diff --git a/plugins/GigPlayer/PatchesDialog.cpp b/plugins/GigPlayer/PatchesDialog.cpp new file mode 100644 index 000000000..71f1e26ff --- /dev/null +++ b/plugins/GigPlayer/PatchesDialog.cpp @@ -0,0 +1,414 @@ +/* + * PatchesDialog.cpp - display GIG patches (based on Sf2 patches_dialog.cpp) + * + * Copyright (c) 2008 Paul Giblock + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#include "PatchesDialog.h" + +#include + + +// Custom list-view item (as for numerical sort purposes...) +class PatchItem : public QTreeWidgetItem +{ +public: + + // Constructor. + PatchItem( QTreeWidget *pListView, + QTreeWidgetItem *pItemAfter ) + : QTreeWidgetItem( pListView, pItemAfter ) {} + + // Sort/compare overriden method. + bool operator< ( const QTreeWidgetItem& other ) const + { + int iColumn = QTreeWidgetItem::treeWidget()->sortColumn(); + const QString& s1 = text( iColumn ); + const QString& s2 = other.text( iColumn ); + + if( iColumn == 0 || iColumn == 2 ) + { + return s1.toInt() < s2.toInt(); + } + else + { + return s1 < s2; + } + } +}; + + + + +// Constructor. +PatchesDialog::PatchesDialog( QWidget * pParent, Qt::WindowFlags wflags ) + : QDialog( pParent, wflags ) +{ + // Setup UI struct... + setupUi( this ); + + m_pSynth = NULL; + m_iChan = 0; + m_iBank = 0; + m_iProg = 0; + + // Soundfonts list view... + QHeaderView * pHeader = m_progListView->header(); + pHeader->setDefaultAlignment( Qt::AlignLeft ); +#if QT_VERSION >= 0x050000 + pHeader->setSectionsMovable( false ); +#else + pHeader->setMovable( false ); +#endif + pHeader->setStretchLastSection( true ); + + m_progListView->resizeColumnToContents( 0 ); // Prog. + + // Initial sort order... + m_bankListView->sortItems( 0, Qt::AscendingOrder ); + m_progListView->sortItems( 0, Qt::AscendingOrder ); + + // UI connections... + QObject::connect( m_bankListView, + SIGNAL( currentItemChanged( QTreeWidgetItem *,QTreeWidgetItem * ) ), + SLOT( bankChanged() ) ); + QObject::connect( m_progListView, + SIGNAL( currentItemChanged( QTreeWidgetItem *, QTreeWidgetItem * ) ), + SLOT( progChanged( QTreeWidgetItem *, QTreeWidgetItem * ) ) ); + QObject::connect( m_progListView, + SIGNAL( itemActivated( QTreeWidgetItem *, int ) ), + SLOT( accept() ) ); + QObject::connect( m_okButton, + SIGNAL( clicked() ), + SLOT( accept() ) ); + QObject::connect( m_cancelButton, + SIGNAL( clicked() ), + SLOT( reject() ) ); +} + + + + +// Destructor. +PatchesDialog::~PatchesDialog() +{ +} + + + + +// Dialog setup loader. +void PatchesDialog::setup( GigInstance * pSynth, int iChan, + const QString & chanName, + LcdSpinBoxModel * bankModel, + LcdSpinBoxModel * progModel, + QLabel * patchLabel ) +{ + + // We'll going to changes the whole thing... + m_dirty = 0; + m_bankModel = bankModel; + m_progModel = progModel; + m_patchLabel = patchLabel; + + // Set the proper caption... + setWindowTitle( chanName + " - GIG patches" ); + + // set m_pSynth to NULL so we don't trigger any progChanged events + m_pSynth = NULL; + + // Load bank list from actual synth stack... + m_bankListView->setSortingEnabled( false ); + m_bankListView->clear(); + + // now it should be safe to set internal stuff + m_pSynth = pSynth; + m_iChan = iChan; + + + //fluid_preset_t preset; + QTreeWidgetItem * pBankItem = NULL; + + // Currently just use zero as the only bank + int iBankDefault = -1; + int iProgDefault = -1; + + gig::Instrument * pInstrument = m_pSynth->gig.GetFirstInstrument(); + + while( pInstrument ) + { + int iBank = pInstrument->MIDIBank; + int iProg = pInstrument->MIDIProgram; + + if ( !findBankItem( iBank ) ) + { + pBankItem = new PatchItem( m_bankListView, pBankItem ); + + if( pBankItem ) + { + pBankItem->setText( 0, QString::number( iBank ) ); + + if( iBankDefault == -1 ) + { + iBankDefault = iBank; + iProgDefault = iProg; + } + } + } + + pInstrument = m_pSynth->gig.GetNextInstrument(); + } + + m_bankListView->setSortingEnabled( true ); + + // Set the selected bank. + if( iBankDefault != -1 ) + { + m_iBank = iBankDefault; + } + + pBankItem = findBankItem( m_iBank ); + m_bankListView->setCurrentItem( pBankItem ); + m_bankListView->scrollToItem( pBankItem ); + bankChanged(); + + // Set the selected program. + if( iProgDefault != -1 ) + { + m_iProg = iProgDefault; + } + + QTreeWidgetItem * pProgItem = findProgItem( m_iProg ); + m_progListView->setCurrentItem( pProgItem ); + m_progListView->scrollToItem( pProgItem ); +} + + + + +// Stabilize current state form. +void PatchesDialog::stabilizeForm() +{ + m_okButton->setEnabled( validateForm() ); +} + + + + +// Validate form fields. +bool PatchesDialog::validateForm() +{ + bool bValid = true; + + bValid = bValid && ( m_bankListView->currentItem() != NULL ); + bValid = bValid && ( m_progListView->currentItem() != NULL ); + + return bValid; +} + + + + +// Realize a bank-program selection preset. +void PatchesDialog::setBankProg( int iBank, int iProg ) +{ + if( m_pSynth == NULL ) + { + return; + } +} + + + + +// Validate form fields and accept it valid. +void PatchesDialog::accept() +{ + if( validateForm() ) + { + // Unload from current selected dialog items. + int iBank = ( m_bankListView->currentItem() )->text( 0 ).toInt(); + int iProg = ( m_progListView->currentItem() )->text( 0 ).toInt(); + + // And set it right away... + setBankProg( iBank, iProg ); + + if( m_dirty > 0 ) + { + m_bankModel->setValue( iBank ); + m_progModel->setValue( iProg ); + m_patchLabel->setText( m_progListView-> + currentItem()->text( 1 ) ); + } + + // We got it. + QDialog::accept(); + } +} + + + + +// Reject settings (Cancel button slot). +void PatchesDialog::reject() +{ + // Reset selection to initial selection, if applicable... + if( m_dirty > 0 ) + { + setBankProg( m_bankModel->value(), m_progModel->value() ); + } + + // Done (hopefully nothing). + QDialog::reject(); +} + + + + +// Find the bank item of given bank number id. +QTreeWidgetItem * PatchesDialog::findBankItem( int iBank ) +{ + QList banks + = m_bankListView->findItems( + QString::number( iBank ), Qt::MatchExactly, 0 ); + + QListIterator iter( banks ); + + if( iter.hasNext() ) + { + return iter.next(); + } + else + { + return NULL; + } +} + + + + +// Find the program item of given program number id. +QTreeWidgetItem *PatchesDialog::findProgItem( int iProg ) +{ + QList progs + = m_progListView->findItems( + QString::number( iProg ), Qt::MatchExactly, 0 ); + + QListIterator iter( progs ); + + if( iter.hasNext() ) + { + return iter.next(); + } + else + { + return NULL; + } +} + + + + +// Bank change slot. +void PatchesDialog::bankChanged() +{ + if( m_pSynth == NULL ) + { + return; + } + + QTreeWidgetItem * pBankItem = m_bankListView->currentItem(); + + if( pBankItem == NULL ) + { + return; + } + + int iBankSelected = pBankItem->text( 0 ).toInt(); + + // Clear up the program listview. + m_progListView->setSortingEnabled( false ); + m_progListView->clear(); + QTreeWidgetItem * pProgItem = NULL; + + gig::Instrument * pInstrument = m_pSynth->gig.GetFirstInstrument(); + + while( pInstrument ) + { + QString name = QString::fromStdString( pInstrument->pInfo->Name ); + + if( name == "" ) + { + name = ""; + } + + int iBank = pInstrument->MIDIBank; + int iProg = pInstrument->MIDIProgram; + + if( iBank == iBankSelected && !findProgItem( iProg ) ) + { + pProgItem = new PatchItem( m_progListView, pProgItem ); + + if( pProgItem ) + { + pProgItem->setText( 0, QString::number( iProg ) ); + pProgItem->setText( 1, name ); + } + } + + pInstrument = m_pSynth->gig.GetNextInstrument(); + } + + m_progListView->setSortingEnabled( true ); + + // Stabilize the form. + stabilizeForm(); +} + + + + +// Program change slot. +void PatchesDialog::progChanged( QTreeWidgetItem * curr, QTreeWidgetItem * prev ) +{ + if( m_pSynth == NULL || curr == NULL ) + { + return; + } + + // Which preview state... + if( validateForm() ) + { + // Set current selection. + int iBank = ( m_bankListView->currentItem() )->text( 0 ).toInt(); + int iProg = curr->text( 0 ).toInt(); + + // And set it right away... + setBankProg( iBank, iProg ); + + // Now we're dirty nuff. + m_dirty++; + } + + // Stabilize the form. + stabilizeForm(); +} diff --git a/plugins/gig_player/patches_dialog.h b/plugins/GigPlayer/PatchesDialog.h similarity index 66% rename from plugins/gig_player/patches_dialog.h rename to plugins/GigPlayer/PatchesDialog.h index 6b74993f9..bb4dedde2 100644 --- a/plugins/gig_player/patches_dialog.h +++ b/plugins/GigPlayer/PatchesDialog.h @@ -1,5 +1,5 @@ /* - * patches_dialog.h - display sf2 patches + * PatchesDialog.h - display GIG patches (based on Sf2 patches_dialog.h) * * Copyright (c) 2008 Paul Giblock * @@ -23,12 +23,12 @@ */ -#ifndef _PATCHES_DIALOG_H -#define _PATCHES_DIALOG_H +#ifndef PATCHES_DIALOG_H +#define PATCHES_DIALOG_H -#include "ui_patches_dialog.h" +#include "ui_PatchesDialog.h" #include "LcdSpinBox.h" -#include "gig_player.h" +#include "GigPlayer.h" #include #include @@ -37,27 +37,27 @@ //---------------------------------------------------------------------------- // qsynthPresetForm -- UI wrapper form. -class patchesDialog : public QDialog, private Ui::patchesDialog +class PatchesDialog : public QDialog, private Ui::PatchesDialog { Q_OBJECT public: // Constructor. - patchesDialog(QWidget *pParent = 0, Qt::WindowFlags wflags = 0); + PatchesDialog( QWidget * pParent = 0, Qt::WindowFlags wflags = 0 ); // Destructor. - virtual ~patchesDialog(); + virtual ~PatchesDialog(); - void setup(GigInstance * pSynth, int iChan, const QString & _chanName, - LcdSpinBoxModel * _bankModel, LcdSpinBoxModel * _progModel, QLabel *_patchLabel ); + void setup( GigInstance * pSynth, int iChan, const QString & chanName, + LcdSpinBoxModel * bankModel, LcdSpinBoxModel * progModel, QLabel * patchLabel ); public slots: void stabilizeForm(); void bankChanged(); - void progChanged( QTreeWidgetItem * _curr, QTreeWidgetItem * _prev ); + void progChanged( QTreeWidgetItem * curr, QTreeWidgetItem * prev ); protected slots: @@ -66,31 +66,27 @@ protected slots: protected: - void setBankProg(int iBank, int iProg); + void setBankProg( int iBank, int iProg ); - QTreeWidgetItem *findBankItem(int iBank); - QTreeWidgetItem *findProgItem(int iProg); + QTreeWidgetItem * findBankItem( int iBank ); + QTreeWidgetItem * findProgItem( int iProg ); bool validateForm(); private: // Instance variables. - GigInstance *m_pSynth; + GigInstance * m_pSynth; int m_iChan; int m_iBank; int m_iProg; - //int m_iDirtySetup; - //int m_iDirtyCount; int m_dirty; LcdSpinBoxModel * m_bankModel; LcdSpinBoxModel * m_progModel; - QLabel *m_patchLabel; + QLabel * m_patchLabel; }; - #endif - diff --git a/plugins/gig_player/patches_dialog.ui b/plugins/GigPlayer/PatchesDialog.ui similarity index 98% rename from plugins/gig_player/patches_dialog.ui rename to plugins/GigPlayer/PatchesDialog.ui index 5204dc09d..2f9f8a865 100644 --- a/plugins/gig_player/patches_dialog.ui +++ b/plugins/GigPlayer/PatchesDialog.ui @@ -19,8 +19,8 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - patchesDialog - + PatchesDialog + 0 diff --git a/plugins/gig_player/artwork.png b/plugins/GigPlayer/artwork.png similarity index 100% rename from plugins/gig_player/artwork.png rename to plugins/GigPlayer/artwork.png diff --git a/plugins/gig_player/fileselect_off.png b/plugins/GigPlayer/fileselect_off.png similarity index 100% rename from plugins/gig_player/fileselect_off.png rename to plugins/GigPlayer/fileselect_off.png diff --git a/plugins/gig_player/fileselect_on.png b/plugins/GigPlayer/fileselect_on.png similarity index 100% rename from plugins/gig_player/fileselect_on.png rename to plugins/GigPlayer/fileselect_on.png diff --git a/plugins/gig_player/logo.png b/plugins/GigPlayer/logo.png similarity index 100% rename from plugins/gig_player/logo.png rename to plugins/GigPlayer/logo.png diff --git a/plugins/gig_player/patches_off.png b/plugins/GigPlayer/patches_off.png similarity index 100% rename from plugins/gig_player/patches_off.png rename to plugins/GigPlayer/patches_off.png diff --git a/plugins/gig_player/patches_on.png b/plugins/GigPlayer/patches_on.png similarity index 100% rename from plugins/gig_player/patches_on.png rename to plugins/GigPlayer/patches_on.png diff --git a/plugins/gig_player/patches_dialog.cpp b/plugins/gig_player/patches_dialog.cpp deleted file mode 100644 index 7003f888b..000000000 --- a/plugins/gig_player/patches_dialog.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/* - * patches_dialog.cpp - display sf2 patches - * - * Copyright (c) 2008 Paul Giblock - * - * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - - -#include "patches_dialog.h" - -#include -//#include - - -// Custom list-view item (as for numerical sort purposes...) -class patchItem : public QTreeWidgetItem -{ -public: - - // Constructor. - patchItem( QTreeWidget *pListView, - QTreeWidgetItem *pItemAfter ) - : QTreeWidgetItem( pListView, pItemAfter ) {} - - // Sort/compare overriden method. - bool operator< ( const QTreeWidgetItem& other ) const - { - int iColumn = QTreeWidgetItem::treeWidget()->sortColumn(); - const QString& s1 = text( iColumn ); - const QString& s2 = other.text( iColumn ); - if( iColumn == 0 || iColumn == 2 ) - { - return( s1.toInt() < s2.toInt() ); - } - else - { - return( s1 < s2 ); - } - } -}; - - - -// Constructor. -patchesDialog::patchesDialog( QWidget *pParent, Qt::WindowFlags wflags ) - : QDialog( pParent, wflags ) -{ - // Setup UI struct... - setupUi( this ); - - m_pSynth = NULL; - m_iChan = 0; - m_iBank = 0; - m_iProg = 0; - - // Soundfonts list view... - QHeaderView *pHeader = m_progListView->header(); -// pHeader->setResizeMode(QHeaderView::Custom); - pHeader->setDefaultAlignment(Qt::AlignLeft); -// pHeader->setDefaultSectionSize(200); -#if QT_VERSION >= 0x050000 - pHeader->setSectionsMovable(false); -#else - pHeader->setMovable(false); -#endif - pHeader->setStretchLastSection(true); - - m_progListView->resizeColumnToContents(0); // Prog. - //pHeader->resizeSection(1, 200); // Name. - - // Initial sort order... - m_bankListView->sortItems(0, Qt::AscendingOrder); - m_progListView->sortItems(0, Qt::AscendingOrder); - - // UI connections... - QObject::connect(m_bankListView, - SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), - SLOT(bankChanged())); - QObject::connect(m_progListView, - SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), - SLOT(progChanged(QTreeWidgetItem*,QTreeWidgetItem*))); - QObject::connect(m_progListView, - SIGNAL(itemActivated(QTreeWidgetItem*,int)), - SLOT(accept())); - QObject::connect(m_okButton, - SIGNAL(clicked()), - SLOT(accept())); - QObject::connect(m_cancelButton, - SIGNAL(clicked()), - SLOT(reject())); -} - - -// Destructor. -patchesDialog::~patchesDialog() -{ -} - - -// Dialog setup loader. -void patchesDialog::setup ( GigInstance * pSynth, int iChan, - const QString & _chanName, - LcdSpinBoxModel * _bankModel, - LcdSpinBoxModel * _progModel, - QLabel * _patchLabel ) -{ - - // We'll going to changes the whole thing... - m_dirty = 0; - m_bankModel = _bankModel; - m_progModel = _progModel; - m_patchLabel = _patchLabel; - - // Set the proper caption... - setWindowTitle( _chanName + " - GIG patches" ); - - // set m_pSynth to NULL so we don't trigger any progChanged events - m_pSynth = NULL; - - // Load bank list from actual synth stack... - m_bankListView->setSortingEnabled(false); - m_bankListView->clear(); - - // now it should be safe to set internal stuff - m_pSynth = pSynth; - m_iChan = iChan; - - - //fluid_preset_t preset; - QTreeWidgetItem *pBankItem = NULL; - // For all soundfonts (in reversed stack order) fill the available banks... - /*int cSoundFonts = ::fluid_synth_sfcount(m_pSynth); - for (int i = 0; i < cSoundFonts; i++) { - fluid_sfont_t *pSoundFont = ::fluid_synth_get_sfont(m_pSynth, i); - if (pSoundFont) { -#ifdef CONFIG_FLUID_BANK_OFFSET - int iBankOffset = ::fluid_synth_get_bank_offset(m_pSynth, pSoundFont->id); -#endif - pSoundFont->iteration_start(pSoundFont); - while (pSoundFont->iteration_next(pSoundFont, &preset)) { - int iBank = preset.get_banknum(&preset); -#ifdef CONFIG_FLUID_BANK_OFFSET - iBank += iBankOffset; -#endif - if (!findBankItem(iBank)) { - pBankItem = new patchItem(m_bankListView, pBankItem); - if (pBankItem) - pBankItem->setText(0, QString::number(iBank)); - } - } - } - }*/ - - // TODO: get rid of "banks" altogether - // Currently just use zero as the only bank - int iBankDefault = -1; - int iProgDefault = -1; - - gig::Instrument* pInstrument = m_pSynth->gig.GetFirstInstrument(); - while (pInstrument) { - int iBank = pInstrument->MIDIBank; - int iProg = pInstrument->MIDIProgram; - - if (!findBankItem(iBank)) { - pBankItem = new patchItem(m_bankListView, pBankItem); - - if (pBankItem) - { - pBankItem->setText(0, QString::number(iBank)); - - if (iBankDefault == -1) - { - iBankDefault = iBank; - iProgDefault = iProg; - } - } - } - - pInstrument = m_pSynth->gig.GetNextInstrument(); - } - - m_bankListView->setSortingEnabled(true); - - // Set the selected bank. - if (iBankDefault != -1) - m_iBank = iBankDefault; - - pBankItem = findBankItem(m_iBank); - m_bankListView->setCurrentItem(pBankItem); - m_bankListView->scrollToItem(pBankItem); - bankChanged(); - - // Set the selected program. - if (iProgDefault != -1) - m_iProg = iProgDefault; - QTreeWidgetItem *pProgItem = findProgItem(m_iProg); - m_progListView->setCurrentItem(pProgItem); - m_progListView->scrollToItem(pProgItem); - - // Done with setup... - //m_iDirtySetup--; -} - - -// Stabilize current state form. -void patchesDialog::stabilizeForm() -{ - m_okButton->setEnabled(validateForm()); -} - - -// Validate form fields. -bool patchesDialog::validateForm() -{ - bool bValid = true; - - bValid = bValid && (m_bankListView->currentItem() != NULL); - bValid = bValid && (m_progListView->currentItem() != NULL); - - return bValid; -} - - -// Realize a bank-program selection preset. -void patchesDialog::setBankProg ( int iBank, int iProg ) -{ - if (m_pSynth == NULL) - return; - - // just select the synth's program preset... - //::fluid_synth_bank_select(m_pSynth, m_iChan, iBank); - //::fluid_synth_program_change(m_pSynth, m_iChan, iProg); - // Maybe this is needed to stabilize things around. - //::fluid_synth_program_reset(m_pSynth); -} - - -// Validate form fields and accept it valid. -void patchesDialog::accept() -{ - if (validateForm()) { - // Unload from current selected dialog items. - int iBank = (m_bankListView->currentItem())->text(0).toInt(); - int iProg = (m_progListView->currentItem())->text(0).toInt(); - // And set it right away... - setBankProg(iBank, iProg); - - if (m_dirty > 0) { - m_bankModel->setValue( iBank ); - m_progModel->setValue( iProg ); - m_patchLabel->setText( m_progListView-> - currentItem()->text( 1 ) ); - } - - // Do remember preview state... - // if (m_pOptions) - // m_pOptions->bPresetPreview = m_ui.PreviewCheckBox->isChecked(); - // We got it. - QDialog::accept(); - } -} - - -// Reject settings (Cancel button slot). -void patchesDialog::reject (void) -{ - // Reset selection to initial selection, if applicable... - if (m_dirty > 0) - setBankProg(m_bankModel->value(), m_progModel->value()); - // Done (hopefully nothing). - QDialog::reject(); -} - - -// Find the bank item of given bank number id. -QTreeWidgetItem *patchesDialog::findBankItem ( int iBank ) -{ - QList banks - = m_bankListView->findItems( - QString::number(iBank), Qt::MatchExactly, 0); - - QListIterator iter(banks); - if (iter.hasNext()) - return iter.next(); - else - return NULL; -} - - -// Find the program item of given program number id. -QTreeWidgetItem *patchesDialog::findProgItem ( int iProg ) -{ - QList progs - = m_progListView->findItems( - QString::number(iProg), Qt::MatchExactly, 0); - - QListIterator iter(progs); - if (iter.hasNext()) - return iter.next(); - else - return NULL; -} - - - -// Bank change slot. -void patchesDialog::bankChanged (void) -{ - if (m_pSynth == NULL) - return; - - QTreeWidgetItem *pBankItem = m_bankListView->currentItem(); - if (pBankItem == NULL) - return; - - int iBankSelected = pBankItem->text(0).toInt(); - - // Clear up the program listview. - m_progListView->setSortingEnabled(false); - m_progListView->clear(); - QTreeWidgetItem *pProgItem = NULL; - - gig::Instrument* pInstrument = m_pSynth->gig.GetFirstInstrument(); - while (pInstrument) { - QString name = QString::fromStdString(pInstrument->pInfo->Name); - if (name == "") - name = ""; - int iBank = pInstrument->MIDIBank; - int iProg = pInstrument->MIDIProgram; - - if (iBank == iBankSelected && !findProgItem(iProg)) { - pProgItem = new patchItem(m_progListView, pProgItem); - if (pProgItem) { - pProgItem->setText(0, QString::number(iProg)); - pProgItem->setText(1, name); - } - } - - pInstrument = m_pSynth->gig.GetNextInstrument(); - } - - m_progListView->setSortingEnabled(true); - - // Stabilize the form. - stabilizeForm(); -} - - -// Program change slot. -void patchesDialog::progChanged (QTreeWidgetItem * _curr, QTreeWidgetItem * _prev) -{ - if (m_pSynth == NULL || _curr == NULL) - return; - - // Which preview state... - if( validateForm() ) { - // Set current selection. - int iBank = (m_bankListView->currentItem())->text(0).toInt(); - int iProg = _curr->text(0).toInt(); - // And set it right away... - setBankProg(iBank, iProg); - // Now we're dirty nuff. - m_dirty++; - } - - // Stabilize the form. - stabilizeForm(); -}