test/common.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 11 Jan 2009 04:05:28 +0000
changeset 3017 3272431eeee2
parent 2884 9dde605c7540
child 3184 68d3b48a6002
permissions -rw-r--r--
Added testresample.c
     1 
     2 /* A simple test program framework */
     3 
     4 #include <stdio.h>
     5 
     6 #include "common.h"
     7 
     8 #define VIDEO_USAGE \
     9 "[--video driver] [--renderer driver] [--info all|video|modes|render|event] [--display %d] [--fullscreen | --windows N] [--title title] [--center | --position X,Y] [--geometry WxH] [--depth N] [--refresh R] [--vsync] [--noframe] [--resize] [--minimize] [--maximize] [--grab]"
    10 
    11 #define AUDIO_USAGE \
    12 "[--rate N] [--format U8|S8|U16|U16LE|U16BE|S16|S16LE|S16BE] [--channels N] [--samples N]"
    13 
    14 CommonState *
    15 CommonCreateState(char **argv, Uint32 flags)
    16 {
    17     CommonState *state = SDL_calloc(1, sizeof(*state));
    18     if (!state) {
    19         SDL_OutOfMemory();
    20         return NULL;
    21     }
    22 
    23     /* Initialize some defaults */
    24     state->argv = argv;
    25     state->flags = flags;
    26     state->window_title = argv[0];
    27     state->window_flags = SDL_WINDOW_SHOWN;
    28     state->window_x = SDL_WINDOWPOS_UNDEFINED;
    29     state->window_y = SDL_WINDOWPOS_UNDEFINED;
    30     state->window_w = 640;
    31     state->window_h = 480;
    32     state->num_windows = 1;
    33     state->audiospec.freq = 22050;
    34     state->audiospec.format = AUDIO_S16;
    35     state->audiospec.channels = 2;
    36     state->audiospec.samples = 2048;
    37     return state;
    38 }
    39 
    40 int
    41 CommonArg(CommonState * state, int index)
    42 {
    43     char **argv = state->argv;
    44 
    45     if (SDL_strcasecmp(argv[index], "--video") == 0) {
    46         ++index;
    47         if (!argv[index]) {
    48             return -1;
    49         }
    50         state->videodriver = argv[index];
    51         return 2;
    52     }
    53     if (SDL_strcasecmp(argv[index], "--renderer") == 0) {
    54         ++index;
    55         if (!argv[index]) {
    56             return -1;
    57         }
    58         state->renderdriver = argv[index];
    59         return 2;
    60     }
    61     if (SDL_strcasecmp(argv[index], "--info") == 0) {
    62         ++index;
    63         if (!argv[index]) {
    64             return -1;
    65         }
    66         if (SDL_strcasecmp(argv[index], "all") == 0) {
    67             state->verbose |=
    68                 (VERBOSE_VIDEO | VERBOSE_MODES | VERBOSE_RENDER |
    69                  VERBOSE_EVENT);
    70             return 2;
    71         }
    72         if (SDL_strcasecmp(argv[index], "video") == 0) {
    73             state->verbose |= VERBOSE_VIDEO;
    74             return 2;
    75         }
    76         if (SDL_strcasecmp(argv[index], "modes") == 0) {
    77             state->verbose |= VERBOSE_MODES;
    78             return 2;
    79         }
    80         if (SDL_strcasecmp(argv[index], "render") == 0) {
    81             state->verbose |= VERBOSE_RENDER;
    82             return 2;
    83         }
    84         if (SDL_strcasecmp(argv[index], "event") == 0) {
    85             state->verbose |= VERBOSE_EVENT;
    86             return 2;
    87         }
    88         return -1;
    89     }
    90     if (SDL_strcasecmp(argv[index], "--display") == 0) {
    91         ++index;
    92         if (!argv[index]) {
    93             return -1;
    94         }
    95         state->display = SDL_atoi(argv[index]);
    96         return 2;
    97     }
    98     if (SDL_strcasecmp(argv[index], "--fullscreen") == 0) {
    99         state->window_flags |= SDL_WINDOW_FULLSCREEN;
   100         state->num_windows = 1;
   101         return 1;
   102     }
   103     if (SDL_strcasecmp(argv[index], "--windows") == 0) {
   104         ++index;
   105         if (!argv[index] || !SDL_isdigit(*argv[index])) {
   106             return -1;
   107         }
   108         if (!(state->window_flags & SDL_WINDOW_FULLSCREEN)) {
   109             state->num_windows = SDL_atoi(argv[index]);
   110         }
   111         return 2;
   112     }
   113     if (SDL_strcasecmp(argv[index], "--title") == 0) {
   114         ++index;
   115         if (!argv[index]) {
   116             return -1;
   117         }
   118         state->window_title = argv[index];
   119         return 2;
   120     }
   121     if (SDL_strcasecmp(argv[index], "--center") == 0) {
   122         state->window_x = SDL_WINDOWPOS_CENTERED;
   123         state->window_y = SDL_WINDOWPOS_CENTERED;
   124         return 1;
   125     }
   126     if (SDL_strcasecmp(argv[index], "--position") == 0) {
   127         char *x, *y;
   128         ++index;
   129         if (!argv[index]) {
   130             return -1;
   131         }
   132         x = argv[index];
   133         y = argv[index];
   134         while (*y && *y != ',') {
   135             ++y;
   136         }
   137         if (!*y) {
   138             return -1;
   139         }
   140         *y++ = '\0';
   141         state->window_x = SDL_atoi(x);
   142         state->window_y = SDL_atoi(y);
   143         return 2;
   144     }
   145     if (SDL_strcasecmp(argv[index], "--geometry") == 0) {
   146         char *w, *h;
   147         ++index;
   148         if (!argv[index]) {
   149             return -1;
   150         }
   151         w = argv[index];
   152         h = argv[index];
   153         while (*h && *h != 'x') {
   154             ++h;
   155         }
   156         if (!*h) {
   157             return -1;
   158         }
   159         *h++ = '\0';
   160         state->window_w = SDL_atoi(w);
   161         state->window_h = SDL_atoi(h);
   162         return 2;
   163     }
   164     if (SDL_strcasecmp(argv[index], "--depth") == 0) {
   165         ++index;
   166         if (!argv[index]) {
   167             return -1;
   168         }
   169         state->depth = SDL_atoi(argv[index]);
   170         return 2;
   171     }
   172     if (SDL_strcasecmp(argv[index], "--refresh") == 0) {
   173         ++index;
   174         if (!argv[index]) {
   175             return -1;
   176         }
   177         state->refresh_rate = SDL_atoi(argv[index]);
   178         return 2;
   179     }
   180     if (SDL_strcasecmp(argv[index], "--vsync") == 0) {
   181         state->render_flags |= SDL_RENDERER_PRESENTVSYNC;
   182         return 1;
   183     }
   184     if (SDL_strcasecmp(argv[index], "--noframe") == 0) {
   185         state->window_flags |= SDL_WINDOW_BORDERLESS;
   186         return 1;
   187     }
   188     if (SDL_strcasecmp(argv[index], "--resize") == 0) {
   189         state->window_flags |= SDL_WINDOW_RESIZABLE;
   190         return 1;
   191     }
   192     if (SDL_strcasecmp(argv[index], "--minimize") == 0) {
   193         state->window_flags |= SDL_WINDOW_MINIMIZED;
   194         return 1;
   195     }
   196     if (SDL_strcasecmp(argv[index], "--maximize") == 0) {
   197         state->window_flags |= SDL_WINDOW_MAXIMIZED;
   198         return 1;
   199     }
   200     if (SDL_strcasecmp(argv[index], "--grab") == 0) {
   201         state->window_flags |= SDL_WINDOW_INPUT_GRABBED;
   202         return 1;
   203     }
   204     if (SDL_strcasecmp(argv[index], "--rate") == 0) {
   205         ++index;
   206         if (!argv[index]) {
   207             return -1;
   208         }
   209         state->audiospec.freq = SDL_atoi(argv[index]);
   210         return 2;
   211     }
   212     if (SDL_strcasecmp(argv[index], "--format") == 0) {
   213         ++index;
   214         if (!argv[index]) {
   215             return -1;
   216         }
   217         if (SDL_strcasecmp(argv[index], "U8") == 0) {
   218             state->audiospec.format = AUDIO_U8;
   219             return 2;
   220         }
   221         if (SDL_strcasecmp(argv[index], "S8") == 0) {
   222             state->audiospec.format = AUDIO_S8;
   223             return 2;
   224         }
   225         if (SDL_strcasecmp(argv[index], "U16") == 0) {
   226             state->audiospec.format = AUDIO_U16;
   227             return 2;
   228         }
   229         if (SDL_strcasecmp(argv[index], "U16LE") == 0) {
   230             state->audiospec.format = AUDIO_U16LSB;
   231             return 2;
   232         }
   233         if (SDL_strcasecmp(argv[index], "U16BE") == 0) {
   234             state->audiospec.format = AUDIO_U16MSB;
   235             return 2;
   236         }
   237         if (SDL_strcasecmp(argv[index], "S16") == 0) {
   238             state->audiospec.format = AUDIO_S16;
   239             return 2;
   240         }
   241         if (SDL_strcasecmp(argv[index], "S16LE") == 0) {
   242             state->audiospec.format = AUDIO_S16LSB;
   243             return 2;
   244         }
   245         if (SDL_strcasecmp(argv[index], "S16BE") == 0) {
   246             state->audiospec.format = AUDIO_S16MSB;
   247             return 2;
   248         }
   249         return -1;
   250     }
   251     if (SDL_strcasecmp(argv[index], "--channels") == 0) {
   252         ++index;
   253         if (!argv[index]) {
   254             return -1;
   255         }
   256         state->audiospec.channels = (Uint8) SDL_atoi(argv[index]);
   257         return 2;
   258     }
   259     if (SDL_strcasecmp(argv[index], "--samples") == 0) {
   260         ++index;
   261         if (!argv[index]) {
   262             return -1;
   263         }
   264         state->audiospec.samples = (Uint16) SDL_atoi(argv[index]);
   265         return 2;
   266     }
   267     if ((SDL_strcasecmp(argv[index], "-h") == 0)
   268         || (SDL_strcasecmp(argv[index], "--help") == 0)) {
   269         /* Print the usage message */
   270         return -1;
   271     }
   272     return 0;
   273 }
   274 
   275 const char *
   276 CommonUsage(CommonState * state)
   277 {
   278     switch (state->flags & (SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
   279     case SDL_INIT_VIDEO:
   280         return VIDEO_USAGE;
   281     case SDL_INIT_AUDIO:
   282         return AUDIO_USAGE;
   283     case (SDL_INIT_VIDEO | SDL_INIT_AUDIO):
   284         return VIDEO_USAGE " " AUDIO_USAGE;
   285     default:
   286         return "";
   287     }
   288 }
   289 
   290 static void
   291 PrintRendererFlag(Uint32 flag)
   292 {
   293     switch (flag) {
   294     case SDL_RENDERER_SINGLEBUFFER:
   295         fprintf(stderr, "SingleBuffer");
   296         break;
   297     case SDL_RENDERER_PRESENTCOPY:
   298         fprintf(stderr, "PresentCopy");
   299         break;
   300     case SDL_RENDERER_PRESENTFLIP2:
   301         fprintf(stderr, "PresentFlip2");
   302         break;
   303     case SDL_RENDERER_PRESENTFLIP3:
   304         fprintf(stderr, "PresentFlip3");
   305         break;
   306     case SDL_RENDERER_PRESENTDISCARD:
   307         fprintf(stderr, "PresentDiscard");
   308         break;
   309     case SDL_RENDERER_PRESENTVSYNC:
   310         fprintf(stderr, "PresentVSync");
   311         break;
   312     case SDL_RENDERER_ACCELERATED:
   313         fprintf(stderr, "Accelerated");
   314         break;
   315     default:
   316         fprintf(stderr, "0x%8.8x", flag);
   317         break;
   318     }
   319 }
   320 
   321 static void
   322 PrintBlendMode(Uint32 flag)
   323 {
   324     switch (flag) {
   325     case SDL_BLENDMODE_NONE:
   326         fprintf(stderr, "None");
   327         break;
   328     case SDL_BLENDMODE_MASK:
   329         fprintf(stderr, "Mask");
   330         break;
   331     case SDL_BLENDMODE_BLEND:
   332         fprintf(stderr, "Blend");
   333         break;
   334     case SDL_BLENDMODE_ADD:
   335         fprintf(stderr, "Add");
   336         break;
   337     case SDL_BLENDMODE_MOD:
   338         fprintf(stderr, "Mod");
   339         break;
   340     default:
   341         fprintf(stderr, "0x%8.8x", flag);
   342         break;
   343     }
   344 }
   345 
   346 static void
   347 PrintScaleMode(Uint32 flag)
   348 {
   349     switch (flag) {
   350     case SDL_TEXTURESCALEMODE_NONE:
   351         fprintf(stderr, "None");
   352         break;
   353     case SDL_TEXTURESCALEMODE_FAST:
   354         fprintf(stderr, "Fast");
   355         break;
   356     case SDL_TEXTURESCALEMODE_SLOW:
   357         fprintf(stderr, "Slow");
   358         break;
   359     case SDL_TEXTURESCALEMODE_BEST:
   360         fprintf(stderr, "Best");
   361         break;
   362     default:
   363         fprintf(stderr, "0x%8.8x", flag);
   364         break;
   365     }
   366 }
   367 
   368 static void
   369 PrintPixelFormat(Uint32 format)
   370 {
   371     switch (format) {
   372     case SDL_PIXELFORMAT_UNKNOWN:
   373         fprintf(stderr, "Unknwon");
   374         break;
   375     case SDL_PIXELFORMAT_INDEX1LSB:
   376         fprintf(stderr, "Index1LSB");
   377         break;
   378     case SDL_PIXELFORMAT_INDEX1MSB:
   379         fprintf(stderr, "Index1MSB");
   380         break;
   381     case SDL_PIXELFORMAT_INDEX4LSB:
   382         fprintf(stderr, "Index4LSB");
   383         break;
   384     case SDL_PIXELFORMAT_INDEX4MSB:
   385         fprintf(stderr, "Index4MSB");
   386         break;
   387     case SDL_PIXELFORMAT_INDEX8:
   388         fprintf(stderr, "Index8");
   389         break;
   390     case SDL_PIXELFORMAT_RGB332:
   391         fprintf(stderr, "RGB332");
   392         break;
   393     case SDL_PIXELFORMAT_RGB444:
   394         fprintf(stderr, "RGB444");
   395         break;
   396     case SDL_PIXELFORMAT_RGB555:
   397         fprintf(stderr, "RGB555");
   398         break;
   399     case SDL_PIXELFORMAT_ARGB4444:
   400         fprintf(stderr, "ARGB4444");
   401         break;
   402     case SDL_PIXELFORMAT_ARGB1555:
   403         fprintf(stderr, "ARGB1555");
   404         break;
   405     case SDL_PIXELFORMAT_RGB565:
   406         fprintf(stderr, "RGB565");
   407         break;
   408     case SDL_PIXELFORMAT_RGB24:
   409         fprintf(stderr, "RGB24");
   410         break;
   411     case SDL_PIXELFORMAT_BGR24:
   412         fprintf(stderr, "BGR24");
   413         break;
   414     case SDL_PIXELFORMAT_RGB888:
   415         fprintf(stderr, "RGB888");
   416         break;
   417     case SDL_PIXELFORMAT_BGR888:
   418         fprintf(stderr, "BGR888");
   419         break;
   420     case SDL_PIXELFORMAT_ARGB8888:
   421         fprintf(stderr, "ARGB8888");
   422         break;
   423     case SDL_PIXELFORMAT_RGBA8888:
   424         fprintf(stderr, "RGBA8888");
   425         break;
   426     case SDL_PIXELFORMAT_ABGR8888:
   427         fprintf(stderr, "ABGR8888");
   428         break;
   429     case SDL_PIXELFORMAT_BGRA8888:
   430         fprintf(stderr, "BGRA8888");
   431         break;
   432     case SDL_PIXELFORMAT_ARGB2101010:
   433         fprintf(stderr, "ARGB2101010");
   434         break;
   435     case SDL_PIXELFORMAT_YV12:
   436         fprintf(stderr, "YV12");
   437         break;
   438     case SDL_PIXELFORMAT_IYUV:
   439         fprintf(stderr, "IYUV");
   440         break;
   441     case SDL_PIXELFORMAT_YUY2:
   442         fprintf(stderr, "YUY2");
   443         break;
   444     case SDL_PIXELFORMAT_UYVY:
   445         fprintf(stderr, "UYVY");
   446         break;
   447     case SDL_PIXELFORMAT_YVYU:
   448         fprintf(stderr, "YVYU");
   449         break;
   450     default:
   451         fprintf(stderr, "0x%8.8x", format);
   452         break;
   453     }
   454 }
   455 
   456 static void
   457 PrintRenderer(SDL_RendererInfo * info)
   458 {
   459     int i, count;
   460 
   461     fprintf(stderr, "  Renderer %s:\n", info->name);
   462 
   463     fprintf(stderr, "    Flags: 0x%8.8X", info->flags);
   464     fprintf(stderr, " (");
   465     count = 0;
   466     for (i = 0; i < sizeof(info->flags) * 8; ++i) {
   467         Uint32 flag = (1 << i);
   468         if (info->flags & flag) {
   469             if (count > 0) {
   470                 fprintf(stderr, " | ");
   471             }
   472             PrintRendererFlag(flag);
   473             ++count;
   474         }
   475     }
   476     fprintf(stderr, ")\n");
   477 
   478     fprintf(stderr, "    Blend: 0x%8.8X", info->blend_modes);
   479     fprintf(stderr, " (");
   480     count = 0;
   481     for (i = 0; i < sizeof(info->blend_modes) * 8; ++i) {
   482         Uint32 flag = (1 << i);
   483         if (info->blend_modes & flag) {
   484             if (count > 0) {
   485                 fprintf(stderr, " | ");
   486             }
   487             PrintBlendMode(flag);
   488             ++count;
   489         }
   490     }
   491     fprintf(stderr, ")\n");
   492 
   493     fprintf(stderr, "    Scale: 0x%8.8X", info->scale_modes);
   494     fprintf(stderr, " (");
   495     count = 0;
   496     for (i = 0; i < sizeof(info->scale_modes) * 8; ++i) {
   497         Uint32 flag = (1 << i);
   498         if (info->scale_modes & flag) {
   499             if (count > 0) {
   500                 fprintf(stderr, " | ");
   501             }
   502             PrintScaleMode(flag);
   503             ++count;
   504         }
   505     }
   506     fprintf(stderr, ")\n");
   507 
   508     fprintf(stderr, "    Texture formats (%d): ", info->num_texture_formats);
   509     for (i = 0; i < (int) info->num_texture_formats; ++i) {
   510         if (i > 0) {
   511             fprintf(stderr, ", ");
   512         }
   513         PrintPixelFormat(info->texture_formats[i]);
   514     }
   515     fprintf(stderr, "\n");
   516 
   517     if (info->max_texture_width || info->max_texture_height) {
   518         fprintf(stderr, "    Max Texture Size: %dx%d\n",
   519                 info->max_texture_width, info->max_texture_height);
   520     }
   521 }
   522 
   523 SDL_bool
   524 CommonInit(CommonState * state)
   525 {
   526     int i, j, m, n;
   527     SDL_DisplayMode fullscreen_mode;
   528 
   529     if (state->flags & SDL_INIT_VIDEO) {
   530         if (state->verbose & VERBOSE_VIDEO) {
   531             n = SDL_GetNumVideoDrivers();
   532             if (n == 0) {
   533                 fprintf(stderr, "No built-in video drivers\n");
   534             } else {
   535                 fprintf(stderr, "Built-in video drivers:");
   536                 for (i = 0; i < n; ++i) {
   537                     if (i > 0) {
   538                         fprintf(stderr, ",");
   539                     }
   540                     fprintf(stderr, " %s", SDL_GetVideoDriver(i));
   541                 }
   542                 fprintf(stderr, "\n");
   543             }
   544         }
   545         if (SDL_VideoInit(state->videodriver, 0) < 0) {
   546             fprintf(stderr, "Couldn't initialize video driver: %s\n",
   547                     SDL_GetError());
   548             return SDL_FALSE;
   549         }
   550         if (state->verbose & VERBOSE_VIDEO) {
   551             fprintf(stderr, "Video driver: %s\n",
   552                     SDL_GetCurrentVideoDriver());
   553         }
   554 
   555         if (state->verbose & VERBOSE_MODES) {
   556             SDL_DisplayMode mode;
   557             int bpp;
   558             Uint32 Rmask, Gmask, Bmask, Amask;
   559 
   560             n = SDL_GetNumVideoDisplays();
   561             fprintf(stderr, "Number of displays: %d\n", n);
   562             for (i = 0; i < n; ++i) {
   563                 fprintf(stderr, "Display %d:\n", i);
   564                 SDL_SelectVideoDisplay(i);
   565 
   566                 SDL_GetDesktopDisplayMode(&mode);
   567                 SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask, &Gmask,
   568                                            &Bmask, &Amask);
   569                 fprintf(stderr,
   570                         "  Current mode: %dx%d@%dHz, %d bits-per-pixel\n",
   571                         mode.w, mode.h, mode.refresh_rate, bpp);
   572                 if (Rmask || Gmask || Bmask) {
   573                     fprintf(stderr, "      Red Mask = 0x%.8x\n", Rmask);
   574                     fprintf(stderr, "      Green Mask = 0x%.8x\n", Gmask);
   575                     fprintf(stderr, "      Blue Mask = 0x%.8x\n", Bmask);
   576                     if (Amask)
   577                         fprintf(stderr, "      Alpha Mask = 0x%.8x\n", Amask);
   578                 }
   579 
   580                 /* Print available fullscreen video modes */
   581                 m = SDL_GetNumDisplayModes();
   582                 if (m == 0) {
   583                     fprintf(stderr, "No available fullscreen video modes\n");
   584                 } else {
   585                     fprintf(stderr, "  Fullscreen video modes:\n");
   586                     for (j = 0; j < m; ++j) {
   587                         SDL_GetDisplayMode(j, &mode);
   588                         SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask,
   589                                                    &Gmask, &Bmask, &Amask);
   590                         fprintf(stderr,
   591                                 "    Mode %d: %dx%d@%dHz, %d bits-per-pixel\n",
   592                                 j, mode.w, mode.h, mode.refresh_rate, bpp);
   593                         if (Rmask || Gmask || Bmask) {
   594                             fprintf(stderr, "        Red Mask = 0x%.8x\n",
   595                                     Rmask);
   596                             fprintf(stderr, "        Green Mask = 0x%.8x\n",
   597                                     Gmask);
   598                             fprintf(stderr, "        Blue Mask = 0x%.8x\n",
   599                                     Bmask);
   600                             if (Amask)
   601                                 fprintf(stderr,
   602                                         "        Alpha Mask = 0x%.8x\n",
   603                                         Amask);
   604                         }
   605                     }
   606                 }
   607             }
   608         }
   609 
   610         SDL_SelectVideoDisplay(state->display);
   611         if (state->verbose & VERBOSE_RENDER) {
   612             SDL_RendererInfo info;
   613 
   614             n = SDL_GetNumRenderDrivers();
   615             if (n == 0) {
   616                 fprintf(stderr, "No built-in render drivers\n");
   617             } else {
   618                 fprintf(stderr, "Built-in render drivers:\n");
   619                 for (i = 0; i < n; ++i) {
   620                     SDL_GetRenderDriverInfo(i, &info);
   621                     PrintRenderer(&info);
   622                 }
   623             }
   624         }
   625 
   626         switch (state->depth) {
   627         case 8:
   628             fullscreen_mode.format = SDL_PIXELFORMAT_INDEX8;
   629             break;
   630         case 15:
   631             fullscreen_mode.format = SDL_PIXELFORMAT_RGB555;
   632             break;
   633         case 16:
   634             fullscreen_mode.format = SDL_PIXELFORMAT_RGB565;
   635             break;
   636         default:
   637             fullscreen_mode.format = SDL_PIXELFORMAT_RGB888;
   638             break;
   639         }
   640         fullscreen_mode.w = state->window_w;
   641         fullscreen_mode.h = state->window_h;
   642         fullscreen_mode.refresh_rate = state->refresh_rate;
   643         SDL_SetFullscreenDisplayMode(&fullscreen_mode);
   644 
   645         state->windows =
   646             (SDL_WindowID *) SDL_malloc(state->num_windows *
   647                                         sizeof(*state->windows));
   648         if (!state->windows) {
   649             fprintf(stderr, "Out of memory!\n");
   650             return SDL_FALSE;
   651         }
   652         for (i = 0; i < state->num_windows; ++i) {
   653             char title[1024];
   654 
   655             if (state->num_windows > 1) {
   656                 SDL_snprintf(title, SDL_arraysize(title), "%s %d",
   657                              state->window_title, i + 1);
   658             } else {
   659                 SDL_strlcpy(title, state->window_title, SDL_arraysize(title));
   660             }
   661             state->windows[i] =
   662                 SDL_CreateWindow(title, state->window_x, state->window_y,
   663                                  state->window_w, state->window_h,
   664                                  state->window_flags);
   665             if (!state->windows[i]) {
   666                 fprintf(stderr, "Couldn't create window: %s\n",
   667                         SDL_GetError());
   668                 return SDL_FALSE;
   669             }
   670 
   671             if (!state->skip_renderer
   672                 && (state->renderdriver
   673                     || !(state->window_flags & SDL_WINDOW_OPENGL))) {
   674                 m = -1;
   675                 if (state->renderdriver) {
   676                     SDL_RendererInfo info;
   677                     n = SDL_GetNumRenderDrivers();
   678                     for (j = 0; j < n; ++j) {
   679                         SDL_GetRenderDriverInfo(j, &info);
   680                         if (SDL_strcasecmp(info.name, state->renderdriver) ==
   681                             0) {
   682                             m = j;
   683                             break;
   684                         }
   685                     }
   686                     if (m == n) {
   687                         fprintf(stderr,
   688                                 "Couldn't find render driver named %s",
   689                                 state->renderdriver);
   690                         return SDL_FALSE;
   691                     }
   692                 }
   693                 if (SDL_CreateRenderer
   694                     (state->windows[i], m, state->render_flags) < 0) {
   695                     fprintf(stderr, "Couldn't create renderer: %s\n",
   696                             SDL_GetError());
   697                     return SDL_FALSE;
   698                 }
   699                 if (state->verbose & VERBOSE_RENDER) {
   700                     SDL_RendererInfo info;
   701 
   702                     fprintf(stderr, "Current renderer:\n");
   703                     SDL_GetRendererInfo(&info);
   704                     PrintRenderer(&info);
   705                 }
   706             }
   707         }
   708         SDL_SelectRenderer(state->windows[0]);
   709     }
   710 
   711     if (state->flags & SDL_INIT_AUDIO) {
   712         if (state->verbose & VERBOSE_AUDIO) {
   713             n = SDL_GetNumAudioDrivers();
   714             if (n == 0) {
   715                 fprintf(stderr, "No built-in audio drivers\n");
   716             } else {
   717                 fprintf(stderr, "Built-in audio drivers:");
   718                 for (i = 0; i < n; ++i) {
   719                     if (i > 0) {
   720                         fprintf(stderr, ",");
   721                     }
   722                     fprintf(stderr, " %s", SDL_GetAudioDriver(i));
   723                 }
   724                 fprintf(stderr, "\n");
   725             }
   726         }
   727         if (SDL_AudioInit(state->audiodriver) < 0) {
   728             fprintf(stderr, "Couldn't initialize audio driver: %s\n",
   729                     SDL_GetError());
   730             return SDL_FALSE;
   731         }
   732         if (state->verbose & VERBOSE_VIDEO) {
   733             fprintf(stderr, "Audio driver: %s\n",
   734                     SDL_GetCurrentAudioDriver());
   735         }
   736 
   737         if (SDL_OpenAudio(&state->audiospec, NULL) < 0) {
   738             fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
   739             return SDL_FALSE;
   740         }
   741     }
   742 
   743     return SDL_TRUE;
   744 }
   745 
   746 static void
   747 PrintEvent(SDL_Event * event)
   748 {
   749     fprintf(stderr, "SDL EVENT: ");
   750     switch (event->type) {
   751     case SDL_WINDOWEVENT:
   752         switch (event->window.event) {
   753         case SDL_WINDOWEVENT_SHOWN:
   754             fprintf(stderr, "Window %d shown", event->window.windowID);
   755             break;
   756         case SDL_WINDOWEVENT_HIDDEN:
   757             fprintf(stderr, "Window %d hidden", event->window.windowID);
   758             break;
   759         case SDL_WINDOWEVENT_EXPOSED:
   760             fprintf(stderr, "Window %d exposed", event->window.windowID);
   761             break;
   762         case SDL_WINDOWEVENT_MOVED:
   763             fprintf(stderr, "Window %d moved to %d,%d",
   764                     event->window.windowID, event->window.data1,
   765                     event->window.data2);
   766             break;
   767         case SDL_WINDOWEVENT_RESIZED:
   768             fprintf(stderr, "Window %d resized to %dx%d",
   769                     event->window.windowID, event->window.data1,
   770                     event->window.data2);
   771             break;
   772         case SDL_WINDOWEVENT_MINIMIZED:
   773             fprintf(stderr, "Window %d minimized", event->window.windowID);
   774             break;
   775         case SDL_WINDOWEVENT_MAXIMIZED:
   776             fprintf(stderr, "Window %d maximized", event->window.windowID);
   777             break;
   778         case SDL_WINDOWEVENT_RESTORED:
   779             fprintf(stderr, "Window %d restored", event->window.windowID);
   780             break;
   781         case SDL_WINDOWEVENT_ENTER:
   782             fprintf(stderr, "Mouse entered window %d",
   783                     event->window.windowID);
   784             break;
   785         case SDL_WINDOWEVENT_LEAVE:
   786             fprintf(stderr, "Mouse left window %d", event->window.windowID);
   787             break;
   788         case SDL_WINDOWEVENT_FOCUS_GAINED:
   789             fprintf(stderr, "Window %d gained keyboard focus",
   790                     event->window.windowID);
   791             break;
   792         case SDL_WINDOWEVENT_FOCUS_LOST:
   793             fprintf(stderr, "Window %d lost keyboard focus",
   794                     event->window.windowID);
   795             break;
   796         case SDL_WINDOWEVENT_CLOSE:
   797             fprintf(stderr, "Window %d closed", event->window.windowID);
   798             break;
   799         default:
   800             fprintf(stderr, "Window %d got unknown event %d",
   801                     event->window.windowID, event->window.event);
   802             break;
   803         }
   804         break;
   805     case SDL_KEYDOWN:
   806         fprintf(stderr,
   807                 "Keyboard %d: key pressed  in window %d: scancode 0x%08X = %s, keycode 0x%08X = %s",
   808                 event->key.which, event->key.windowID,
   809                 event->key.keysym.scancode,
   810                 SDL_GetScancodeName(event->key.keysym.scancode),
   811                 event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
   812         break;
   813     case SDL_KEYUP:
   814         fprintf(stderr,
   815                 "Keyboard %d: key released in window %d: scancode 0x%08X = %s, keycode 0x%08X = %s",
   816                 event->key.which, event->key.windowID,
   817                 event->key.keysym.scancode,
   818                 SDL_GetScancodeName(event->key.keysym.scancode),
   819                 event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym));
   820         break;
   821     case SDL_TEXTINPUT:
   822         fprintf(stderr, "Keyboard %d: text input \"%s\" in window %d",
   823                 event->text.which, event->text.text, event->text.windowID);
   824         break;
   825     case SDL_MOUSEMOTION:
   826         fprintf(stderr, "Mouse %d: moved to %d,%d (%d,%d) in window %d",
   827                 event->motion.which, event->motion.x, event->motion.y,
   828                 event->motion.xrel, event->motion.yrel,
   829                 event->motion.windowID);
   830         break;
   831     case SDL_MOUSEBUTTONDOWN:
   832         fprintf(stderr, "Mouse %d: button %d pressed at %d,%d in window %d",
   833                 event->button.which, event->button.button, event->button.x,
   834                 event->button.y, event->button.windowID);
   835         break;
   836     case SDL_MOUSEBUTTONUP:
   837         fprintf(stderr, "Mouse %d: button %d released at %d,%d in window %d",
   838                 event->button.which, event->button.button, event->button.x,
   839                 event->button.y, event->button.windowID);
   840         break;
   841     case SDL_MOUSEWHEEL:
   842         fprintf(stderr,
   843                 "Mouse %d: wheel scrolled %d in x and %d in y in window %d",
   844                 event->wheel.which, event->wheel.x, event->wheel.y,
   845                 event->wheel.windowID);
   846         break;
   847     case SDL_JOYBALLMOTION:
   848         fprintf(stderr, "Joystick %d: ball %d moved by %d,%d",
   849                 event->jball.which, event->jball.ball, event->jball.xrel,
   850                 event->jball.yrel);
   851         break;
   852     case SDL_JOYHATMOTION:
   853         fprintf(stderr, "Joystick %d: hat %d moved to ", event->jhat.which,
   854                 event->jhat.hat);
   855         switch (event->jhat.value) {
   856         case SDL_HAT_CENTERED:
   857             fprintf(stderr, "CENTER");
   858             break;
   859         case SDL_HAT_UP:
   860             fprintf(stderr, "UP");
   861             break;
   862         case SDL_HAT_RIGHTUP:
   863             fprintf(stderr, "RIGHTUP");
   864             break;
   865         case SDL_HAT_RIGHT:
   866             fprintf(stderr, "RIGHT");
   867             break;
   868         case SDL_HAT_RIGHTDOWN:
   869             fprintf(stderr, "RIGHTDOWN");
   870             break;
   871         case SDL_HAT_DOWN:
   872             fprintf(stderr, "DOWN");
   873             break;
   874         case SDL_HAT_LEFTDOWN:
   875             fprintf(stderr, "LEFTDOWN");
   876             break;
   877         case SDL_HAT_LEFT:
   878             fprintf(stderr, "LEFT");
   879             break;
   880         case SDL_HAT_LEFTUP:
   881             fprintf(stderr, "LEFTUP");
   882             break;
   883         default:
   884             fprintf(stderr, "UNKNOWN");
   885             break;
   886         }
   887         break;
   888     case SDL_JOYBUTTONDOWN:
   889         fprintf(stderr, "Joystick %d: button %d pressed",
   890                 event->jbutton.which, event->jbutton.button);
   891         break;
   892     case SDL_JOYBUTTONUP:
   893         fprintf(stderr, "Joystick %d: button %d released",
   894                 event->jbutton.which, event->jbutton.button);
   895         break;
   896     case SDL_QUIT:
   897         fprintf(stderr, "Quit requested");
   898         break;
   899     case SDL_USEREVENT:
   900         fprintf(stderr, "User event %d", event->user.code);
   901         break;
   902     default:
   903         fprintf(stderr, "Unknown event %d", event->type);
   904         break;
   905     }
   906     fprintf(stderr, "\n");
   907 }
   908 
   909 void
   910 CommonEvent(CommonState * state, SDL_Event * event, int *done)
   911 {
   912     if (state->verbose & VERBOSE_EVENT) {
   913         PrintEvent(event);
   914     }
   915 
   916     switch (event->type) {
   917     case SDL_WINDOWEVENT:
   918         switch (event->window.event) {
   919         case SDL_WINDOWEVENT_CLOSE:
   920             *done = 1;
   921             break;
   922         }
   923         break;
   924     case SDL_KEYDOWN:
   925         switch (event->key.keysym.sym) {
   926             /* Add hotkeys here */
   927         case SDLK_g:
   928             if (event->key.keysym.mod & KMOD_CTRL) {
   929                 /* Ctrl-G toggle grab */
   930             }
   931             break;
   932         case SDLK_ESCAPE:
   933             *done = 1;
   934             break;
   935         default:
   936             break;
   937         }
   938         break;
   939     case SDL_QUIT:
   940         *done = 1;
   941         break;
   942     }
   943 }
   944 
   945 void
   946 CommonQuit(CommonState * state)
   947 {
   948     if (state->flags & SDL_INIT_VIDEO) {
   949         SDL_VideoQuit();
   950     }
   951     if (state->flags & SDL_INIT_AUDIO) {
   952         SDL_AudioQuit();
   953     }
   954     if (state->windows) {
   955         SDL_free(state->windows);
   956     }
   957     SDL_free(state);
   958 }