/*
**
** $VER: main.c 0.3 (05.11.02)
** Description
**	Main program
**
** (C) Copyright 1999 Paul Hill
** (C) Copyright 2002 Alexandre Balaban
**
** $HISTORY :
**		- 0.3, 05.11.02 : Added pack pragma directives for PPC compilation
**		- 0.2, 03.10.02 : o Include PPC compilation improvements by Steffen Haeuser
**                        o Added LOOP settings
**      - 0.1, 08.03.99 : Original version by Paul Hill
**
*/



#include <stdio.h>

#pragma pack(2)

#ifndef __PPC__
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/icon.h>
#include <proto/intuition.h>
#include <proto/asl.h>
#include <proto/graphics.h>
#else
#include </ADE/os-includeppc/proto/dos.h>
#include </ADE/os-includeppc/proto/exec.h>
//#include </ADE/os-includeppc/proto/icon.h>
#include </ADE/os-includeppc/proto/intuition.h>
#include </ADE/os-includeppc/proto/asl.h>
#include </ADE/os-includeppc/proto/graphics.h>
#endif // __PPC__
#include <graphics/gfxbase.h>
#include <intuition/intuition.h>
#include <workbench/startup.h>

#pragma pack()

#include <string.h> // [SHA, 03/10/2002 : missing include ?]

#include "flash.h"
#include "swfplayer.h"

#include "timer.h"

#define TEMPLATE "FILE,PUBSCREEN/K,INFO/S,MONOSOUND/S,MAXWIDTH/K/N,MAXHEIGHT/K/N,ACTIVEPLAY/S"

unsigned long __stack = 12288; // ABA: Added some more stack

static const char *version = "$VER: SWFPlayer 1.2c ("__DATE__")";

void __chkabort(void){}
char __stdiowin[]="con:0/0//200/SWFPlayer Output/close/wait";

struct Library *CyberGfxBase=NULL;

#ifdef __PPC__
struct GfxBase *GfxBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct Library *AslBase = NULL;
struct Library *GadToolsBase = NULL;
#else
extern struct GfxBase *GfxBase;
#endif // __PPC__

LONG args[OPT_COUNT];

struct _swfinfo swfinfo;
static char filename[MAXPATH];

/* Functions definitions (See each function for description) */
void	drawinfo();
LONG	open_swf_file( char * fname );
ULONG	playswf(char *fname);
ULONG	getfilename( char * name, char * title );
long	AmigaFlashGraphicInit( FlashHandle fh );


/*
** DrawInfo()
**	- prints out misc flash informations
*/
void drawinfo()
{
 printf("%s (Flash %ld)  - Frames = %ld  - Rate = %ld fps\n", swfinfo.filename,swfinfo.fi.version,swfinfo.fi.frameCount,swfinfo.fi.frameRate);
}


/*
** open_swf_file( char * fname )
** - reads all data from specified file into buffer
*/
LONG open_swf_file( char * fname )
{
  struct FileInfoBlock *MyInfoBlock;
  LONG rc = 1;
  BPTR MyLock, fh;
  LONG bytesread;

  if (!fname) return 1;

  TRACE("Entering open_swf_file...\n");

  MyInfoBlock = (struct FileInfoBlock*)AllocDosObject (DOS_FIB, TAG_END);
  if (MyInfoBlock)
  {
    MyLock = Lock (fname, ACCESS_READ);
    if (MyLock)
    {
      if (Examine (MyLock, MyInfoBlock))
      {
        if (MyInfoBlock->fib_DirEntryType < 0)
        {
          fh = OpenFromLock(MyLock);
          if (fh)
          {
            swfinfo.buffer = (char *) AllocVec(MyInfoBlock->fib_Size, MEMF_ANY);
            if (swfinfo.buffer)
            {
              bytesread = Read(fh,swfinfo.buffer,MyInfoBlock->fib_Size);
              if (bytesread == MyInfoBlock->fib_Size)
              {
                swfinfo.filename = fname;
                swfinfo.filesize = MyInfoBlock->fib_Size;
                rc = 0;
              }
            }
            Close(fh);
            TRACE("fh closed\n");
          }
          else
          {
            /* OpenFromLock() failed, so release the lock */
            UnLock (MyLock);
          }
        } else
        {
          /* We can't open directories */
          SetIoErr(ERROR_OBJECT_WRONG_TYPE);
        }
      }
    }

    FreeDosObject (DOS_FIB, MyInfoBlock);
  }

  TRACE("Exiting open_swf_file with rc %ld\n", rc );
  return rc;
}


/*
** getfilename()
** - ask the user for a file name using the ASL file requester
*/
ULONG getfilename( char * name, char * title)
{
  struct FileRequester *fr;
  char dirname[MAXPATH];
  char *filename;
  ULONG rc=0;

  dirname[0] = NULL;
  filename = dirname;

  if( ( fr = (struct FileRequester *)
    AllocAslRequestTags(    ASL_FileRequest,
    ASLFR_TitleText,            (ULONG) title,
    ASLFR_InitialFile,        (ULONG) filename,
    ASLFR_InitialDrawer,        (ULONG) dirname,
    ASLFR_InitialPattern,    (LONG) "#?.swf",
    ASLFR_Screen,                 (LONG) swfinfo.screen,
    ASLFR_DoPatterns,            TRUE,
    TAG_DONE) ) )
  {
    if (AslRequest(fr, NULL))
    {
      strcpy(name,fr->rf_Dir);
      AddPart(name,fr->rf_File,MAXPATH);
      rc = 1;
    }
    FreeAslRequest(fr);
  }
  return rc;
}

/*
**
** AmigaFlashInitGraphic( FlashHandle ) - Amiga specific FlashInit
**
*/
long AmigaFlashGraphicInit( FlashHandle fh )
{
  long bpp = 0, bpl = 0, pad = 4;

  if( NULL != swfinfo.rport )
  {
    switch( GetBitMapAttr(swfinfo.rport->BitMap,BMA_DEPTH) )
    {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
      bpp = 1;
      pad = 2;
      break;

    case 15:
    case 16:
      bpp = 4; /* We don't support bpp=2 (16 bits/pixel) yet, so use 32 bits/pixel */
      break;

    case 24:
    case 32:
      bpp = 4;
      break;

    default:
      fprintf(stderr,"Warning: Unsupported screen depth\n");
      bpp = 1;
      pad = 2;
    }

    if (bpp) {
      bpl = (swfinfo.width*bpp + pad-1)/pad*pad;
    } else {
      bpl = (swfinfo.width/8 + pad-1)/pad*pad;
    }

    TRACE("*** Infos bpp = %ld, bpl = %ld, pad = %ld, AllocVec(%ld)\n",
                                    bpp, bpl, pad, bpl * swfinfo.height );

    swfinfo.fd = new FlashDisplay;

    swfinfo.fd->pixels = (char*) AllocVec(bpl * swfinfo.height, MEMF_ANY);
    swfinfo.fd->width    = swfinfo.width;
    swfinfo.fd->height= swfinfo.height;
    swfinfo.fd->bpl    = bpl;
    swfinfo.fd->depth    = swfinfo.depth;
    swfinfo.fd->bpp    = bpp;

    return FlashGraphicInit( fh, swfinfo.fd );
  }
  else
  {
    PrintFault( 1, "Rastport not initialized !" );
    return 0;
  }
}

/*
**
** playswf(name) - plays the specified swf file (if it exists).
**
*/
ULONG playswf(char *fname)
{
  FlashHandle flashHandle = FlashNew();
  ULONG rc = 0;

  if( open_swf_file(fname) == 0 )
  {
    int level = 0;
    int status = FlashParse(flashHandle, level, swfinfo.buffer, swfinfo.filesize);

    TRACE("FlashParse returned with status = %d\n", status );

    if( status & FLASH_PARSE_START )
    {
      FlashGetInfo(flashHandle, &swfinfo.fi);
      TRACE( "*** FlashGetInfo passed !\n" );

      /* width & height will hold the innner dimensions for our window */
      swfinfo.width  = swfinfo.fi.frameWidth/20;
      swfinfo.height = swfinfo.fi.frameHeight/20;

      /* width & height MUST be even, or swfplayer crashes.  Don't know why
      yet, so I do a simple fix here */
      if (swfinfo.width  & 1) swfinfo.width++;
      if (swfinfo.height & 1) swfinfo.height++;

      if (args[OPT_INFO]) drawinfo();

      if (open_swf_window()) // open_swf_window() can modify swfinfo.width & height!!!
      {
        int audioflags=0;
		TRACE( "*** open_swf_window() passed !\n" );

        AmigaFlashGraphicInit( flashHandle );
        TRACE( "*** AmigaFlashGraphicInit passed !\n" );

        if (args[OPT_MONO]) audioflags |= AMIGAFLAG_MONO;

        /* It does not work yet :-(
        AmigaFlashSoundInit(flashHandle, audioflags);
        TRACE( "*** AmigaFlashSoundInit passed\n" );
        */

        // [ABA, 02/10/2002 : add LOOP settings]
        FlashSettings(flashHandle, PLAYER_LOOP);
        TRACE( "*** FlashSettings passed\n" );
        // [END ABA, 02/10/2002]

        FlashSetGetUrlMethod(flashHandle, showUrl, 0);
        TRACE( "*** FlashSetGetUrlMethod passed\n" );

        rc = playMovie(flashHandle, swfinfo.screen, swfinfo.window);
        TRACE( "*** playMovie returned code %ld\n", rc );

        FlashClose(flashHandle);
        TRACE( "*** FlashClose passed\n" );

        close_swf_window();
        TRACE( "*** swf_window closed\n" );
      }
      else
        PrintFault(15,"open_swf_window failed");
    }
    else
      PrintFault(16,"FlashParse error");

    if( swfinfo.buffer )
    {
      FreeVec(swfinfo.buffer);
      swfinfo.buffer = NULL;
    }

    if( swfinfo.fd )
    {
      if( swfinfo.fd->pixels )
      {
        FreeVec( swfinfo.fd->pixels );
        swfinfo.fd->pixels = NULL;
      }
      delete swfinfo.fd;
    }
  }
  else
  {
    PrintFault(IoErr(),swfinfo.filename);
  }

  return rc;
}



int main(void)
{
  struct RDArgs *rd,*myrd=NULL;
  int err=ERROR_REQUIRED_ARG_MISSING;
  char *fname = (char *) NULL;

// [SHA, 03/10/2002 : improved PPC compilation]
#ifdef __PPC__
  GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
  IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
  AslBase = OpenLibrary("asl.library",0);
  GadToolsBase = OpenLibrary("gadtools.library",0);
#endif // __PPC__
// [END SHA, 03/10/2002]

  memset( &swfinfo, NULL, sizeof(swfinfo) ); // [SHA, 03/10/2002 : potential problem]

  swfinfo.task = FindTask(NULL);
  swfinfo.oldtaskpri = SetTaskPri(swfinfo.task,0);
  SetTaskPri(swfinfo.task,swfinfo.oldtaskpri);

  TRACE( "*** GfxBase version = %d\n", GfxBase->LibNode.lib_Version );
  if (GfxBase->LibNode.lib_Version >= 39)
    swfinfo.kick31 = 1;
  else
    swfinfo.kick31 = 0;

  /* Attempt to open cgfx.  If it doesn't open, then that's OK */
  CyberGfxBase = OpenLibrary("cybergraphics.library", 40L);

  filename[0] = NULL;

  rd=ReadArgs(TEMPLATE,args,NULL);
  if (rd)
  {
    if (args[OPT_PUBSCREEN]) swfinfo.pubscreenname = (UBYTE *) args[OPT_PUBSCREEN];

    /* Open the timer.device */
    if (opentimer())
    {
      TRACE("timer opened\n");
      err = 0;
      if (args[OPT_FILE])
      {
        /* Filename given on the command line */
        fname = (char *) args[OPT_FILE];
        TRACE("fname = '%s'\n", fname );
      }
      else
      {
        /* No filename given, so pop up an ASL file requester */
        if (getfilename(filename,"Please select a file"))
        {
          fname = filename;
        }
        else
        {
          fname = 0;
        }
      }

      if (fname) playswf(fname);

      closetimer();
      TRACE("*** timer closed\n");
    }

    FreeArgs(rd);
    TRACE( "*** Args freed\n" );

    if( myrd ) FreeDosObject(DOS_RDARGS,myrd);
  }
  else
  {
    err=IoErr();
  }

  if (err)
  {
    PrintFault(err,"SWFPlayer failed");
  }
  SetIoErr(err);

  if (CyberGfxBase) CloseLibrary(CyberGfxBase);
  TRACE( "*** CGX library closed\n" );

  TRACE( "*** Main returning %d\n", err );
  return err;
}
