bool FeRomList::fix_filters( FeDisplayInfo &display, FeRomInfo::Index target ) { bool retval = false; for ( int i=0; i<display.get_filter_count(); i++ ) { FeFilter *f = display.get_filter( i ); ASSERT( f ); if ( f->test_for_target( target ) ) { m_filtered_list[i].clear(); retval = true; for ( FeRomInfoListType::iterator itr=m_list.begin(); itr!=m_list.end(); ++itr ) { if ( f->apply_filter( *itr ) ) m_filtered_list[i].push_back( &( *itr ) ); } } } return retval; }
bool FeSettings::build_romlist( const std::vector< FeImportTask > &task_list, const std::string &output_name, FeFilter &filter, bool full ) { FeRomInfoListType total_romlist; std::string best_name, list_name, path; for ( std::vector<FeImportTask>::const_iterator itr=task_list.begin(); itr < task_list.end(); ++itr ) { if ( (*itr).task_type == FeImportTask::BuildRomlist ) { // Build romlist task std::cout << "*** Generating Collection/Rom List" << std::endl; FeEmulatorInfo *emu = m_rl.get_emulator( (*itr).emulator_name ); if ( emu == NULL ) { std::cout << "Error: Invalid -build-rom-list target: " << (*itr).emulator_name << std::endl; } else { FeRomInfoListType romlist; best_name = emu->get_info( FeEmulatorInfo::Name ); FeImporterContext ctx( *emu, romlist ); build_basic_romlist( ctx ); apply_xml_import( ctx ); apply_import_extras( ctx ); apply_emulator_name( best_name, romlist ); total_romlist.splice( total_romlist.end(), romlist ); } } else if ( (*itr).task_type == FeImportTask::ImportRomlist ) { // import romlist from file task std::cout << "*** Importing Collection/Rom List" << std::endl; FeRomInfoListType romlist; std::string emu_name; if ( (*itr).emulator_name.empty() ) { // deduce the emulator name from the filename provided size_t my_start = (*itr).file_name.find_last_of( "\\/" ); if ( my_start == std::string::npos ) // if there is no / we start at the beginning my_start = 0; else my_start += 1; size_t my_end = (*itr).file_name.find_last_of( "." ); if ( my_end != std::string::npos ) emu_name = (*itr).file_name.substr( my_start, my_end - my_start ); } else emu_name = (*itr).emulator_name; best_name = emu_name; if ( tail_compare( (*itr).file_name, ".txt" ) ) { // Attract-Mode format list // FeRomList temp_list( m_config_path ); temp_list.load_from_file( (*itr).file_name, ";" ); FeRomInfoListType &entries = temp_list.get_list(); for ( FeRomInfoListType::iterator itr = entries.begin(); itr != entries.end(); ++itr ) romlist.push_back( *itr ); } else if ( tail_compare( (*itr).file_name, ".lst" ) ) { // Mamewah/Wahcade! format list // import_mamewah( (*itr).file_name, emu_name, romlist ); } else if ( tail_compare( (*itr).file_name, ".xml" ) ) { // HyperSpin format list // FeHyperSpinXMLParser my_parser( romlist ); if ( my_parser.parse( (*itr).file_name ) ) apply_emulator_name( emu_name, romlist ); } else { std::cerr << "Error: Unsupported --import-rom-list file: " << (*itr).file_name << std::endl; } std::cout << "[Import " << (*itr).file_name << "] - Imported " << romlist.size() << " entries." << std::endl; FeEmulatorInfo *emu = m_rl.get_emulator( emu_name ); if ( emu == NULL ) { std::cout << "Warning: The emulator specified with --import-rom-list was not found: " << emu_name << std::endl; } else { FeImporterContext ctx( *emu, romlist ); apply_import_extras( ctx ); } total_romlist.splice( total_romlist.end(), romlist ); } else // scrape artwork { FeEmulatorInfo *emu = m_rl.get_emulator( (*itr).emulator_name ); if ( emu == NULL ) return false; std::cout << "*** Scraping artwork for: " << (*itr).emulator_name << std::endl; FeRomInfoListType romlist; std::string fn = get_config_dir() + FE_ROMLIST_SUBDIR + (*itr).emulator_name + FE_ROMLIST_FILE_EXTENSION; FeImporterContext ctx( *emu, romlist ); if ( file_exists( fn ) ) { FeRomList loader( get_config_dir() ); loader.load_from_file( fn, ";" ); ctx.romlist.swap( loader.get_list() ); } else { build_basic_romlist( ctx ); apply_xml_import( ctx ); } ctx.scrape_art = true; confirm_directory( get_config_dir(), FE_SCRAPER_SUBDIR ); // do the mamedb scraper first (which only does anything for mame) followed // by the more general thegamesdb scraper. mamedb_scraper( ctx ); thegamesdb_scraper( ctx ); std::cout << "*** Scraping done." << std::endl; } } // return now if all we did was scrape artwork if ( total_romlist.empty() ) return true; total_romlist.sort( FeRomListSorter() ); // strip duplicate entries std::cout << " - Removing any duplicate entries..." << std::endl; total_romlist.unique(); // Apply the specified filter if ( filter.get_rule_count() > 0 ) { std::cout << " - Applying filter..." << std::endl; filter.init(); FeRomInfoListType::iterator last_it=total_romlist.begin(); for ( FeRomInfoListType::iterator it=total_romlist.begin(); it!=total_romlist.end(); ) { if ( filter.apply_filter( *it ) ) { if ( last_it != it ) it = total_romlist.erase( last_it, it ); else ++it; last_it = it; } else ++it; } if ( last_it != total_romlist.end() ) total_romlist.erase( last_it, total_romlist.end() ); } if ( task_list.size() > 1 ) best_name = "multi"; path = get_config_dir(); confirm_directory( path, FE_ROMLIST_SUBDIR ); path += FE_ROMLIST_SUBDIR; // if we weren't given a specific output name, then we come up with a name // that doesn't exist already // if ( output_name.empty() ) get_available_filename( path, best_name, FE_ROMLIST_FILE_EXTENSION, list_name ); else list_name = path + output_name + FE_ROMLIST_FILE_EXTENSION; write_romlist( list_name, total_romlist ); return true; }
bool FeRomList::load_romlist( const std::string &path, const std::string &romlist_name, const std::string &user_path, const std::string &stat_path, FeDisplayInfo &display ) { m_user_path = user_path; m_romlist_name = romlist_name; m_list.clear(); m_filtered_list.clear(); m_availability_checked = false; m_global_filter_ptr = NULL; m_global_filtered_out_count = 0; FeFilter *first_filter = display.get_global_filter(); if ( first_filter ) { first_filter->init(); if ( !first_filter->test_for_target( FeRomInfo::FileIsAvailable ) && !first_filter->test_for_target( FeRomInfo::Favourite ) && !first_filter->test_for_target( FeRomInfo::Tags ) ) { // If the global filter doesn't care about file availability, // favourites or tags then we can apply it right up front when we // load the romlist. We signal this by setting m_global_filter_ptr m_global_filter_ptr = first_filter; first_filter = NULL; } } sf::Clock load_timer; bool retval = FeBaseConfigurable::load_from_file( path + m_romlist_name + FE_ROMLIST_FILE_EXTENSION, ";" ); // // Create rom name to romlist entry lookup map // std::map < std::string, FeRomInfo * > rom_map; std::map < std::string, FeRomInfo * >::iterator rm_itr; for ( FeRomInfoListType::iterator itr = m_list.begin(); itr != m_list.end(); ++itr ) rom_map[ (*itr).get_info( FeRomInfo::Romname ) ] = &(*itr); // // Load favourites // m_extra_favs.clear(); m_fav_changed=false; std::string load_name( m_user_path + m_romlist_name + FE_FAVOURITE_FILE_EXTENSION ); std::ifstream myfile( load_name.c_str() ); if ( myfile.is_open() ) { while ( myfile.good() ) { size_t pos=0; std::string line, name; getline( myfile, line ); token_helper( line, pos, name ); if ( !name.empty() ) { rm_itr = rom_map.find( name ); if ( rm_itr != rom_map.end() ) (*rm_itr).second->set_info( FeRomInfo::Favourite, "1" ); else m_extra_favs.insert( name ); } } myfile.close(); } // // Load tags // m_tags.clear(); m_extra_tags.clear(); m_tags_changed=false; load_name = m_user_path + m_romlist_name + "/"; if ( directory_exists( load_name ) ) { std::vector<std::string> temp_tags; get_basename_from_extension( temp_tags, load_name, FE_FAVOURITE_FILE_EXTENSION ); for ( std::vector<std::string>::iterator itr=temp_tags.begin(); itr!=temp_tags.end(); ++itr ) { if ( (*itr).empty() ) continue; std::ifstream myfile( std::string(load_name + (*itr) + FE_FAVOURITE_FILE_EXTENSION).c_str() ); if ( !myfile.is_open() ) continue; std::map<std::string, bool>::iterator itt = m_tags.begin(); itt = m_tags.insert( itt, std::pair<std::string,bool>( (*itr), false ) ); while ( myfile.good() ) { size_t pos=0; std::string line, rname; getline( myfile, line ); token_helper( line, pos, rname ); if ( !rname.empty() ) { rm_itr = rom_map.find( rname ); if ( rm_itr != rom_map.end() ) (*rm_itr).second->append_tag( (*itt).first.c_str() ); else m_extra_tags.insert( std::pair<std::string,const char*>(rname, (*itt).first.c_str() ) ); } } myfile.close(); } } // Apply global filter if it hasn't been applied already if ( first_filter ) { if ( first_filter->test_for_target( FeRomInfo::FileIsAvailable ) ) get_file_availability(); FeRomInfoListType::iterator last_it=m_list.begin(); for ( FeRomInfoListType::iterator it=m_list.begin(); it!=m_list.end(); ) { if ( first_filter->apply_filter( *it ) ) { if ( last_it != it ) it = m_list.erase( last_it, it ); else ++it; last_it = it; } else { // // This rom is being filtered out and we may need to keep track of a few things // // 1. Track if this is a favourite... // if ( !(*it).get_info( FeRomInfo::Favourite ).empty() ) m_extra_favs.insert( (*it).get_info( FeRomInfo::Romname ) ); // // 2. Track if this rom has tags we'll need to keep // if ( !(*it).get_info( FeRomInfo::Tags ).empty() ) { const std::string &name = (*it).get_info( FeRomInfo::Romname ); const std::string &tags = (*it).get_info( FeRomInfo::Tags ); const char sep[] = { FE_TAGS_SEP, 0 }; size_t pos=0; while ( pos < tags.size() ) { std::string one_tag; token_helper( tags, pos, one_tag, sep ); std::map<std::string, bool>::iterator itt = m_tags.find( one_tag ); if ( itt != m_tags.end() ) m_extra_tags.insert( std::pair<std::string,const char *>( name, (*itt).first.c_str() ) ); } } m_global_filtered_out_count++; ++it; } } if ( last_it != m_list.end() ) m_list.erase( last_it, m_list.end() ); } std::cout << " - Loaded master romlist '" << m_romlist_name << "' in " << load_timer.getElapsedTime().asMilliseconds() << " ms (" << m_list.size() << " entries kept, " << m_global_filtered_out_count << " discarded)" << std::endl; load_timer.restart(); // // Apply filters // int filters_count = display.get_filter_count(); // // If the display doesn't have any filters configured, we create a single "filter" in the romlist object // with every romlist entry in it // if ( filters_count == 0 ) filters_count = 1; m_filtered_list.reserve( filters_count ); for ( int i=0; i<filters_count; i++ ) { m_filtered_list.push_back( std::vector< FeRomInfo *>() ); FeFilter *f = display.get_filter( i ); if ( f ) { if ( f->get_size() > 0 ) // if this is non zero then we've loaded before and know how many to expect m_filtered_list[i].reserve( f->get_size() ); if ( f->test_for_target( FeRomInfo::FileIsAvailable ) ) get_file_availability(); f->init(); for ( FeRomInfoListType::iterator itr=m_list.begin(); itr!=m_list.end(); ++itr ) if ( f->apply_filter( *itr ) ) m_filtered_list[i].push_back( &( *itr ) ); } else // no filter situation, so we just add the entire list... { m_filtered_list[i].reserve( m_list.size() ); for ( FeRomInfoListType::iterator itr=m_list.begin(); itr!=m_list.end(); ++itr ) m_filtered_list[i].push_back( &( *itr ) ); } // // make sure stats are loaded for the roms we will be showing // if ( !stat_path.empty() ) { for ( std::vector< FeRomInfo * >::iterator itf=m_filtered_list[i].begin(); itf!=m_filtered_list[i].end(); ++itf ) (*itf)->load_stats( stat_path ); // this will just return if stats are already loaded for the rom } if ( f ) { // track the size of the filtered list in our filter info object f->set_size( m_filtered_list[i].size() ); // // Sort and/or prune now if configured for this filter // FeRomInfo::Index sort_by=f->get_sort_by(); bool rev = f->get_reverse_order(); int list_limit = f->get_list_limit(); if ( sort_by != FeRomInfo::LAST_INDEX ) { std::stable_sort( m_filtered_list[i].begin(), m_filtered_list[i].end(), FeRomListSorter2( sort_by, rev ) ); } else if ( rev != false ) std::reverse( m_filtered_list[i].begin(), m_filtered_list[i].end() ); if (( list_limit != 0 ) && ( (int)m_filtered_list[i].size() > abs( list_limit ) )) { if ( list_limit > 0 ) m_filtered_list[i].erase( m_filtered_list[i].begin() + list_limit, m_filtered_list[i].end() ); else m_filtered_list[i].erase( m_filtered_list[i].begin(), m_filtered_list[i].end() + list_limit ); } } } std::cout << " - Constructed " << filters_count << " filters in " << load_timer.getElapsedTime().asMilliseconds() << " ms (" << filters_count * m_list.size() << " comparisons)" << std::endl; return retval; }