1 //
2 // C++ Implementation: PresetLoader
3 //
4 // Description:
5 //
6 //
7 // Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2007
8 //
9 // Copyright: See COPYING file that comes with this distribution
10 //
11 //
12 #include "PresetLoader.hpp"
13 #include "Preset.hpp"
14 #include "PresetFactory.hpp"
15 #include <iostream>
16 #include <sstream>
17 #include <set>
18 
19 #ifdef LINUX
20 extern "C"
21 {
22 #include <errno.h>
23 }
24 #endif
25 
26 #ifdef MACOS
27 extern "C"
28 {
29 #include <errno.h>
30 }
31 #endif
32 
33 #include <cassert>
34 #include "fatal.h"
35 
36 #include "Common.hpp"
37 
PresetLoader(int gx,int gy,std::string dirname=std::string ())38 PresetLoader::PresetLoader (int gx, int gy, std::string dirname = std::string()) :_dirname ( dirname ), _dir ( 0 )
39 {
40 	_presetFactoryManager.initialize(gx,gy);
41 	// Do one scan
42 	if ( _dirname != std::string() )
43 		rescan();
44 	else
45 		clear();
46 }
47 
~PresetLoader()48 PresetLoader::~PresetLoader()
49 {
50 	if ( _dir )
51 		closedir ( _dir );
52 }
53 
setScanDirectory(std::string dirname)54 void PresetLoader::setScanDirectory ( std::string dirname )
55 {
56 	_dirname = dirname;
57 }
58 
59 
rescan()60 void PresetLoader::rescan()
61 {
62 	// std::cerr << "Rescanning..." << std::endl;
63 
64 	// Clear the directory entry collection
65 	clear();
66 
67 	// If directory already opened, close it first
68 	if ( _dir )
69 	{
70 		closedir ( _dir );
71 		_dir = 0;
72 	}
73 
74 	// Allocate a new a stream given the current directory name
75 	if ( ( _dir = opendir ( _dirname.c_str() ) ) == NULL )
76 	{
77 		handleDirectoryError();
78 		return; // no files loaded. _entries is empty
79 	}
80 
81 	struct dirent * dir_entry;
82 	std::set<std::string> alphaSortedFileSet;
83 	std::set<std::string> alphaSortedPresetNameSet;
84 
85 	while ( ( dir_entry = readdir ( _dir ) ) != NULL )
86 	{
87     if (dir_entry->d_name == 0)
88       continue;
89 
90 		std::ostringstream out;
91 		// Convert char * to friendly string
92 		std::string filename ( dir_entry->d_name );
93 
94 		// Verify extension is projectm or milkdrop
95 		if (!_presetFactoryManager.extensionHandled(parseExtension(filename)))
96 			continue;
97 
98 		if ( filename.length() > 0 && filename[0] == '.' )
99 			continue;
100 
101 		// Create full path name
102 		out << _dirname << PATH_SEPARATOR << filename;
103 
104 		// Add to our directory entry collection
105 		alphaSortedFileSet.insert ( out.str() );
106 		alphaSortedPresetNameSet.insert ( filename );
107 
108 		// the directory entry struct is freed elsewhere
109 	}
110 
111 	// Push all entries in order from the file set to the file entries member (which is an indexed vector)
112 	for ( std::set<std::string>::iterator pos = alphaSortedFileSet.begin();
113 	        pos != alphaSortedFileSet.end();++pos )
114 		_entries.push_back ( *pos );
115 
116 	// Push all preset names in similar fashion
117 	for ( std::set<std::string>::iterator pos = alphaSortedPresetNameSet.begin();
118 	        pos != alphaSortedPresetNameSet.end();++pos )
119 		_presetNames.push_back ( *pos );
120 
121 	// Give all presets equal rating of 3 - why 3? I don't know
122 	_ratings = std::vector<RatingList>(TOTAL_RATING_TYPES, RatingList( _presetNames.size(), 3 ));
123 	_ratingsSums = std::vector<int>(TOTAL_RATING_TYPES, 3 * _presetNames.size());
124 
125 
126 	assert ( _entries.size() == _presetNames.size() );
127 
128 
129 
130 }
131 
132 
loadPreset(unsigned int index) const133 std::auto_ptr<Preset> PresetLoader::loadPreset ( unsigned int index )  const
134 {
135 
136 	// Check that index isn't insane
137 	assert ( index >= 0 );
138 	assert ( index < _entries.size() );
139 
140 	// Return a new autopointer to a preset
141 	const std::string extension = parseExtension ( _entries[index] );
142 
143 	return _presetFactoryManager.factory(extension).allocate
144 		( _entries[index], _presetNames[index] );
145 
146 }
147 
148 
loadPreset(const std::string & url) const149 std::auto_ptr<Preset> PresetLoader::loadPreset ( const std::string & url )  const
150 {
151 
152 	// Return a new autopointer to a preset
153 	const std::string extension = parseExtension ( url );
154 
155 	/// @bug probably should not use url for preset name
156 	return _presetFactoryManager.factory(extension).allocate
157 		(url, url);
158 
159 }
160 
handleDirectoryError()161 void PresetLoader::handleDirectoryError()
162 {
163 
164 #ifdef WIN32
165 	std::cerr << "[PresetLoader] warning: errno unsupported on win32 platforms. fix me" << std::endl;
166 #else
167 
168 	switch ( errno )
169 	{
170 		case ENOENT:
171 			std::cerr << "[PresetLoader] ENOENT error. The path \"" << this->_dirname << "\" probably does not exist. \"man open\" for more info." << std::endl;
172 			break;
173 		case ENOMEM:
174 			std::cerr << "[PresetLoader] out of memory! Are you running Windows?" << std::endl;
175 			abort();
176 		case ENOTDIR:
177 			std::cerr << "[PresetLoader] directory specified is not a preset directory! Trying to continue..." << std::endl;
178 			break;
179 		case ENFILE:
180 			std::cerr << "[PresetLoader] Your system has reached its open file limit. Trying to continue..." << std::endl;
181 			break;
182 		case EMFILE:
183 			std::cerr << "[PresetLoader] too many files in use by projectM! Bailing!" << std::endl;
184 			break;
185 		case EACCES:
186 			std::cerr << "[PresetLoader] permissions issue reading the specified preset directory." << std::endl;
187 			break;
188 		default:
189 			break;
190 	}
191 #endif
192 }
193 
setRating(unsigned int index,int rating,const PresetRatingType ratingType)194 void PresetLoader::setRating(unsigned int index, int rating, const PresetRatingType ratingType)
195 {
196 	assert ( index >=0 );
197 
198 	const unsigned int ratingTypeIndex = static_cast<unsigned int>(ratingType);
199 	assert (index < _ratings[ratingTypeIndex].size());
200 
201 	_ratingsSums[ratingTypeIndex] -= _ratings[ratingTypeIndex][index];
202 
203 	_ratings[ratingTypeIndex][index] = rating;
204 	_ratingsSums[ratingType] += rating;
205 
206 }
207 
208 
addPresetURL(const std::string & url,const std::string & presetName,const std::vector<int> & ratings)209 unsigned int PresetLoader::addPresetURL ( const std::string & url, const std::string & presetName, const std::vector<int> & ratings)
210 {
211 	_entries.push_back(url);
212 	_presetNames.push_back ( presetName );
213 
214 	assert(ratings.size() == TOTAL_RATING_TYPES);
215 	assert(ratings.size() == _ratings.size());
216 
217 	for (int i = 0; i < _ratings.size(); i++)
218 		_ratings[i].push_back(ratings[i]);
219 
220 	for (int i = 0; i < ratings.size(); i++)
221 		_ratingsSums[i] += ratings[i];
222 
223 	return _entries.size()-1;
224 }
225 
removePreset(unsigned int index)226 void PresetLoader::removePreset ( unsigned int index )
227 {
228 
229 	_entries.erase ( _entries.begin() + index );
230 	_presetNames.erase ( _presetNames.begin() + index );
231 
232 	for (int i = 0; i < _ratingsSums.size(); i++) {
233 		_ratingsSums[i] -= _ratings[i][index];
234 		_ratings[i].erase ( _ratings[i].begin() + index );
235 	}
236 
237 
238 }
239 
getPresetURL(unsigned int index) const240 const std::string & PresetLoader::getPresetURL ( unsigned int index ) const
241 {
242 	return _entries[index];
243 }
244 
getPresetName(unsigned int index) const245 const std::string & PresetLoader::getPresetName ( unsigned int index ) const
246 {
247 	return _presetNames[index];
248 }
249 
getPresetRating(unsigned int index,const PresetRatingType ratingType) const250 int PresetLoader::getPresetRating ( unsigned int index, const PresetRatingType ratingType ) const
251 {
252 	return _ratings[ratingType][index];
253 }
254 
getPresetRatings() const255 const std::vector<RatingList> & PresetLoader::getPresetRatings () const
256 {
257 	return _ratings;
258 }
259 
getPresetRatingsSums() const260 const std::vector<int> & PresetLoader::getPresetRatingsSums() const {
261 	return _ratingsSums;
262 }
263 
setPresetName(unsigned int index,std::string name)264 void PresetLoader::setPresetName(unsigned int index, std::string name) {
265 	_presetNames[index] = name;
266 }
267 
insertPresetURL(unsigned int index,const std::string & url,const std::string & presetName,const RatingList & ratings)268 void PresetLoader::insertPresetURL ( unsigned int index, const std::string & url, const std::string & presetName, const RatingList & ratings)
269 {
270 	_entries.insert ( _entries.begin() + index, url );
271 	_presetNames.insert ( _presetNames.begin() + index, presetName );
272 
273 
274 
275 	for (int i = 0; i < _ratingsSums.size();i++) {
276 		_ratingsSums[i] += _ratings[i][index];
277 		_ratings[i].insert ( _ratings[i].begin() + index, ratings[i] );
278 	}
279 
280 	assert ( _entries.size() == _presetNames.size() );
281 
282 
283 }
284