1 /* ScummVM Tools
2  *
3  * ScummVM Tools is the legal property of its developers, whose
4  * names are too numerous to list here. Please refer to the
5  * COPYRIGHT file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 #ifndef TOOL_H
23 #define TOOL_H
24 
25 #include <vector>
26 #include <deque>
27 #include <string>
28 
29 #include "common/file.h"
30 
31 /**
32  * Different types of tools, used to differentiate them when
33  * fetching lists of games & tools.
34  */
35 enum ToolType {
36 	TOOLTYPE_COMPRESSION,
37 	TOOLTYPE_EXTRACTION,
38 	TOOLTYPE_UNKNOWN,
39 	TOOLTYPE_ALL
40 };
41 
42 /**
43  * Return type of the inspectInput function, perfect match means we know we can
44  * parse this file, possible means we might be able to, Awful means we most likely
45  * can't read this file.
46  * If there are perfect results, those are displayed first, if there are none,
47  * possible results are displayed and finally awful results are dispalyed.
48  */
49 enum InspectionMatch {
50 	IMATCH_PERFECT,
51 	IMATCH_POSSIBLE,
52 	IMATCH_AWFUL
53 };
54 
55 /**
56  * Describes a possible input to the tool (since some take two seperate files,
57  * some a dir and some a single file.
58  */
59 struct ToolInput {
ToolInputToolInput60 	ToolInput() : format("*.*"), file(true) {}
61 
62 	/** The expected format of the input file, in wildcard fashion. */
63 	std::string format;
64 	/** A short description of what file is expected, displayed in the UI. */
65 	std::string description;
66 	/** The path filled in. */
67 	std::string path;
68 	/** If false, this input is a directory. */
69 	bool file;
70 };
71 
72 typedef std::vector<ToolInput> ToolInputs;
73 
74 class Tool {
75 public:
76 	Tool(const std::string &name, ToolType type);
77 	virtual ~Tool();
78 
79 	/**
80 	 * Run tool with command line arguments.
81 	 */
82 	int run(const std::deque<std::string> &args);
83 
84 	/**
85 	 * Parse with args set already (modify the public members to set them).
86 	 * Exceptions are not caught, so this function may throw.
87 	 */
88 	void run();
89 
90 	/**
91 	 * Returns true if the file appears to be a valid input to this tool.
92 	 * Default implementation checks the name versus the expected inputs
93 	 * format.
94 	 *
95 	 * @param filename The file to inspect
96 	 */
97 	virtual InspectionMatch inspectInput(const Common::Filename &filename);
98 
99 	/**
100 	 * Check the given input path against the expected inputs that have not
101 	 * yet been provided. If it finds a match the input is stored and the
102 	 * function returns true. Otherwise it returns false.
103 	 *
104 	 * @param inputPath Input directory of file to store.
105 	 */
106 	bool addInputPath(const std::string& inputPath);
107 
108 	/**
109 	 * Clear the input paths previously given by calls to addInputPath()
110 	 * If you run the same tools multiple times with different inputs you
111 	 * will need to call this before giving the inputs for the second run
112 	 * (and each additional run thereafter).
113 	 */
114 	void clearInputPaths();
115 
116 	/**
117 	 * Aborts executing of the tool, can be called from another thread.
118 	 * The progress will not be aborted until the next call to notifyProgress.
119 	 */
120 	void abort();
121 
122 	/**
123 	 * Fatal error in the tool, throws a ToolException,
124 	 * you shouldn't really catch this exception.
125 	 */
126 	void error(const char *format, ...);
127 
128 	/**
129 	 * A warning, the same as print but WARNING: is prepended to the message.
130 	 */
131 	void warning(const char *format, ...);
132 
133 	/**
134 	 * Prints a formatted message, to either stdout or the GUI. Always use this
135 	 * instead of printf.
136 	 */
137 	void print(const char *format, ...);
138 
139 	/**
140 	 * Prints a message, to either stdout or the GUI.
141 	 */
142 	void print(const std::string &msg);
143 
144 	/** Returns name of the tool. */
145 	std::string getName() const;
146 
147 	/** Returns the help string of the tool. */
148 	virtual std::string getHelp() const;
149 
150 	/** Returns the short help string of the tool. */
151 	virtual std::string getShortHelp() const;
152 
153 	/** Returns the version string of the tool. */
154 	virtual std::string getVersion() const;
155 
156 	/** Returns the type of the tool. */
157 	ToolType getType() const;
158 
159 	/**
160 	 * Notifies of progress, normally just prints a dot if enough time
161 	 * has passed since the last call.
162 	 * This may through an AbortException, you should generally not catch this
163 	 * (except for doing cleanup).
164 	 *
165 	 * @param print_dot Provides visual feedback to the user, defaults to true
166 	 */
167 	void notifyProgress(bool print_dot = true);
168 
169 	/**
170 	 * Update progress in a more distinct way, if we know the estimated runtime.
171 	 * This may through an AbortException, you should generally not catch this
172 	 * (except for doing cleanup).
173 	 *
174 	 * @param done how many parts that have been done
175 	 * @param total parts in total
176 	 */
177 	void updateProgress(int done, int total = 100);
178 
179 	/**
180 	 * Spawns a subprocess with the given commandline.
181 	 * This acts exactly the same as 'system()', but hides the process window.
182 	 *
183 	 * @param cmd The commandline to run
184 	 */
185 	int spawnSubprocess(const char *cmd);
186 
187 	/**
188 	 * This function sets the function which will be called needs to
189 	 * output something.
190 	 *
191 	 * @param f the function to be called, it takes a userdata argument in addition to text to print
192 	 * @param udata The userdata to call to the print function each time it is called
193 	 */
194 	void setPrintFunction(void f(void *, const char *), void *udata);
195 
196 	/**
197 	 * Set the function that is called on status updates.
198 	 * Parameters to the function are 'done' and 'total', if total is 0,
199 	 * it's a simple status notification (print a dot or something).
200 	 *
201 	 * @param f this function will be called with udata arguments and 'done' / 'total'
202 	 * @param udata Userdata that will be passed to the function on each call
203 	 */
204 	void setProgressFunction(void f(void *, int, int), void *udata);
205 
206 	/**
207 	 * Sets the function to use to execute a process.
208 	 * This defaults to the function 'system()', GUI overloads this
209 	 * to not spawn a window.
210 	 *
211 	 * @param f this function will be called when a process needs to be spawned
212 	 * @param udata Userdata that will be passed to the function on each call
213 	 */
214 	void setSubprocessFunction(int f(void *, const char *), void *udata);
215 
216 protected:
217 	virtual void parseAudioArguments();
218 	virtual void setTempFileName();
219 	void parseOutputArguments();
220 
221 	InspectionMatch inspectInput(const Common::Filename &filename, const std::string& format);
222 
223 	/** Parses the arguments only this tool takes. */
224 	virtual void parseExtraArguments();
225 
226 	/** Runs the internal tool (the 'main'). */
227 	virtual void execute() = 0;
228 
229 public:
230 
231 	/** List of all inputs this tool expects, also contains the paths filled in. */
232 	ToolInputs _inputPaths;
233 
234 	// Output
235 	Common::Filename _outputPath;
236 
237 protected:
238 	/** Command line arguments we are parsing. */
239 	std::deque<std::string> _arguments;
240 
241 	/** If this tools outputs to a directory, not a file. */
242 	bool _outputToDirectory;
243 	/** If this tool can display output progress in percent. */
244 	bool _supportsProgressBar;
245 	/** If this tool can be run again on other files with the same extension **/
246 	bool _supportsMultipleRuns;
247 
248 	/** Name of the tool. */
249 	std::string _name;
250 	/** Type of the tool. */
251 	ToolType _type;
252 	/** The text to display to help the user. */
253 	std::string _helptext;
254 	/** The text to display to help the user. */
255 	std::string _shorthelp;
256 
257 	/** Status of internal abort flag, if set, next call to *Progress will throw. */
258 	bool _abort;
259 
260 private:
261 	typedef void (*PrintFunction)(void *, const char *);
262 	PrintFunction _internalPrint;
263 	void *_print_udata;
264 
265 	typedef void (*ProgressFunction)(void *, int, int);
266 	ProgressFunction _internalProgress;
267 	void *_progress_udata;
268 
269 	typedef int (*SubprocessFunction)(void *, const char *);
270 	SubprocessFunction _internalSubprocess;
271 	void *_subprocess_udata;
272 
273 	// Standard print function
274 	static void standardPrint(void *udata, const char *message);
275 
276 	// Standard progress function
277 	static void standardProgress(void *udata, int done, int total);
278 
279 	// Standard subprocess function
280 	static int standardSpawnSubprocess(void *udata, const char *);
281 
282 	friend class ToolGUI;
283 };
284 
285 #endif
286 
287