/*
  uxcook 2.0.0 by Ben D Canning (bdc@bethany.edu)
  --
  Yeah, I know we jumped from v1.0 to 2.0.0, but I felt it was necessary
  since this has been completely recoded and there's a new maintainer (me).
  I added buffering in this version, so it goes quite a bit faster than the
  original, non-buffered, version and every other similar program out there.
  That's right, uxcook 2.0.0 is 3 times as fast as DeTox 1.2 and about 4
  times faster than Uncook95.  Not bad, huh?
  --
  This is just a quickie release I hammered out to tide everyone over until I
  can make a really sweet version of this puppy.  I'll probably rewrite it to
  use C++ and I'm planning on adding batch modes and stuff.  Send me an email
  if you can think of any features to add to it.
  --
  (C)1998 under the GNU GPL
  All code by Ben D Canning unless otherwise noted
  Ideas from Mike Epstein (author of Uxcoook v1.0)
  Algorithm provided by both Andrew Bent and Mike Epstein
  --
  Check out http://ns.bethany.edu/bdc/warez/uxcook.html for updates
  Also hosted on http://www.free-music.com/ along with the Uncook FAQ
*/


#include <stdio.h>

#define DIE(s,i) {fprintf(stderr, "%s\n", s); exit(i);}

size_t Uncook_File (FILE *in, FILE *out);
long   File_Length (FILE *f);
char   If_File_Exists (const char *filename);



int
main (int argc, char **argv)
{
  long counter = 0;


  printf ("Uxcook 2.0.1 (Dec 5 1998) by Ben D Canning (bdc@bethany.edu)\n");
  printf ("-- Fixs cooked MP3s just like Uncook95 and DeTox.\n");

  if (argc < 3)
  {
      printf (
          "There weren't enough commandline parameters given.\n"
          "usage: %s infile outfile\n", argv[0]);

      return 0;
  }

  if (!If_File_Exists (argv[1]))
      DIE ("Whoops! Can't find the input file.  Check the commandline.", 0);

  if (If_File_Exists (argv[2]))
      DIE("At this time, Uxcook does not allow overwriting.\nTry a different outfile.\nNext release will have a commandline toggle for this.", 0);

  counter = Uncook_File (fopen (argv[1], "rb"), fopen (argv[2], "wb"));

  printf ("We found and fixed %ld drunk spots.\n", counter);

  if ( (File_Length (fopen (argv[1], "rb")) / 1000) > counter)
      printf (
      "\n"
      "HEY!  It looks like this file wasn't cooked in the first place.  You\n"
      "should probably keep the original just in case.  Of course, don't\n"
      "take this warning as gospel.  It could be as cooked as Bob Marley.\n"
      );


  return 0;
}


/*
  Uncook_File()
  --
  This will "uncook" a file by taking out stuff that was caused by incorrect
  MIME settings.  Be warned that it probably won't fix files with exact
  formats, but it will fix MP3s and the like.

  It uses buffering, so it's pretty darned fast.

  Returns the number of fixed spots or -1 if there's an error.
*/

size_t
Uncook_File (FILE *in, FILE *out)
{
  char   inbuf[BUFSIZ], outbuf[BUFSIZ];
  long   counter = 0;
  size_t buflen, loop1, loop2;


  /* Start at the beginning of each file */
  fseek (in,  0L, SEEK_SET);
  fseek (out, 0L, SEEK_SET);


  while ( (buflen = fread (inbuf, 1, sizeof inbuf, in)) )
  {
      if (-1 == buflen)    /* error reading file */
          return -1;

      for (loop1 = loop2 = 0; loop1 < buflen; loop1++)
      {
          if (inbuf[loop1] == '\r' && inbuf[loop1+1] == '\n')
              ++counter;

          else
              outbuf[loop2++] = inbuf[loop1];
      }

      fwrite (outbuf, 1, loop2, out);
  }

  return counter;
}





long
File_Length (FILE *f)
{
  long marker, length;

  marker = ftell (f);
  fseek (f, 0L, SEEK_END);
  length = ftell (f);
  fseek (f, marker, SEEK_SET);

  return length;
}



char
If_File_Exists (const char *filename)
{
  if (!fopen (filename, "r"))
      return 0;
  else
      return 1;
}
