Tscope5
system.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // __ ______
4 // / /_______________ ____ ___ / ____/
5 // / __/ ___/ ___/ __ \/ __ \/ _ \ /___ )
6 // / /_(__ ) /__/ /_/ / /_/ / __/ ____/ /
7 // \__/____/\___/\____/ .___/\___/ /_____/
8 // /_/
9 //
10 /// \file system.c
11 /// Definitions of system functions.
12 /// \example system01.c
13 /// \example system02.c
14 ////////////////////////////////////////////////////////////////////////////////
15 
16 #include "../include/tscope5/system.h"
17 #include "../include/tscope5/display.h"
18 #include "../include/tscope5/system_internal.h"
19 
20 
21 ////////////////////////////////////////////////////////////////////////////////
22 /// @name Logging functions
23 /// Tscope5 automatically sends information about its status
24 /// to a logging window and a file called tscope5.log.
25 ///
26 /// With the functions below you control the amount of information
27 /// that is logged.
28 /// It is also possible to send your own log messages.
29 //@{
30 ////////////////////////////////////////////////////////////////////////////////
31 
32 
33 ////////////////////////////////////////////////////////////////////////////////
34 /// Send info to a logging window.
35 ///
36 /// \param level The importance of this message
37 /// (TS5_LOGLEVEL_0 - TS5_LOGLEVEL_6). Smaller values are more important.
38 /// \param format Printf-style format string that contains the log message.
39 ///
40 /// The log message is printed in a separate text log window.
41 ///
42 /// Messages with a level above the level specified
43 /// with ts5_set_log_level are omitted.
44 ////////////////////////////////////////////////////////////////////////////////
45 void ts5_log(const unsigned int level, const char *format, ...)
46 {
48  ts5_install_tscope5("ts5_log");
49  }
50 
51  if (level <= _ts5_status.loglevel) {
52 
54  _ts5_data.textlog = fopen("tscope5.log", "w+");
55  if (!_ts5_data.textlog) {
56  ts5_fatal("ts5_log: could not open log file\n");
57  }
59  }
60 
61  char outbuf[TS5_MAX_CHAR];
62  va_list args;
63  va_start(args, format);
64  vsnprintf(outbuf, TS5_MAX_CHAR*sizeof(char), format, args);
65  va_end(args);
66 
67  double logtime = al_get_time();
68  fprintf(stdout, "%8.3f: %s", logtime, outbuf);
69  //fflush(stdout);
70  fprintf(_ts5_data.textlog, "%8.3f: %s", logtime, outbuf);
71  }
72 }
73 
74 
75 ////////////////////////////////////////////////////////////////////////////////
76 /// Set log level
77 ///
78 /// \param loglevel How much stuff is logged.
79 ///
80 /// \return The previous log level.
81 ///
82 /// This parameter function controls what information
83 /// is printed to the log window.
84 ///
85 /// There are six possible settings:
86 /// - TS5_LOGLEVEL_0: no debugging info.
87 /// - TS5_LOGLEVEL_1: report when Tscope5 subsystems are loaded.
88 /// - TS5_LOGLEVEL_2: report when memory is allocated/freed.
89 /// - TS5_LOGLEVEL_3: report when response buttons are defined.
90 /// - TS5_LOGLEVEL_4: report when parameter are set or queried.
91 /// - TS5_LOGLEVEL_5: report each function call.
92 /// - TS5_LOGLEVEL_6: report internal check and coordinate functions.
93 ///
94 /// If other values are passed to this function the program is aborted.
95 ///
96 /// The default loglevel is TS5_LOGLEVEL_3.
97 ////////////////////////////////////////////////////////////////////////////////
98 int ts5_set_log_level(const unsigned int loglevel)
99 {
101  ts5_install_tscope5("ts5_set_log_level");
102  }
103 
104  ts5_log(TS5_LOGLEVEL_4, "ts5_set_log_level(%d)\n", loglevel);
105 
106  int retval;
107  retval = _ts5_status.loglevel;
108 
109  if (loglevel <= TS5_LOGLEVEL_6) {
110  _ts5_status.loglevel = loglevel;
111 
112  ts5_log(TS5_LOGLEVEL_4, "%s: %s %d to %d\n", "ts5_set_log_level",
113  "changed loglevel from", retval, loglevel);
114  }
115  else {
116  ts5_fatal("ts5_log: requested loglevel not supported.");
117  }
118 
119  return retval;
120 }
121 
122 
123 ////////////////////////////////////////////////////////////////////////////////
124 /// Get log level
125 ///
126 /// \return The log level.
127 ////////////////////////////////////////////////////////////////////////////////
129 {
131  ts5_install_tscope5("ts5_get_log_level");
132  }
133 
134  ts5_log(TS5_LOGLEVEL_4, "ts5_get_log_level\n");
135 
136  return _ts5_status.loglevel;
137 }
138 
139 
140 ////////////////////////////////////////////////////////////////////////////////
141 /// Write the status of all Tscope5 subsystem to the log window.
142 ///
143 /// Information is printed about:
144 /// - The display adapter(s) of the computer and the available fullscreen modes.
145 /// - The displays opened by Tscope5.
146 /// - The graphics parameters.
147 ////////////////////////////////////////////////////////////////////////////////
149 {
150  char line[]="==================================================\n";
151  int i;
152 
153  // display adapters + supported fullscreen modes
154 
155  ts5_log(TS5_LOGLEVEL_0, "\n");
156  ts5_log(TS5_LOGLEVEL_0, line);
157  ts5_log(TS5_LOGLEVEL_0, "tscope5 status:\n");
158  ts5_log(TS5_LOGLEVEL_0, "\n");
159 
160  ts5_log(TS5_LOGLEVEL_0, "Loglevel: %d\n", _ts5_status.loglevel);
161  ts5_log(TS5_LOGLEVEL_0, "Number of display adapters: %d\n",
162  _ts5_status.num_display_adapters);
163 
164  for (i = 0; i < _ts5_status.num_display_adapters; i++) {
165 
166  ts5_log(TS5_LOGLEVEL_0, "%s %d: w: %d (%d:%d), h: %d (%d:%d)\n",
167  "Display adapter", i+1,
168  _ts5_status.display_adapter[i].w,
169  _ts5_status.display_adapter[i].x1,
170  _ts5_status.display_adapter[i].x2,
171  _ts5_status.display_adapter[i].h,
172  _ts5_status.display_adapter[i].y1,
173  _ts5_status.display_adapter[i].y2);
174  }
175 
176  ts5_log(TS5_LOGLEVEL_0, "\n");
177 
178  int oldadapter = ts5_nextdisplay.adapter;
179  ALLEGRO_DISPLAY_MODE *mode;
180  mode = (ALLEGRO_DISPLAY_MODE *)al_malloc(sizeof(ALLEGRO_DISPLAY_MODE));
181 
182  for (i = 0; i < _ts5_status.num_display_adapters; i++) {
183 
184  al_set_new_display_adapter(i);
185  int oldrate = al_get_new_display_refresh_rate();
186  int oldflags = al_get_new_display_flags();
187  al_set_new_display_refresh_rate(0);
188  al_set_new_display_flags(0);
189 
190  int nmodes = al_get_num_display_modes();
191 
192  int j;
193  for (j=0; j<nmodes; j++) {
194 
195  mode = al_get_display_mode(j, mode);
196  ts5_log(TS5_LOGLEVEL_0,
197  "adapter %d mode %2d: w=%4d, h=%4d, format=%d, rate=%d\n",
198  i+1, j+1, mode->width, mode->height,
199  mode->format, mode->refresh_rate);
200  }
201 
202  al_set_new_display_refresh_rate(oldrate);
203  al_set_new_display_flags(oldflags);
204  }
205 
206  ts5_log(TS5_LOGLEVEL_0, "\n");
207  al_set_new_display_adapter(oldadapter);
208  al_free(mode);
209 
210  // display settings + settings for next display
211  ts5_log(TS5_LOGLEVEL_0, line);
212  ts5_log(TS5_LOGLEVEL_0, "Parameters for next display:\n");
213 
214  ts5_log(TS5_LOGLEVEL_0, "\tAdapter %d\n",
215  ts5_nextdisplay.adapter+1);
216 
217  ts5_log(TS5_LOGLEVEL_0, "\tw=%d, h=%d\n",
219 
220  ts5_log(TS5_LOGLEVEL_0, "\tx=%d, y=%d\n",
222 
223  ts5_log(TS5_LOGLEVEL_0, "\tRefreshrate=%d\n",
224  ts5_nextdisplay.refreshrate);
225 
226  ts5_log(TS5_LOGLEVEL_0, "\tDisplay mode=%d\n",
227  ts5_nextdisplay.display_mode);
228 
229  ts5_log(TS5_LOGLEVEL_0, "\tVsync mode=%d\n",
230  ts5_nextdisplay.vsync_mode);
231 
232  ts5_log(TS5_LOGLEVEL_0, "\tMultisampling=%d\n",
233  ts5_nextdisplay.multisampling);
234 
235  ts5_log(TS5_LOGLEVEL_0, "\n");
236 
237  ts5_log(TS5_LOGLEVEL_0, "Number of displays: %d\n",
238  _ts5_status.num_displays);
239 
240  ts5_log(TS5_LOGLEVEL_0, "Active display: %d\n",
241  _ts5_status.active_display);
242 
243  for (i = 0; i < _ts5_status.num_displays; i++) {
244 
245  ts5_log(TS5_LOGLEVEL_0,
246  "%s %d: %s %d, w=%d, h=%d, x=%d, y=%d, %s=%d, %s=%d, %s=%d %s=%d\n",
247  "Display", i+1,
248  "Adapter", _ts5_status.display[i].adapter+1,
249  _ts5_status.display[i].w, _ts5_status.display[i].h,
250  _ts5_status.display[i].x, _ts5_status.display[i].y,
251  "Refreshrate", _ts5_status.display[i].refreshrate,
252  "Dispay mode", _ts5_status.display[i].display_mode,
253  "Vsync mode", _ts5_status.display[i].vsync_mode,
254  "Multisampling", _ts5_status.display[i].multisampling);
255  }
256 
257  ts5_log(TS5_LOGLEVEL_0, "\n");
258 
259  // graphics parameters
260  float r, g, b, a;
261  ts5_log(TS5_LOGLEVEL_0, line);
262 
263  ts5_log(TS5_LOGLEVEL_0, "%s: %d\n",
264  "Coordinate system", _ts5_status.graphics.coordinate_system);
265 
266  ts5_log(TS5_LOGLEVEL_0, "%s: %d\n",
267  "Coordinate scale", _ts5_status.graphics.coordinate_scale);
268 
269  ts5_log(TS5_LOGLEVEL_0, "%s: %d x %d\n",
270  "Target bitmap size",
271  _ts5_status.graphics.target_width,
272  _ts5_status.graphics.target_height);
273 
274  al_unmap_rgba_f(_ts5_status.graphics.foreground_color, &r, &g, &b, &a);
275  ts5_log(TS5_LOGLEVEL_0, "%s: r: %f g: %f b: %f alpha: %f\n",
276  "Foreground color", r, g, b, a);
277 
278  al_unmap_rgba_f(_ts5_status.graphics.background_color, &r, &g, &b, &a);
279  ts5_log(TS5_LOGLEVEL_0, "%s: r: %f g: %f b: %f alpha: %f\n",
280  "Background color", r, g, b, a);
281 
282  ts5_log(TS5_LOGLEVEL_0, "%s: %f\n",
283  "Line drawing thickness", _ts5_status.graphics.drawing_thickness);
284 
285  ts5_log(TS5_LOGLEVEL_0, "%s: %d\n",
286  "Fill mode", _ts5_status.graphics.fill_mode);
287 
288  ts5_log(TS5_LOGLEVEL_0, "%s: %d\n",
289  "Font type", _ts5_status.graphics.font_type);
290 
291  ts5_log(TS5_LOGLEVEL_0, "%s: %d\n",
292  "Font style", _ts5_status.graphics.font_style);
293 
294  ts5_log(TS5_LOGLEVEL_0, "%s: %d\n",
295  "Font size", _ts5_status.graphics.font_size);
296 
297  ts5_log(TS5_LOGLEVEL_0, "%s: %d\n",
298  "Font number", _ts5_status.graphics.font_index);
299 
300  ts5_log(TS5_LOGLEVEL_0, "%s: %d\n",
301  "Text alignment", _ts5_status.graphics.text_alignment);
302 
303  ts5_log(TS5_LOGLEVEL_0, "\n");
304 
305 
306  // audio parameters
307  ts5_log(TS5_LOGLEVEL_0, line);
308 
309  ts5_log(TS5_LOGLEVEL_0, "%s: %d\n",
310  "Number of audio channels", _ts5_status.audio.channels);
311 
312  ts5_log(TS5_LOGLEVEL_0, "%s: %d\n",
313  "Sample rate", _ts5_status.audio.samplerate);
314 
315  ts5_log(TS5_LOGLEVEL_0, "%s: %d\n",
316  "Sample format", _ts5_status.audio.depth);
317 
318  ts5_log(TS5_LOGLEVEL_0, "%s: %f\n",
319  "Audio Gain", _ts5_status.audio.gain);
320 
321 
322  // timer
323  TS5_TIMER_STATUS *timer = &_ts5_status.timer;
324 
325  ts5_log(TS5_LOGLEVEL_0, line);
326 
327  ts5_log(TS5_LOGLEVEL_0, "Program priority: %+d\n",
328  timer->priority);
329 
330  ts5_log(TS5_LOGLEVEL_0, "Number of defined response buttons: %d\n",
331  timer->num_defined_buttons);
332 
333  ts5_log(TS5_LOGLEVEL_0, "Number of active response buttons: %d\n",
334  timer->num_active_buttons);
335 
336  ts5_log(TS5_LOGLEVEL_0, "Voicekey is response device: %d\n",
337  timer->voicekey_is_response_device);
338 
339  if (timer->voicekey_is_response_device) {
340 
341  for (i=0; i<timer->voicekey.num_buttons; i++) {
342 
343  if (timer->voicekey.button_press_active[i]!=0) {
344  ts5_log(TS5_LOGLEVEL_0, "%s %d %s %d\n",
345  "Voice key button press", i+1, "has response value",
346  timer->voicekey.button_press_defined[i]);
347  }
348 
349  if (timer->voicekey.button_release_active[i]!=0) {
350  ts5_log(TS5_LOGLEVEL_0, "%s %d %s %d\n",
351  "Voice key button release", i+1, "has response value",
352  timer->voicekey.button_release_defined[i]);
353  }
354  }
355  }
356 
357  ts5_log(TS5_LOGLEVEL_0, "Mouse is response device: %d\n",
358  timer->mouse_is_response_device);
359 
360  if (timer->mouse_is_response_device) {
361 
362  for (i=0; i<timer->mouse.num_buttons; i++) {
363 
364  if (timer->mouse.button_press_active[i]!=0) {
365  ts5_log(TS5_LOGLEVEL_0, "%s %d %s %d\n",
366  "Mouse button press", i+1, "has response value",
367  timer->mouse.button_press_defined[i]);
368  }
369 
370  if (timer->mouse.button_release_active[i]!=0) {
371  ts5_log(TS5_LOGLEVEL_0, "%s %d %s %d\n",
372  "Mouse button release", i+1, "has response value",
373  timer->mouse.button_release_defined[i]);
374  }
375  }
376  }
377 
378  ts5_log(TS5_LOGLEVEL_0, "Keyboard is response device: %d\n",
379  timer->keyboard_is_response_device);
380 
381  if (timer->keyboard_is_response_device) {
382 
383  for (i=0; i<timer->keyboard.num_buttons; i++) {
384 
385  if (timer->keyboard.button_press_active[i]!=0) {
386  ts5_log(TS5_LOGLEVEL_0, "%s %d %s %d\n",
387  "Keyboard button press", i+1, "has response value",
388  timer->keyboard.button_press_defined[i]);
389  }
390 
391  if (timer->keyboard.button_release_active[i]!=0) {
392  ts5_log(TS5_LOGLEVEL_0, "%s %d %s %d\n",
393  "Keyboard button release", i+1, "has response value",
394  timer->keyboard.button_release_defined[i]);
395  }
396  }
397  }
398 
399  ts5_log(TS5_LOGLEVEL_0, "Number of joysticks: %d\n",
400  timer->num_joysticks);
401 
402  ts5_log(TS5_LOGLEVEL_0, "Joystick is response device: %d\n",
403  timer->joystick_is_response_device);
404 
405  if (timer->joystick_is_response_device) {
406 
407  for (i=0; i<timer->num_joysticks; i++) {
408  int j;
409 
410  for (j=0; j<timer->joystick[i].num_buttons; j++) {
411 
412  if (timer->joystick[i].button_press_active[j]!=0) {
413  ts5_log(TS5_LOGLEVEL_0, "%s %d %s %d %s %d\n",
414  "Joystick", i+1, "button press", j+1,
415  "has response value",
416  timer->joystick[i].button_press_defined[j]);
417  }
418 
419  if (timer->joystick[i].button_release_active[j]!=0) {
420  ts5_log(TS5_LOGLEVEL_0, "%s %d %s %d %s %d\n",
421  "Joystick", i+1, "button release", j+1,
422  "has response value",
423  timer->joystick[i].button_release_defined[j]);
424  }
425  }
426  }
427  }
428 
429  ts5_log(TS5_LOGLEVEL_0, "Number of cedrusboxes: %d\n",
430  timer->num_cedrusboxes);
431 
432  ts5_log(TS5_LOGLEVEL_0, "Cedrusbox is response device: %d\n",
433  timer->cedrusbox_is_response_device);
434 
435  if (timer->cedrusbox_is_response_device) {
436 
437  for (i=0; i<timer->num_cedrusboxes; i++) {
438 
439  ts5_log(TS5_LOGLEVEL_0, "%s %d %s %d\n",
440  "Cedrusbox", i+1,
441  "is mapped to serial device",
442  timer->cedrusbox[i].port_num+1);
443 
444  ts5_log(TS5_LOGLEVEL_0, "Cedrusbox %d is type %d\n",
445  i+1, timer->cedrusbox[i].type);
446 
447  int j;
448  for (j=0; j<timer->cedrusbox[i].num_buttons; j++) {
449 
450  if (timer->cedrusbox[i].button_press_active[j]!=0) {
451  ts5_log(TS5_LOGLEVEL_0, "%s %d %s %d %s %d\n",
452  "Cedrusbox", i+1, "button press", j+1,
453  "has response value",
454  timer->cedrusbox[i].button_press_defined[j]);
455  }
456 
457  if (timer->cedrusbox[i].button_release_active[j]!=0) {
458  ts5_log(TS5_LOGLEVEL_0, "%s %d %s %d %s %d\n",
459  "Cedrusbox", i+1, "button release", j+1,
460  "has response value",
461  timer->cedrusbox[i].button_release_defined[j]);
462  }
463  }
464  }
465  }
466 
467  ts5_log(TS5_LOGLEVEL_0, "Number of parallel ports: %d\n",
468  timer->num_parports);
469 
470  ts5_log(TS5_LOGLEVEL_0, "Parallel port is response device: %d\n",
471  timer->parport_is_response_device);
472 
473  if (timer->parport_is_response_device) {
474 
475  for (i=0; i<timer->num_parports; i++) {
476 
477  int j;
478  for (j=0; j<timer->parport[i].num_buttons; j++) {
479 
480  if (timer->parport[i].button_press_active[j]!=0) {
481  ts5_log(TS5_LOGLEVEL_0, "%s %d %s %d %s %d\n",
482  "Parallel box", i+1, "button press", j+1,
483  "has response value",
484  timer->parport[i].button_press_defined[j]);
485  }
486 
487  if (timer->cedrusbox[i].button_release_active[j]!=0) {
488  ts5_log(TS5_LOGLEVEL_0, "%s %d %s %d %s %d\n",
489  "Parallel box", i+1, "button release", j+1,
490  "has response value",
491  timer->parport[i].button_release_defined[j]);
492  }
493  }
494  }
495  }
496 
497  ts5_log(TS5_LOGLEVEL_0, "\n");
498 
499 
500 
501  ts5_log(TS5_LOGLEVEL_0, "\n");
502  ts5_log(TS5_LOGLEVEL_0, line);
503 }
504 
505 
506 ////////////////////////////////////////////////////////////////////////////////
507 //@}
508 ////////////////////////////////////////////////////////////////////////////////
509 
510 
511 ////////////////////////////////////////////////////////////////////////////////
512 /// @name Error exit
513 /// During an experiment lots of unexpected things can happen.
514 /// (e.g. you forgot to copy stimulus bitmaps to the experiment computer).
515 ///
516 /// It is a good habit to check for such unexpected events and exit your
517 /// program safely before an ugly crash happens.
518 //@{
519 ////////////////////////////////////////////////////////////////////////////////
520 
521 
522 ////////////////////////////////////////////////////////////////////////////////
523 /// Exit safely with an error message.
524 ///
525 /// \param format Printf-style format string that contains the error message.
526 ///
527 /// Closes Tscope5, all subsystems and the log window.
528 ///
529 /// A message box appears with the error message supplied by the user.
530 ///
531 /// This function can be called before Tscope5 is installed.
532 ////////////////////////////////////////////////////////////////////////////////
533 void ts5_fatal(const char *format, ...)
534 {
535  ts5_log(TS5_LOGLEVEL_1, "ts5_fatal\n");
536 
537  char outbuf[TS5_MAX_CHAR];
538  va_list args;
539  va_start(args, format);
540  vsnprintf(outbuf, TS5_MAX_CHAR*sizeof(char), format, args);
541  va_end(args);
542 
543  fprintf(stdout, "Tscope5 error: %s", outbuf);
544 
545  #ifndef TS5_RASPBERRYPI
546  if (_ts5_status.num_displays>0) {
547 
548  if (_ts5_status.display[_ts5_status.active_display].display_mode
549  == TS5_FULLSCREEN_WINDOW) {
550 
551  al_toggle_display_flag(
552  _ts5_data.display[_ts5_status.active_display],
553  ALLEGRO_FULLSCREEN_WINDOW, 0);
554 
555  _ts5_status.display[_ts5_status.active_display].display_mode
556  = TS5_WINDOWED;
557  }
558 
559  al_show_native_message_box(
560  _ts5_data.display[_ts5_status.active_display],
561  "Tscope5 error", "Tscope5 error", outbuf, NULL,
562  ALLEGRO_MESSAGEBOX_ERROR);
563  }
564  else {
565  al_show_native_message_box(NULL, "Tscope5 error", "Tscope5 error",
566  outbuf, NULL, ALLEGRO_MESSAGEBOX_ERROR);
567  }
568 
569  #endif
570 
571  exit(1);
572 }
573 
574 
575 ////////////////////////////////////////////////////////////////////////////////
576 //@}
577 ////////////////////////////////////////////////////////////////////////////////
int _ts5_is_tscope5_installed
Is Tscope5 installed?
int ts5_get_log_level()
Get log level.
Definition: system.c:128
TS5_DISPLAY_STATUS ts5_nextdisplay
Settings for the next display that will be opened.
void ts5_log(const unsigned int level, const char *format,...)
Send info to a logging window.
Definition: system.c:45
int ts5_set_log_level(const unsigned int loglevel)
Set log level.
Definition: system.c:98
void ts5_install_tscope5(char *calling_function)
Install Tscope5.
void ts5_print_status()
Write the status of all Tscope5 subsystem to the log window.
Definition: system.c:148
int _ts5_is_textlog_installed
Is text log installed?
void ts5_fatal(const char *format,...)
Exit safely with an error message.
Definition: system.c:533