@ -28,8 +28,15 @@
LOGMODULE ( " Performance " ) ;
//#define VERBOSE_DEBUG
# define PERFORMANCE_DIR "performance"
# define DEFAULT_PERFORMANCE_FILENAME "performance.ini"
# define DEFAULT_PERFORMANCE_NAME "Default"
# define DEFAULT_PERFORMANCE_BANK_NAME "Default"
CPerformanceConfig : : CPerformanceConfig ( FATFS * pFileSystem )
: m_Properties ( " performance.ini " , pFileSystem )
: m_Properties ( DEFAULT_PERFORMANCE_FILENAME , pFileSystem )
{
m_pFileSystem = pFileSystem ;
}
@ -38,6 +45,47 @@ CPerformanceConfig::~CPerformanceConfig (void)
{
}
bool CPerformanceConfig : : Init ( void )
{
// Check intermal performance directory exists
DIR Directory ;
FRESULT Result ;
//Check if internal "performance" directory exists
Result = f_opendir ( & Directory , " SD:/ " PERFORMANCE_DIR ) ;
if ( Result = = FR_OK )
{
m_bPerformanceDirectoryExists = true ;
Result = f_closedir ( & Directory ) ;
}
else
{
m_bPerformanceDirectoryExists = false ;
}
// List banks if present
ListPerformanceBanks ( ) ;
# ifdef VERBOSE_DEBUG
# warning "PerformanceConfig in verbose debug printing mode"
LOGNOTE ( " Testing loading of banks " ) ;
for ( unsigned i = 0 ; i < NUM_PERFORMANCE_BANKS ; i + + )
{
if ( ! m_PerformanceBankName [ i ] . empty ( ) )
{
SetNewPerformanceBank ( i ) ;
SetNewPerformance ( 0 ) ;
}
}
# endif
// Set to default initial bank
SetNewPerformanceBank ( 0 ) ;
SetNewPerformance ( 0 ) ;
LOGNOTE ( " Loaded Default Performance Bank - Last Performance: %d " , m_nLastPerformance + 1 ) ; // Show "user facing" index
return true ;
}
bool CPerformanceConfig : : Load ( void )
{
if ( ! m_Properties . Load ( ) )
@ -715,44 +763,116 @@ bool CPerformanceConfig::VoiceDataFilled(unsigned nTG)
std : : string CPerformanceConfig : : GetPerformanceFileName ( unsigned nID )
{
return m_nPerformanceFileName [ nID ] ;
assert ( nID < NUM_PERFORMANCES ) ;
std : : string FileN = " " ;
if ( ( m_nPerformanceBank = = 0 ) & & ( nID = = 0 ) ) // in order to assure retrocompatibility
{
FileN + = DEFAULT_PERFORMANCE_FILENAME ;
}
else
{
// Build up from the index, "_", performance name, and ".ini"
// NB: Index on disk = index in memory + 1
std : : string nIndex = " 000000 " ;
nIndex + = std : : to_string ( nID + 1 ) ;
nIndex = nIndex . substr ( nIndex . length ( ) - 6 , 6 ) ;
FileN + = nIndex ;
FileN + = " _ " ;
FileN + = m_PerformanceFileName [ nID ] ;
FileN + = " .ini " ;
}
return FileN ;
}
std : : string CPerformanceConfig : : GetPerformanceFullFilePath ( unsigned nID )
{
assert ( nID < NUM_PERFORMANCES ) ;
std : : string FileN = " SD:/ " ;
if ( ( m_nPerformanceBank = = 0 ) & & ( nID = = 0 ) )
{
// Special case for the legacy Bank 1/Default performance
FileN + = DEFAULT_PERFORMANCE_FILENAME ;
}
else
{
if ( m_bPerformanceDirectoryExists )
{
FileN + = PERFORMANCE_DIR ;
FileN + = AddPerformanceBankDirName ( m_nPerformanceBank ) ;
FileN + = " / " ;
FileN + = GetPerformanceFileName ( nID ) ;
}
}
return FileN ;
}
std : : string CPerformanceConfig : : GetPerformanceName ( unsigned nID )
{
if ( nID = = 0 ) // in order to assure retrocompatibility
assert ( nID < NUM_PERFORMANCES ) ;
if ( ( m_nPerformanceBank = = 0 ) & & ( nID = = 0 ) ) // in order to assure retrocompatibility
{
return " Default " ;
return DEFAULT_PERFORMANCE_NAME ;
}
else
{
return m_nPerformanceFileName [ nID ] . substr ( 0 , m_nPerformanceFileName [ nID ] . length ( ) - 4 ) . substr ( 7 , 14 ) ;
return m_PerformanceFileName [ nID ] ;
}
}
unsigned CPerformanceConfig : : GetLastPerformance ( )
{
return nLastPerformance ;
return m_nLastPerformance ;
}
unsigned CPerformanceConfig : : GetLastPerformanceBank ( )
{
return m_nLastPerformanceBank ;
}
unsigned CPerformanceConfig : : GetActualPerformanceID ( )
{
return nActualPerformance ;
return m_ nActualPerformance;
}
void CPerformanceConfig : : SetActualPerformanceID ( unsigned nID )
{
nActualPerformance = nID ;
assert ( nID < NUM_PERFORMANCES ) ;
m_nActualPerformance = nID ;
}
unsigned CPerformanceConfig : : GetActualPerformanceBankID ( )
{
return m_nActualPerformanceBank ;
}
void CPerformanceConfig : : SetActualPerformanceBankID ( unsigned nBankID )
{
assert ( nBankID < NUM_PERFORMANCE_BANKS ) ;
m_nActualPerformanceBank = nBankID ;
}
bool CPerformanceConfig : : GetInternalFolderOk ( )
{
return nInternalFolderOk ;
return m_bPerformanceDirectoryExists ;
}
bool CPerformanceConfig : : IsValidPerformance ( unsigned nID )
{
if ( nID < NUM_PERFORMANCES )
{
if ( ! m_PerformanceFileName [ nID ] . empty ( ) )
{
return true ;
}
}
return false ;
}
bool CPerformanceConfig : : CheckFreePerformanceSlot ( void )
{
if ( nLastPerformance < NUM_PERFORMANCES )
if ( m_ nLastPerformance < NUM_PERFORMANCES - 1 )
{
// There is a free slot...
return true ;
@ -765,19 +885,36 @@ bool CPerformanceConfig::CheckFreePerformanceSlot(void)
bool CPerformanceConfig : : CreateNewPerformanceFile ( void )
{
if ( nLastPerformance > = NUM_PERFORMANCES ) {
if ( ! m_bPerformanceDirectoryExists )
{
// Nothing can be done if there is no performance directory
LOGNOTE ( " Performance directory does not exist " ) ;
return false ;
}
if ( m_nLastPerformance > = NUM_PERFORMANCES ) {
// No space left for new performances
LOGWARN ( " No space left for new performance " ) ;
return false ;
}
// Note: New performances are created at the end of the currently selected bank.
// Sould we default to a new bank just for user-performances?
//
// There is the possibility of MIDI changing the Bank Number and the user
// not spotting the bank has changed...
//
// Another option would be to find empty slots in the current bank
// rather than always add at the end.
//
// Sorting this out is left for a future update.
std : : string sPerformanceName = NewPerformanceName ;
NewPerformanceName = " " ;
nActualPerformance = nLastPerformance ;
unsigned nNewPerformance = m_nLastPerformance + 1 ;
std : : string nFileName ;
std : : string nPath ;
std : : string nIndex = " 000000 " ;
nIndex + = std : : to_string ( + + nLastFileIndex ) ;
nIndex + = std : : to_string ( nNewPerformance + 1 ) ; // Index on disk = index in memory+1
nIndex = nIndex . substr ( nIndex . length ( ) - 6 , 6 ) ;
@ -793,10 +930,11 @@ bool CPerformanceConfig::CreateNewPerformanceFile(void)
nFileName + = sPerformanceName . substr ( 0 , 14 ) ;
}
nFileName + = " .ini " ;
m_n PerformanceFileName [ nLastPerformance ] = nFil eName ;
m_PerformanceFileName [ nNewPerformance ] = sPerformanc eName ;
nPath = " SD:/ " ;
nPath + = PERFORMANCE_DIR ;
nPath + = AddPerformanceBankDirName ( m_nPerformanceBank ) ;
nPath + = " / " ;
nFileName = nPath + nFileName ;
@ -804,17 +942,18 @@ bool CPerformanceConfig::CreateNewPerformanceFile(void)
FRESULT Result = f_open ( & File , nFileName . c_str ( ) , FA_WRITE | FA_CREATE_ALWAYS ) ;
if ( Result ! = FR_OK )
{
m_n PerformanceFileName [ nLast Performance ] = nullptr ;
m_PerformanceFileName [ nNew Performance ] = nullptr ;
return false ;
}
if ( f_close ( & File ) ! = FR_OK )
{
m_n PerformanceFileName [ nLast Performance ] = nullptr ;
m_PerformanceFileName [ nNew Performance ] = nullptr ;
return false ;
}
nLastPerformance + + ;
m_nLastPerformance = nNewPerformance ;
m_nActualPerformance = nNewPerformance ;
new ( & m_Properties ) CPropertiesFatFsFile ( nFileName . c_str ( ) , m_pFileSystem ) ;
return true ;
@ -822,88 +961,124 @@ bool CPerformanceConfig::CreateNewPerformanceFile(void)
bool CPerformanceConfig : : ListPerformances ( )
{
nInternalFolderOk = false ;
nExternalFolderOk = false ; // for future USB implementation
nLastPerformance = 0 ;
nLastFileIndex = 0 ;
m_nPerformanceFileName [ nLastPerformance + + ] = " performance.ini " ; // in order to assure retrocompatibility
unsigned nPIndex ;
DIR Directory ;
FILINFO FileInfo ;
FRESULT Result ;
//Check if internal "performance" directory exists
Result = f_opendir ( & Directory , " SD:/ " PERFORMANCE_DIR ) ;
if ( Result = = FR_OK )
// Clear any existing lists of performances
for ( unsigned i = 0 ; i < NUM_PERFORMANCES ; i + + )
{
nInternalFolderOk = true ;
// Result = f_closedir (&Directory);
m_PerformanceFileName [ i ] . clear ( ) ;
}
else
m_nLastPerformance = 0 ;
if ( m_nPerformanceBank = = 0 )
{
// attenpt to create the folder
Result = f_mkdir ( " SD:/ " PERFORMANCE_DIR ) ;
nInternalFolderOk = ( Result = = FR_OK ) ;
// The first bank is the default performance directory
m_PerformanceFileName [ 0 ] = DEFAULT_PERFORMANCE_NAME ; // in order to assure retrocompatibility
}
if ( nInternalFolderOk )
if ( m_bPerformanceDirectoryExists )
{
Result = f_findfirst ( & Directory , & FileInfo , " SD:/ " PERFORMANCE_DIR , " *.ini " ) ;
DIR Directory ;
FILINFO FileInfo ;
FRESULT Result ;
std : : string PerfDir = " SD:/ " PERFORMANCE_DIR + AddPerformanceBankDirName ( m_nPerformanceBank ) ;
# ifdef VERBOSE_DEBUG
LOGNOTE ( " Listing Performances from %s " , PerfDir . c_str ( ) ) ;
# endif
Result = f_opendir ( & Directory , PerfDir . c_str ( ) ) ;
if ( Result ! = FR_OK )
{
return false ;
}
unsigned nPIndex ;
Result = f_findfirst ( & Directory , & FileInfo , PerfDir . c_str ( ) , " *.ini " ) ;
for ( unsigned i = 0 ; Result = = FR_OK & & FileInfo . fname [ 0 ] ; i + + )
{
if ( nLastPerformance > = NUM_PERFORMANCES ) {
LOGNOTE ( " Skipping performance %s " , FileInfo . fname ) ;
} else {
if ( ! ( FileInfo . fattrib & ( AM_HID | AM_SYS ) ) )
if ( ! ( FileInfo . fattrib & ( AM_HID | AM_SYS ) ) )
{
std : : string OriFileName = FileInfo . fname ;
size_t nLen = OriFileName . length ( ) ;
if ( nLen > 8 & & nLen < 26 & & strcmp ( OriFileName . substr ( 6 , 1 ) . c_str ( ) , " _ " ) = = 0 )
{
std : : string FileName = FileInfo . fname ;
size_t nLen = FileName . length ( ) ;
if ( nLen > 8 & & nLen < 26 & & strcmp ( FileName . substr ( 6 , 1 ) . c_str ( ) , " _ " ) = = 0 )
{
nPIndex = stoi ( FileName . substr ( 0 , 6 ) ) ;
if ( nPIndex > nLastFileIndex )
// Note: m_nLastPerformance - refers to the number (index) of the last performance in memory,
// which includes a default performance.
//
// Filenames on the disk start from 1 to match what the user might see in MIDI.
// So this means that actually file 000001_ will correspond to index position [0].
// For the default bank though, ID 1 is the default performance, so will already exist.
// m_PerformanceFileName[0] = default performance (file 000001)
// m_PerformanceFileName[1] = first available on-disk performance (file 000002)
//
// Note2: filenames assume 6 digits, underscore, name, finally ".ini"
// i.e. 123456_Performance Name.ini
//
nPIndex = stoi ( OriFileName . substr ( 0 , 6 ) ) ;
if ( ( nPIndex < 1 ) | | ( nPIndex > = ( NUM_PERFORMANCES + 1 ) ) )
{
// Index is out of range - skip to next file
LOGNOTE ( " Performance number out of range: %s (%d to %d) " , FileInfo . fname , 1 , NUM_PERFORMANCES ) ;
}
else
{
// Convert from "user facing" 1..indexed number to internal 0..indexed
nPIndex = nPIndex - 1 ;
if ( m_PerformanceFileName [ nPIndex ] . empty ( ) )
{
nLastFileIndex = nPIndex ;
}
if ( nPIndex > m_nLastPerformance )
{
m_nLastPerformance = nPIndex ;
}
m_nPerformanceFileName [ nLastPerformance + + ] = FileName ;
}
std : : string FileName = OriFileName . substr ( 0 , OriFileName . length ( ) - 4 ) . substr ( 7 , 14 ) ;
m_PerformanceFileName [ nPIndex ] = FileName ;
# ifdef VERBOSE_DEBUG
LOGNOTE ( " Loading performance %s (%d, %s) " , OriFileName . c_str ( ) , nPIndex , FileName . c_str ( ) ) ;
# endif
}
else
{
LOGNOTE ( " Duplicate performance %s " , OriFileName . c_str ( ) ) ;
}
}
}
}
Result = f_findnext ( & Directory , & FileInfo ) ;
}
// sort by performance number-name
if ( nLastPerformance > 2 )
{
sort ( m_nPerformanceFileName + 1 , m_nPerformanceFileName + nLastPerformance ) ; // default is always on first place. %%%%%%%%%%%%%%%%
}
f_closedir ( & Directory ) ;
}
LOGNOTE ( " Number of Performances: %d " , nLastPerformance ) ;
return nInternalFolderOk ;
}
return true ;
}
void CPerformanceConfig : : SetNewPerformance ( unsigned nID )
{
nActualPerformance = nID ;
std : : string FileN = " " ;
if ( nID ! = 0 ) // in order to assure retrocompatibility
assert ( nID < NUM_PERFORMANCES ) ;
m_nActualPerformance = nID ;
std : : string FileN = GetPerformanceFullFilePath ( nID ) ;
new ( & m_Properties ) CPropertiesFatFsFile ( FileN . c_str ( ) , m_pFileSystem ) ;
# ifdef VERBOSE_DEBUG
LOGNOTE ( " Selecting Performance: %d (%s) " , nID + 1 , FileN . c_str ( ) ) ;
# endif
}
unsigned CPerformanceConfig : : FindFirstPerformance ( void )
{
for ( int nID = 0 ; nID < NUM_PERFORMANCES ; nID + + )
{
if ( IsValidPerformance ( nID ) )
{
FileN + = PERFORMANCE_DIR ;
FileN + = " / " ;
return nID ;
}
FileN + = m_nPerformanceFileName [ nID ] ;
new ( & m_Properties ) CPropertiesFatFsFile ( FileN . c_str ( ) , m_pFileSystem ) ;
}
return 0 ; // Even though 0 is a valid performance, not much else to do
}
std : : string CPerformanceConfig : : GetNewPerformanceDefaultName ( void )
{
std : : string nIndex = " 000000 " ;
nIndex + = std : : to_string ( nLastFileIndex + 1 ) ;
nIndex + = std : : to_string ( m_nLastPerformance + 1 + 1 ) ; // Convert from internal 0.. index to a file-based 1.. index to show the user
nIndex = nIndex . substr ( nIndex . length ( ) - 6 , 6 ) ;
return " Perf " + nIndex ;
}
@ -923,31 +1098,229 @@ void CPerformanceConfig::SetNewPerformanceName(std::string nName)
bool CPerformanceConfig : : DeletePerformance ( unsigned nID )
{
if ( ! m_bPerformanceDirectoryExists )
{
// Nothing can be done if there is no performance directory
LOGNOTE ( " Performance directory does not exist " ) ;
return false ;
}
bool bOK = false ;
if ( nID = = 0 ) { return bOK ; } // default (performance.ini at root directory) can't be deleted
if ( ( m_nPerformanceBank = = 0 ) & & ( nID = = 0 ) ) { return bOK ; } // default (performance.ini at root directory) can't be deleted
DIR Directory ;
FILINFO FileInfo ;
std : : string FileN = " SD:/ " ;
FileN + = PERFORMANCE_DIR ;
FileN + = AddPerformanceBankDirName ( m_nPerformanceBank ) ;
FRESULT Result = f_findfirst ( & Directory , & FileInfo , FileN . c_str ( ) , m_nPerformanceFileName [ nID ] . c_str ( ) ) ;
FRESULT Result = f_findfirst ( & Directory , & FileInfo , FileN . c_str ( ) , GetPerformanceFileName ( nID ) . c_str ( ) ) ;
if ( Result = = FR_OK & & FileInfo . fname [ 0 ] )
{
FileN + = " / " ;
FileN + = m_nPerformanceFileName [ nID ] ;
FileN + = GetPerformanceFileName ( nID ) ;
Result = f_unlink ( FileN . c_str ( ) ) ;
if ( Result = = FR_OK )
{
SetNewPerformance ( 0 ) ;
nActualPerformance = 0 ;
m_ nActualPerformance = 0 ;
//nMenuSelectedPerformance=0;
m_nPerformanceFileName [ nID ] = " ZZZZZZ " ;
sort ( m_nPerformanceFileName + 1 , m_nPerformanceFileName + nLastPerformance ) ; // test si va con -1 o no
- - nLastPerformance ;
m_nPerformanceFileName [ nLastPerformance ] = nullptr ;
m_PerformanceFileName [ nID ] . clear ( ) ;
// If this was the last performance in the bank...
if ( nID = = m_nLastPerformance )
{
do
{
// Find the new last performance
m_nLastPerformance - - ;
} while ( ! IsValidPerformance ( m_nLastPerformance ) & & ( m_nLastPerformance > 0 ) ) ;
}
bOK = true ;
}
else
{
LOGNOTE ( " Failed to delete %s " , FileN . c_str ( ) ) ;
}
}
return bOK ;
}
bool CPerformanceConfig : : ListPerformanceBanks ( )
{
m_nPerformanceBank = 0 ;
m_nLastPerformance = 0 ;
m_nLastPerformanceBank = 0 ;
// Open performance directory
DIR Directory ;
FILINFO FileInfo ;
FRESULT Result ;
Result = f_opendir ( & Directory , " SD:/ " PERFORMANCE_DIR ) ;
if ( Result ! = FR_OK )
{
// No performance directory, so no performance banks.
// So nothing else to do here
LOGNOTE ( " No performance banks detected " ) ;
m_bPerformanceDirectoryExists = false ;
return false ;
}
unsigned nNumBanks = 0 ;
// Add in the default performance directory as the first bank
m_PerformanceBankName [ 0 ] = DEFAULT_PERFORMANCE_BANK_NAME ;
nNumBanks = 1 ;
m_nLastPerformanceBank = 0 ;
// List directories with names in format 01_Perf Bank Name
Result = f_findfirst ( & Directory , & FileInfo , " SD:/ " PERFORMANCE_DIR , " * " ) ;
for ( unsigned i = 0 ; Result = = FR_OK & & FileInfo . fname [ 0 ] ; i + + )
{
// Check to see if it is a directory
if ( ( FileInfo . fattrib & AM_DIR ) ! = 0 )
{
// Looking for Performance banks of the form: 01_Perf Bank Name
// So positions 0,1,2 = decimal digit
// position 3 = "_"
// positions 4.. = actual name
//
std : : string OriFileName = FileInfo . fname ;
size_t nLen = OriFileName . length ( ) ;
if ( nLen > 4 & & nLen < 26 & & strcmp ( OriFileName . substr ( 3 , 1 ) . c_str ( ) , " _ " ) = = 0 )
{
unsigned nBankIndex = stoi ( OriFileName . substr ( 0 , 3 ) ) ;
// Recall user index numbered 002..NUM_PERFORMANCE_BANKS
// NB: Bank 001 is reserved for the default performance directory
if ( ( nBankIndex > 0 ) & & ( nBankIndex < = NUM_PERFORMANCE_BANKS ) )
{
// Convert from "user facing" 1..indexed number to internal 0..indexed
nBankIndex = nBankIndex - 1 ;
if ( m_PerformanceBankName [ nBankIndex ] . empty ( ) )
{
std : : string BankName = OriFileName . substr ( 4 , nLen ) ;
m_PerformanceBankName [ nBankIndex ] = BankName ;
# ifdef VERBOSE_DEBUG
LOGNOTE ( " Found performance bank %s (%d, %s) " , OriFileName . c_str ( ) , nBankIndex , BankName . c_str ( ) ) ;
# endif
nNumBanks + + ;
if ( nBankIndex > m_nLastPerformanceBank )
{
m_nLastPerformanceBank = nBankIndex ;
}
}
else
{
LOGNOTE ( " Duplicate Performance Bank: %s " , FileInfo . fname ) ;
if ( nBankIndex = = 0 )
{
LOGNOTE ( " (Bank 001 is the default performance directory) " ) ;
}
}
}
else
{
LOGNOTE ( " Performance Bank number out of range: %s (%d to %d) " , FileInfo . fname , 1 , NUM_PERFORMANCE_BANKS ) ;
}
}
else
{
# ifdef VERBOSE_DEBUG
LOGNOTE ( " Skipping: %s " , FileInfo . fname ) ;
# endif
}
}
Result = f_findnext ( & Directory , & FileInfo ) ;
}
if ( nNumBanks > 0 )
{
LOGNOTE ( " Number of Performance Banks: %d (last = %d) " , nNumBanks , m_nLastPerformanceBank + 1 ) ;
}
f_closedir ( & Directory ) ;
return true ;
}
void CPerformanceConfig : : SetNewPerformanceBank ( unsigned nBankID )
{
assert ( nBankID < NUM_PERFORMANCE_BANKS ) ;
if ( IsValidPerformanceBank ( nBankID ) )
{
# ifdef VERBOSE_DEBUG
LOGNOTE ( " Selecting Performance Bank: %d " , nBankID + 1 ) ;
# endif
m_nPerformanceBank = nBankID ;
m_nActualPerformanceBank = nBankID ;
ListPerformances ( ) ;
}
else
{
# ifdef VERBOSE_DEBUG
LOGNOTE ( " Not selecting invalid Performance Bank: %d " , nBankID + 1 ) ;
# endif
}
}
unsigned CPerformanceConfig : : GetPerformanceBank ( void )
{
return m_nPerformanceBank ;
}
std : : string CPerformanceConfig : : GetPerformanceBankName ( unsigned nBankID )
{
assert ( nBankID < NUM_PERFORMANCE_BANKS ) ;
if ( IsValidPerformanceBank ( nBankID ) )
{
return m_PerformanceBankName [ nBankID ] ;
}
else
{
return DEFAULT_PERFORMANCE_BANK_NAME ;
}
}
std : : string CPerformanceConfig : : AddPerformanceBankDirName ( unsigned nBankID )
{
assert ( nBankID < NUM_PERFORMANCE_BANKS ) ;
if ( IsValidPerformanceBank ( nBankID ) )
{
// Performance Banks directories in format "001_Bank Name"
std : : string Index ;
if ( nBankID = = 0 )
{
// Legacy: Bank 1 is the default performance directory
return " " ;
}
if ( nBankID < 9 )
{
Index = " 00 " + std : : to_string ( nBankID + 1 ) ;
}
else if ( nBankID < 99 )
{
Index = " 0 " + std : : to_string ( nBankID + 1 ) ;
}
else
{
Index = std : : to_string ( nBankID + 1 ) ;
}
return " / " + Index + " _ " + m_PerformanceBankName [ nBankID ] ;
}
else
{
return " " ;
}
}
bool CPerformanceConfig : : IsValidPerformanceBank ( unsigned nBankID )
{
if ( nBankID > = NUM_PERFORMANCE_BANKS ) {
return false ;
}
if ( m_PerformanceBankName [ nBankID ] . empty ( ) )
{
return false ;
}
return true ;
}