Adonthell  0.4
prefs.cc
Go to the documentation of this file.
1 /*
2  $Id: prefs.cc,v 1.36 2006/09/03 20:48:08 ksterker Exp $
3 
4  Copyright (C) 2000/2001/2002/2003 Kai Sterker <kaisterker@linuxgames.com>
5  Part of the Adonthell Project http://adonthell.linuxgames.com
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file prefs.cc
17  *
18  * @author Kai Sterker
19  * @brief Adonthell's configuration
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <getopt.h>
26 #include <stdio.h>
27 #include <iostream>
28 #include <sys/stat.h>
29 #include <dirent.h>
30 #include <unistd.h>
31 #include "prefs.h"
32 #include "python_class.h"
33 #include "game.h"
34 
36 {
37  // set some default values where possible
38 #if defined (WIN32) || defined (__APPLE__)
39  screen_mode = 1; // Fullscreen
40 #else
41  screen_mode = 0; // Fullscreen
42 #endif
43 #if defined (QTOPIA)
44  double_screen = 0; // Double screen
45 #else
46  double_screen = 1; // Double screen
47 #endif
48  quick_load = 0; // Quick-load disabled
49  audio_channels = 1; // Stereo
50  audio_resolution = 1; // 16 bit
51  audio_sample_rate = 2; // 11025, 22050 or 44100 Hz
52  audio_volume = 100; // 0 - 100%
53  language = ""; // Let the user's environment decide
54  font = ""; // use default font
55 
56  // set the path to the adonthellrc file:
57 #ifndef SINGLE_DIR_INST
58  adonthellrc = string (getenv ("HOME")) + "/.adonthell";
59 #else
60  adonthellrc = string (".");
61 #endif
62 }
63 
64 /**
65  * Displays the help message - for internal use only.
66  *
67  */
68 void print_help_message (char * argv[])
69 {
70  cout << "Usage: " << argv[0] << " [OPTIONS] GAME" << endl;
71  cout << endl;
72  cout << "Where [OPTIONS] can be:\n";
73  cout << "-h print this help message" << endl;
74  cout << "-d print the data directory and exit" << endl;
75  cout << "-v print version and exit" << endl;
76  cout << "-l list installed games and exit" << endl;
77  cout << "-g dir play the game contained in dir (for development only)" << endl;
78  cout << "-c byte-compile all Python scripts in this directory (for " << endl;
79  cout << " development only)" << endl;
80 }
81 
82 /**
83  * Displays the available games - for internal use only.
84  *
85  */
87 {
88  struct dirent * d;
89  DIR * mydir = opendir ((game::global_data_dir() + "/games").c_str());
90  bool nogames = true;
91 
92  if (!mydir)
93  {
94  cerr << "Cannot open directory " << game::global_data_dir() + "/games!" << endl;
95  exit (1);
96  }
97 
98  while ((d = readdir (mydir)) != NULL)
99  {
100  string s (d->d_name);
101  if (s != "." && s != "..")
102  {
103  if (nogames)
104  {
105  nogames = false;
106  cout << "Installed games (Suitable for the GAME parameter):\n";
107  }
108  cout << " - " << d->d_name << endl;
109  }
110  }
111 
112  if (nogames) cout << "No games available.\n";
113 
114  closedir (mydir);
115 }
116 
117 void config::parse_arguments (int argc, char * argv[])
118 {
119  int c;
120 
121  // Check for options
122  while (1)
123  {
124  c = getopt (argc, argv, "lcdhvg:");
125  if (c == -1)
126  break;
127 
128  switch (c)
129  {
130  case 'l':
132  exit (0);
133  break;
134 
135  case 'd':
136  cout << game::global_data_dir() << endl;
137  exit (0);
138  break;
139 
140  case 'v':
141  cout << VERSION << endl;
142  exit (0);
143  break;
144 
145  case 'c':
146  {
147  python::init ();
148  python::exec_string ("import compileall; compileall.compile_dir (\".\", 0);");
149  python::cleanup ();
150  exit (0);
151  break;
152  }
153 
154  case 'g':
155  {
156  gamedir = optarg;
157  if (gamedir[gamedir.size () - 1] == '/')
158  gamedir.erase (gamedir.size () - 1);
159 
160  // Check whether the requested game directory exists
161  DIR * mydir = opendir (gamedir.c_str ());
162 
163  if (!mydir)
164  {
165  cerr << "Cannot open directory " << gamedir << "!" << endl;
166  exit (1);
167  }
168  closedir (mydir);
169 
170  break;
171  }
172 
173  case '?':
174  case 'h':
175  print_help_message (argv);
176  exit (0);
177  break;
178  }
179  }
180 
181  // Check whether the GAME parameter is needed
182  if (gamedir == "")
183  {
184  // Check whether the GAME parameter is given
185  if (argc - optind != 1)
186  {
187  print_help_message (argv);
188  exit (0);
189  }
190 
191  // Check whether the requested game exists
192  struct dirent * d;
193  DIR * mydir = opendir ((game::global_data_dir() + "/games").c_str());
194  bool found = false;
195 
196  if (!mydir)
197  {
198  cerr << "Cannot open directory " << game::global_data_dir() + "/games!" << endl;
199  exit (1);
200  }
201 
202  while ((d = readdir (mydir)) != NULL)
203  {
204  if (string (d->d_name) == argv[optind]) found = true;
205  }
206 
207  closedir (mydir);
208 
209  if (!found)
210  {
211  cerr << "Game '" << argv[optind] << "' can't be found.\n"
212  << "Run '" << argv[0] << " -l' for a list of available games.\n";
213  exit (1);
214  }
215 
216  // The game exists, so let the show continue...
217  gamedir = game::global_data_dir() + "/games/";
218  gamedir += argv[optind];
219  }
220 
221  // Now check whether the directory is a valid game directory
222  string tfile = gamedir + "/gamename.txt";
223  ifstream f (tfile.c_str ());
224  if (!f.is_open ())
225  {
226  cerr << "Directory " << gamedir << " is not a valid game directory.\n";
227  exit (1);
228  }
229  char t[256];
230  f.getline (t, 256);
231  game_name = t;
232  f.close ();
233 }
234 
235 
236 
237 // That's more or less a move operator, as the source is destroyed
238 config& config::operator =(const config *c)
239 {
245  adonthellrc = c->adonthellrc;
246 
247  delete c;
248  return *this;
249 }
250 
252 {
253  return (char *) adonthellrc.c_str ();
254 }
255 
256 // write a default configuration file
258 {
259  string fname;
260 
261 #ifndef WIN32
262  fname = adonthellrc + "/adonthellrc";
263 #else
264  fname = adonthellrc + "/adonthell.ini";
265 #endif
266 
267  ofstream rc (fname.c_str ());
268 
269  rc << "# Sample Adonthell configuration file;\n"
270  << "# edit to your needs!\n\n"
271  << "# Screen-mode num\n# 0 Windowed mode\n"
272  << "# 1 Fullscreen mode\n Screen-mode " << (int) screen_mode
273  << "\n\n" << "# Double-size num\n# 0 320x240 mode\n"
274  << "# 1 640x480 (double) mode\n Double-size "
275  << (int) double_screen << "\n\n"
276  << "# Language [locale]\n# Where locale has the form fr_FR or de_DE, etc.\n"
277  << " Language [" << language << "]\n\n"
278  << "# Font [font.ttf]\n# Path to a true type font to use. Leave empty for default\n"
279  << " Font [" << font << "]\n\n"
280  << "# Quick-load num\n# 0 off\n# 1 on\n Quick-load "
281  << (int) quick_load << "\n\n"
282  << "# Audio-channels num\n# 0 Mono\n# 1 Stereo\n"
283  << " Audio-channels " << (int) audio_channels << "\n\n"
284  << "# Audio-resolution num\n# 0 8 bit\n# 1 16 bit\n"
285  << " Audio-resolution " << (int) audio_resolution << "\n\n"
286  << "# Audio-sample-rate num\n# 0 11025 Hz\n# 1 22050 Hz\n# 2 44100 Hz\n"
287  << " Audio-sample-rate " << (int) audio_sample_rate << "\n\n"
288  << "# Audio-volume num\n# 0 - 100 %\n"
289  << " Audio-volume " << (int) audio_volume << "\n\n"
290  << "# Version number of this file. Please don't edit\n Version [" << VERSION << "]\n";
291 
292  rc.close ();
293 }
294 
296 {
297  int n, i = 1;
298  u_int32 major = 0, minor = 0, micro = 0, MAJOR, MINOR, MICRO;
299  char suffix[16] = "\0", SUFFIX[16] = "\0";
300  string s, fname;
301 
302 #ifndef WIN32
303  fname = adonthellrc + "/adonthellrc";
304 #else
305  fname = adonthellrc + "/adonthell.ini";
306 #endif
307 
308  // try to create that directory in case it dosn't exist
309 #ifdef WIN32
310  mkdir (adonthellrc.c_str ());
311 #else
312  mkdir (adonthellrc.c_str (), 0700);
313 #endif
314 
315  // prefsin is declared in lex.prefs.c
316  prefsin = fopen (fname.c_str (), "r");
317 
318  // open failed -> try to write new configuration
319  if (!prefsin)
320  {
322 
323  // now try again
324  if (!(prefsin = fopen (fname.c_str (), "r")))
325  {
326  fprintf (stderr, "*** warning: prefs::read_adonthellrc: creating config file failed\n");
327  return false;
328  }
329  }
330 
331  // adonthellrc opened -> read configuration
332  while (i)
333  {
334  switch (i = parse_adonthellrc (n, s))
335  {
336  case PREFS_LANGUAGE:
337  {
338  if (parse_adonthellrc (n, s) == PREFS_STR) language = s;
339  break;
340  }
341  case PREFS_FONT:
342  {
343  if (parse_adonthellrc (n, s) == PREFS_NUM) font = s;
344  break;
345  }
346  case PREFS_SCREEN_MODE:
347  {
348  if (parse_adonthellrc (n, s) == PREFS_NUM) screen_mode = n;
349  break;
350  }
351 
352  case PREFS_DOUBLE_SCREEN:
353  {
354  if (parse_adonthellrc (n, s) == PREFS_NUM) double_screen = n;
355  break;
356  }
357 
358  case PREFS_QUICK_LOAD:
359  {
360  if (parse_adonthellrc (n, s) == PREFS_NUM) quick_load = n;
361  break;
362  }
363 
364  case PREFS_AUDIO_RESOLUTION:
365  {
366  if (parse_adonthellrc (n, s) == PREFS_NUM) audio_resolution = n;
367  break;
368  }
369 
370  case PREFS_AUDIO_CHANNELS:
371  {
372  if (parse_adonthellrc (n, s) == PREFS_NUM) audio_channels = n;
373  break;
374  }
375 
376  case PREFS_AUDIO_SAMPLE_RATE:
377  {
378  if (parse_adonthellrc (n, s) == PREFS_NUM) audio_sample_rate = n;
379  break;
380  }
381 
382  case PREFS_AUDIO_VOLUME:
383  {
384  if (parse_adonthellrc (n, s) == PREFS_NUM) audio_volume = n;
385  break;
386  }
387 
388  case PREFS_VERSION:
389  {
390  // get config file version number
391  if (parse_adonthellrc (n, s) == PREFS_STR)
392  sscanf (s.c_str (), "%d.%d.%d%15s", &major, &minor, &micro, suffix);
393  break;
394  }
395  default: break;
396  }
397  }
398 
399  fclose (prefsin);
400 
401  // get engine version numbers
402  sscanf (VERSION, "%d.%d.%d%15s", &MAJOR, &MINOR, &MICRO, SUFFIX);
403 
404  // compare version of config file and engine
405  if (major < MAJOR ||
406  (major == MAJOR && minor < MINOR) ||
407  (major == MAJOR && minor == MINOR && micro < MICRO) ||
408  strcmp (suffix, SUFFIX) != 0)
409  {
410  // update config file if engine is newer
412  }
413 
414  return true;
415 }
bool read_adonthellrc()
Reads the configuration file.
Definition: prefs.cc:295
char * get_adonthellrc()
Returns the path to the user's private Adonthell directory.
Definition: prefs.cc:251
FILE * prefsin
The config file opened by the lexical scanner.
string gamedir
Path of the directory that contains the game running at present.
Definition: prefs.h:135
Adonthell's configuration.
u_int8 audio_sample_rate
The sample rate: 11025 Hz (0), 22050 Hz (1) or 44100 Hz (2)
Definition: prefs.h:156
Declares the game class.
#define u_int32
32 bits long unsigned integer
Definition: types.h:35
void print_help_message(char *argv[])
Displays the help message - for internal use only.
Definition: prefs.cc:68
string language
Language to use if NLS was compiled in.
Definition: prefs.h:126
static string global_data_dir()
Returns the absolute path to the global data directory.
Definition: game.h:86
config()
Constructor.
Definition: prefs.cc:35
int parse_adonthellrc(int &, string &)
Start the lexical scanner to parse the config file, usually fount at ~/.adonthell/adonthellrc.
u_int8 quick_load
Whether the quick-load feature is enabled (1) or not (0)
Definition: prefs.h:144
Defines the python class. This file is named this way so it doesn't conflicts with Python...
u_int8 audio_volume
The volume: a value betwen 0 and 100.
Definition: prefs.h:161
static void exec_string(char *s)
Execute Python statements contained in a string.
Definition: python_class.cc:75
void parse_arguments(int argc, char *argv[])
See whether any options have been specified on the command line.
Definition: prefs.cc:117
void write_adonthellrc()
Writes a default configuration file with the values set in the constructor.
Definition: prefs.cc:257
string game_name
Name of the game that is running at present.
Definition: prefs.h:131
u_int8 audio_resolution
The resolution: 8 bit (0) or 16 bit (1)
Definition: prefs.h:152
void print_available_games()
Displays the available games - for internal use only.
Definition: prefs.cc:86
u_int8 audio_channels
The number of channels: mono (0) or stereo (1).
Definition: prefs.h:148
This class contains the engine's configuration read either from the config file or from the command l...
Definition: prefs.h:70
static void cleanup()
Cleanup Python.
Definition: python_class.cc:48
u_int8 screen_mode
Whether the engine shall run in window (0) or fullscreen (1) mode.
Definition: prefs.h:139
static void init()
Initialise Python and insert the Adonthell include paths.
Definition: python_class.cc:40