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