2 Cafu Engine, http://www.cafu.de/
3 Copyright (c) Carsten Fuchs and other contributors.
4 This project is licensed under the terms of the MIT license.
7 #include "SoundShaderManagerImpl.hpp"
8 #include "SoundShader.hpp"
10 #include "TextParser/TextParser.hpp"
11 #include "FileSys/FileMan.hpp"
12 #include "FileSys/File.hpp"
17 #define WIN32_LEAN_AND_MEAN
28 SoundShaderManagerImplT::SoundShaderManagerImplT()
33 SoundShaderManagerImplT::~SoundShaderManagerImplT()
35 for (std::map
<std::string
, SoundShaderT
*>::const_iterator SoundShader
=m_SoundShaders
.begin(); SoundShader
!=m_SoundShaders
.end(); SoundShader
++)
36 delete SoundShader
->second
;
37 m_SoundShaders
.clear();
41 ArrayT
<const SoundShaderT
*> SoundShaderManagerImplT::RegisterSoundShaderScript(const std::string
& ScriptFile
, const std::string
& ModDir
)
43 ArrayT
<const SoundShaderT
*> NewSoundShaders
;
45 // Check if script has already been loaded and return empty sound shader array if this is the case.
46 for (unsigned long Nr
=0; Nr
<m_SoundShaderScriptFiles
.Size(); Nr
++)
47 if (m_SoundShaderScriptFiles
[Nr
]==ScriptFile
) return NewSoundShaders
;
49 m_SoundShaderScriptFiles
.PushBack(ScriptFile
);
51 // Get sound shaders from the script.
52 TextParserT
TextParser(ScriptFile
.c_str(), "({[]}),");
56 while (!TextParser
.IsAtEOF())
58 const std::string Token
=TextParser
.GetNextToken();
60 // If the sound shader cannot be parsed (e.g. due to a syntax error or unknown token),
61 // the parsing of the entire file is aborted - the file might be something else than a sound shader script.
62 // Even if it was, we cannot easily continue anyway.
64 SoundShaderT
* NewSoundShader
=new SoundShaderT(Token
, TextParser
, ModDir
);
65 SoundShaderT
*& TestShader
=m_SoundShaders
[NewSoundShader
->Name
];
67 // Check if sound shader with this name already exists.
70 TestShader
=NewSoundShader
;
71 NewSoundShaders
.PushBack(NewSoundShader
);
75 std::cout
<< "File '"<< ScriptFile
<< "' sound shader '" << NewSoundShader
->Name
<< "' duplicate definition (ignored).\n";
76 delete NewSoundShader
;
80 catch (const TextParserT::ParseError
&)
82 std::cout
<< "Error parsing '" << ScriptFile
<< "' at input byte " << TextParser
.GetReadPosByte() << "\n";
85 return NewSoundShaders
;
89 ArrayT
<const SoundShaderT
*> SoundShaderManagerImplT::RegisterSoundShaderScriptsInDir(const std::string
& Directory
, const std::string
& ModDir
, bool Recurse
)
91 ArrayT
<const SoundShaderT
*> NewSoundShaders
;
93 if (Directory
=="") return NewSoundShaders
;
96 WIN32_FIND_DATA FindFileData
;
98 HANDLE hFind
=FindFirstFile((Directory
+"\\*").c_str(), &FindFileData
);
100 // MessageBox(NULL, hFind==INVALID_HANDLE_VALUE ? "INV_VALUE!!" : FindFileData.cFileName, "Starting parsing.", MB_ICONINFORMATION);
101 if (hFind
==INVALID_HANDLE_VALUE
) return NewSoundShaders
;
103 ArrayT
<std::string
> DirEntNames
;
107 // MessageBox(NULL, FindFileData.cFileName, "Material Script Found", MB_ICONINFORMATION);
108 if (!_stricmp(FindFileData
.cFileName
, "." )) continue;
109 if (!_stricmp(FindFileData
.cFileName
, ".." )) continue;
110 if (!_stricmp(FindFileData
.cFileName
, "cvs")) continue;
112 DirEntNames
.PushBack(Directory
+"/"+FindFileData
.cFileName
);
113 } while (FindNextFile(hFind
, &FindFileData
)!=0);
115 if (GetLastError()==ERROR_NO_MORE_FILES
) FindClose(hFind
);
117 DIR* Dir
=opendir(Directory
.c_str());
119 if (!Dir
) return NewSoundShaders
;
121 ArrayT
<std::string
> DirEntNames
;
123 for (dirent
* DirEnt
=readdir(Dir
); DirEnt
!=NULL
; DirEnt
=readdir(Dir
))
125 if (!strcasecmp(DirEnt
->d_name
, "." )) continue;
126 if (!strcasecmp(DirEnt
->d_name
, ".." )) continue;
127 if (!strcasecmp(DirEnt
->d_name
, "cvs")) continue;
129 // For portability, only the 'd_name' member of a 'dirent' may be accessed.
130 DirEntNames
.PushBack(Directory
+"/"+DirEnt
->d_name
);
137 for (unsigned long DENr
=0; DENr
<DirEntNames
.Size(); DENr
++)
140 bool IsDirectory
=true;
142 FILE* TempFile
=fopen(DirEntNames
[DENr
].c_str(), "r");
145 // This was probably a file (instead of a directory).
150 bool IsDirectory
=false;
152 // Sigh. And this doesn't work under Win32... (opendir does not return NULL for files!?!)
153 DIR* TempDir
=opendir(DirEntNames
[DENr
].c_str());
156 // This was a directory.
165 NewSoundShaders
.PushBack(RegisterSoundShaderScriptsInDir(DirEntNames
[DENr
], ModDir
));
169 if (DirEntNames
[DENr
].length()>5)
170 if (std::string(DirEntNames
[DENr
].c_str()+DirEntNames
[DENr
].length()-5)==".caud")
171 NewSoundShaders
.PushBack(RegisterSoundShaderScript(DirEntNames
[DENr
], ModDir
));
175 return NewSoundShaders
;
179 static bool IsFile(const std::string
& Name
)
181 cf::FileSys::InFileI
* AudioFile
=cf::FileSys::FileMan
->OpenRead(Name
);
186 cf::FileSys::FileMan
->Close(AudioFile
);
191 static bool IsCapture(const std::string
& Name
)
193 return Name
.find("capture")==0 && Name
.length()>8;
197 const SoundShaderT
* SoundShaderManagerImplT::GetSoundShader(const std::string
& Name
)
199 // Ignore empty names and just return NULL.
200 if (Name
.empty()) return NULL
;
202 // Note that I'm *not* just writing return SoundShaders[Name] here, because that
203 // would implicitly create a NULL entry for every Name that does not actually exist.
204 std::map
<std::string
, SoundShaderT
*>::const_iterator It
=m_SoundShaders
.find(Name
);
206 if (It
!=m_SoundShaders
.end()) return It
->second
;
208 // Sound shader not found, try to interpret the name as a filename or a "capture n" string.
209 if (IsFile(Name
) || IsCapture(Name
))
211 SoundShaderT
* AutoShader
=new SoundShaderT(Name
);
212 AutoShader
->AudioFile
=Name
;
214 // Add auto created shader to list of shaders.
215 m_SoundShaders
[Name
]=AutoShader
;
220 std::cout
<< "Error auto creating sound shader: File '" << Name
<< "' not doesn't exist.\n";