/*
 * $Header: /home/gene/library/website/docsrc/vwu/src/RCS/enum-icinfo.c,v 395.1 2008/04/20 17:25:48 gene Exp $
 *
 * Copyright (c) 2006 Gene Michael Stover.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 * USA
 */

#include "this.h"

/*
 */
enum { ACTION_RUN, ACTION_HELP };
static int S_action = ACTION_RUN;

/*
 * The output format.  It can be Lisp or DSV with a pipe character
 * (|) as the separator.
 * Default is Lisp.
 * Set it with the -c command line option.
 */
static char S_dsv = 0;

/*
 */
static int
S_Init ()
{
  int rc = 0;

  setbuf (stdout, NULL);
  return rc;
}

static int
S_CommandLine (int argc, char *argv[])
{
  int rc = 0, i;

  for (i = 1; rc == 0 && i < argc; ++i) {
    if (strncmp (argv[i], "-c", 2) == 0) {
      S_dsv = argv[i][2];
      printf ("\n%s:%d: Output format is DSV.  Separator character is %c.",
              __FILE__, __LINE__, S_dsv);
    } else if (strcmp (argv[i], "-h") == 0) {
      S_action = ACTION_HELP;
    } else {
      printf ("\n%s:%d:", __FILE__, __LINE__);
      printf (" Unknown command line option \"%s\".", argv[i]);
      rc = 23;
    }
  }
  return rc;
}

static char *
S_FccToString (DWORD fcc)
{
  static char str[40];

  if (isgraph ((fcc >> 24) & 0x0FF) &&
      isgraph ((fcc >> 16) & 0x0FF) &&
      isgraph ((fcc >> 8) & 0x0FF) &&
      isgraph (fcc & 0x0FF)) {
    sprintf (str, "#x%08lX \"%c%c%c%c\"", (unsigned long) fcc,
             fcc & 0x0FF,
             (fcc >> 8) & 0x0FF,
             (fcc >> 16) & 0x0FF,
             (fcc >> 24) & 0x0FF);
  } else {
    /*
     * If we treat this four-character code as four characters,
     * some of the characters would not be printable.  So we
     * don't treat it as characters.
     */
    sprintf (str, ". #x%08lX)", (unsigned long) fcc);
  }
  return str;
}

static void
S_PrintFlags (DWORD x)
{
  static struct { DWORD bit; char *name; } flags[] = {
    {VIDCF_COMPRESSFRAMES, "VIDCF_COMPRESSFRAMES" },
    {VIDCF_CRUNCH, "VIDCF_CRUNCH" },
    {VIDCF_DRAW, "VIDCF_DRAW" },
    {VIDCF_FASTTEMPORALC, "VIDCF_FASTTEMPORALC" },
    {VIDCF_FASTTEMPORALD, "VIDCF_FASTTEMPORALD" },
    {VIDCF_QUALITY, "VIDCF_QUALITY" },
    {VIDCF_TEMPORAL, "VIDCF_TEMPORAL" }
  };
  static int len = sizeof flags / sizeof flags[0];
  int i;

  if (x == 0) {
    printf (" 0");
  } else {
    for (i = 0; i < len; ++i) {
      if (flags[i].bit & x)
        printf (" %s", flags[i].name);
    }
  }
}

static void
S_PrintDsv (int n, ICINFO *x)
{
  static Boolean isFirstTime = TRUE;

  if (isFirstTime) {
    isFirstTime = FALSE;
    printf ("\n;; N");
    printf ("%cdwSize", S_dsv);
    printf ("%cfccType", S_dsv);
    printf ("%cfccHandler", S_dsv);
    printf ("%cdwFlags", S_dsv);
    printf ("%cdwVersion", S_dsv);
    printf ("%cdwVersionICM", S_dsv);
    printf ("%cszName", S_dsv);
    printf ("%cszDescription", S_dsv);
    printf ("%cszDriver", S_dsv);
  }
  printf ("\n%d", n);
  printf ("%c%lu", S_dsv, (unsigned long) x->dwSize);
  printf ("%c%s", S_dsv, S_FccToString (x->fccType));
  printf ("%c%s", S_dsv, S_FccToString (x->fccHandler));
  printf ("%c", S_dsv);
  S_PrintFlags ((unsigned long) x->dwFlags);
  printf ("%c%ld", S_dsv, (long) x->dwVersion);
  printf ("%c%ld", S_dsv, (long) x->dwVersionICM);
  printf ("%c%s", S_dsv, x->szName);
  printf ("%c%s", S_dsv, x->szDescription);
  printf ("%c%s", S_dsv, x->szDriver);
}

static void
S_PrintLisp (int n, ICINFO *x)
{
  printf ("\n(ICINFO (n %d)", n);
  printf ("\n        (dwSize . %lu)", (unsigned long) x->dwSize);
  printf ("\n        (fccType %s)", S_FccToString (x->fccType));
  printf ("\n        (fccHandler %s)", S_FccToString (x->fccHandler));
  printf ("\n        (dwFlags");
  S_PrintFlags ((unsigned long) x->dwFlags);
  printf (")");
  printf ("\n        (dwVersion . %ld)", (long) x->dwVersion);
  printf ("\n        (dwVersionICM . %ld)", (long) x->dwVersionICM);
  printf ("\n        (szName . \"%s\")", x->szName);
  printf ("\n        (szDescription . \"%s\")", x->szDescription);
  printf ("\n        (szDriver . \"%s\")", x->szDriver);
  printf (")");
  printf ("\n");
}

static void
S_Print (int n, ICINFO *x)
{
  if (S_dsv == 0) {
    S_PrintLisp (n, x);
  } else {
    S_PrintDsv (n, x);
  }
}

static int
S_Loop ()
{
  int rc = 0;
  DWORD type = 0, handler = 0;
  int n = 0;
  ICINFO x;

  while (rc == 0 && ICInfo (type, handler, &x)) {
    printf ("\n;; handler is %u", (unsigned) handler);
    S_Print (n, &x);
    ++handler;
    ++n;
  }
  return rc;
}

static int
S_Help ()
{
  printf ("\nCopyright (c) 2006 Gene Michael Stover.  All rights reserved.");
  printf ("\nCompiled %s %s", __DATE__, __TIME__);
  printf ("\n");
  printf ("\nPrints a list of all the CODECs on your Microsloth Winders");
  printf ("\ncomputer.  By default, prints it as Lisp expressions, but with");
  printf ("\nthe -cCHAR command line option, it will print it in Delimeter");
  printf ("\nSeparated Values (DSV) form.");
  printf ("\nIn the -cCHAR option, CHAR is the delimeter.  For example, to");
  printf ("\nprint in DSV form with a comma as the delimeter, you would run");
  printf ("\n\"enum-icinfo -c,\".");
  printf ("\n");
  printf ("\nAt this time, the program does not convert the four-character");
  printf ("\ncodes which identify the CODECs into more descriptive names.  I");
  printf ("\nhoped the Description field of each CODEC would do that.");
  printf ("\n");
  printf ("\nThe complete documentation is available on the world wide web");
  printf (" at");
  printf ("\n<http://cybertiggyr.com/gene/vwu/>.");
  return 0;
}

static int
S_Dispatch (int action)
{
  int rc = 0;

  switch (action) {
  case ACTION_RUN:
    rc = S_Loop ();
    break;
  case ACTION_HELP:
    rc = S_Help ();
    break;
  default:
    printf ("\n%s:%d: Unknown action %d. ", __FILE__, __LINE__, action);
    printf (" This should never happen.");
    rc = 3;
  }
  return rc;
}

int
main (int argc, char *argv[])
{
  int rc = 0;

  if (S_Init () == 0) {
    if (S_CommandLine (argc, argv) == 0) {
      if (S_Dispatch (S_action) == 0) {
        /* good */
      } else {
        printf ("\n%s:%d: S_Dispatch failed", __FILE__, __LINE__);
        rc = 110;
      }
    } else {
      printf ("\n%s:%d: S_CommandLine failed", __FILE__, __LINE__);
      rc = 1210;
    }
  } else {
    printf ("\n%s:%d: S_Init failed", __FILE__, __LINE__);
    rc = -1245;
  }
  return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

/* --- end of file --- */
