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