/*
**
** $VER: playmovie.c 0.7 (05.11.02)
** Description
**
** (C) Copyright 1999 Paul Hill
** (C) Copyright 2002 Alexandre Balaban
**
** $HISTORY :
**		- 0.7, 05.11.02 : Added pack pragma directives for PPC compilation
**		- 0.6, 04.11.02 : improved PPC includes
**		- 0.5, 03.10.02 : o included PPC compilation by Steffen
**						  o added loop settings
**		- 0.4, 25.09.02 : added real window size in info window
**		- 0.3, 02.09.02 : reorganized playmovie loop
**		- 0.2, 27.07.02 : Cleanup
**		- 0.1, 27.02.99 : Original version by Paul Hill
**
*/

#include <stdio.h>

#pragma pack(2)

#ifndef __PPC__
#include <proto/exec.h>
#include <proto/icon.h>
#include <proto/intuition.h>
#include <proto/gadtools.h>
#else // __PPC__
#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/gadtools.h>
#endif

#include <intuition/intuition.h>

#pragma pack()

static void swf_showinfo();
static void swf_about();

// [SHA, 03/10/2002 : PPC compilation improvements]
#ifdef __PPC__
#include <sys/time.h>
#endif // __PPC__
// [END, SHA, 03/10/2002]
#include "flash.h"
#include "swfplayer.h"

#define AMIGAKEY_Down 77
#define AMIGAKEY_Up 76
#define AMIGAKEY_Left 79
#define AMIGAKEY_Right 78

static int exitnow = 0;

extern void drawchunkypixels(UBYTE *canvasBuffer,LONG bpp,LONG bpl);

/* returns 0 on exit */
ULONG playMovie(FlashHandle flashHandle, struct Screen *screen, struct Window *movie)
{
  struct IntuiMessage * imsg = NULL;
  struct MenuItem * menuitem = NULL;
  struct myTimeval  wd,
                    now;
  FlashEvent fEvent; // Flash Event for flashExec
  UWORD Code      = 0,
        Qualifier = 0;
  WORD MouseX     = 0,
       MouseY     = 0;
  ULONG wakeUp    = 0,
        zoom      = 0, // Zoom level
        Class     = 0,
        rc        = 0,
        userdata  = 0;
  int fCmd        = FLASH_WAKEUP, // Flash command for FlashExec
      delay       = 0;
  BOOL bTimerPending = FALSE;
  BOOL bLoopPlay  = TRUE; // [ABA, 03/10/2002 : loop play]

  // initialize flash event
  fEvent.type = FeNone;
  fEvent.x = fEvent.y = 0;
  fEvent.key = (FlashKey)0;

  wakeUp = FlashExec(flashHandle, fCmd, &fEvent, &wd);

  while(1)
  {
    if (delay < 0)
    {
      delay = 20;
    }

    TRACE("WakeUp = %ld  Delay = %d bTimerPending = %d\n",
                                  wakeUp, delay, bTimerPending);

    if( swfinfo.fd->flash_refresh )
    {
      TRACE("Refresh requested\n");
      drawchunkypixels( (UBYTE*)swfinfo.fd->pixels,
                                swfinfo.fd->bpp,
                                swfinfo.fd->bpl );
      swfinfo.fd->flash_refresh = 0;
      wakeUp = 0;
    }

    if( wakeUp && !bTimerPending )
    {
      /* Initialize TimerIO fields */
      TimerIO->tr_node.io_Command = TR_ADDREQUEST;
      TimerIO->tr_time.tv_secs	= delay/1000;
      TimerIO->tr_time.tv_micro	= (delay%1000)*1000;

      /* Send TimerIO asynchronously... */
      SendIO((struct IORequest *)TimerIO);

      bTimerPending = TRUE;
    }

    if( bTimerPending && CheckIO( (struct IORequest *) TimerIO ) )
    {
      WaitIO( (struct IORequest*) TimerIO );
      bTimerPending = FALSE;
      wakeUp = 1;
    }

    if( wakeUp )
    {
      fCmd |= FLASH_WAKEUP;
      wakeUp = 0;
    }

    while( (imsg = (struct IntuiMessage *)GT_GetIMsg(swfinfo.window->UserPort)) )
    {
      Class     = imsg->Class;
      Code      = imsg->Code;
      Qualifier = imsg->Qualifier;
      MouseX    = imsg->MouseX;
      MouseY    = imsg->MouseY;

      GT_ReplyIMsg(imsg);

      switch ( Class )
      {
        case IDCMP_CLOSEWINDOW:
          return 0;
          break;

        case IDCMP_VANILLAKEY:
          switch (Code)
          {
            // Continue
            case 'C':
            case 'c':
              fCmd |= FLASH_CONT;
              break;
            // Pause
            case 'P':
            case 'p':
              fCmd |= FLASH_STOP;
              break;
            // Rewind
            case 'R':
            case 'r':
              FlashExec(flashHandle, FLASH_REWIND, 0, &wd);
              fCmd |= FLASH_CONT;
              break;
            // Quit
            case 'Q':
            case 'q':
            case  27:
              FlashExec(flashHandle, FLASH_STOP, 0, &wd);
              return 0;
              break;
            // Zoom In
            case '+':				/* Zoom in */
            case '=':
              FlashZoom( flashHandle, ++zoom );
              break;
            // Zoom Out
            case '-':				/* Zoom out */
              FlashZoom( flashHandle, --zoom );
              break;
            // Tab or Enter
            case 9:
            case 13:
              fEvent.type	= FeKeyPress;
              fEvent.key	= (Code == 9)?FeKeyNext:FeKeyEnter;
              fCmd       |= FLASH_EVENT;
              break;
            default:
              TRACE("VANILLAKEY ='%d'\n", Code);
              break;
          }
        break;

        case IDCMP_RAWKEY:
          if (!(Code & 0x080))
          {
            fEvent.type	= FeKeyPress;
            fEvent.key	= (FlashKey)0;
            /* Key press */
            switch (Code & 0x07F)
            {
            case AMIGAKEY_Up:
              fEvent.key = FeKeyUp;
              break;
            case AMIGAKEY_Down:
              fEvent.key = FeKeyDown;
              break;
            case AMIGAKEY_Left:
              fEvent.key = FeKeyLeft;
              break;
            case AMIGAKEY_Right:
              fEvent.key = FeKeyRight;
              break;
            default:
              TRACE("RAWKEY = '%d'\n", Code & 0x07F);
              break;
            }
            if (fEvent.key != 0)
            {
              fCmd |= FLASH_EVENT;
            }
          }
        break;

        case IDCMP_MOUSEBUTTONS:
        {
          switch( Code )
          {
            case SELECTDOWN:
              fEvent.type = FeButtonPress;
              break;
            case SELECTUP:
              fEvent.type = FeButtonRelease;
              break;
          }
          fEvent.x = MouseX;
          fEvent.y = MouseY;
          fCmd |= FLASH_EVENT;
        }
        break;

        case IDCMP_INTUITICKS:
        {
          fEvent.type = FeMouseMove;
          fEvent.x = MouseX - swfinfo.window->BorderLeft;
          fEvent.y = MouseY - swfinfo.window->BorderTop;
          fCmd |= FLASH_EVENT;
        }
        break;

        case	IDCMP_MENUPICK:
        {
          rc = 0;
          while(Code != MENUNULL)
          {
            menuitem = ItemAddress(swfinfo.SWFPlayerMenus, Code);
            userdata = (ULONG ) GTMENUITEM_USERDATA(menuitem);
            if (userdata < MENU_MAX)
            {
              switch (userdata)
              {
                case MENU_INFO:
                  swf_showinfo();
                  break;
                case MENU_ABOUT:
                  swf_about();
                  break;
                case MENU_QUIT:
                  exitnow = 1;
                  break;
                case MENU_PAUSE:
                  fCmd |= FLASH_STOP;
                  break;
                case MENU_CONTINUE:
                  fCmd |= FLASH_CONT;
                  break;
                case MENU_REWIND:
                  FlashExec(flashHandle, FLASH_REWIND, 0, &wd);
                  fCmd |= FLASH_CONT;
                  break;
                case MENU_ZOOMIN:
                  FlashZoom(flashHandle,++zoom);
                  break;
                case MENU_ZOOMOUT:
                  FlashZoom(flashHandle,--zoom);
                  break;
                // [ABA, 03/10/2002 : LOOP setting handling]
                case MENU_LOOPPLAY:
                {
                  long Settings;
                  if( !bLoopPlay )
                  {
                    Settings = PLAYER_LOOP;
                    bLoopPlay = TRUE;
                  }
                  else
                  {
                    Settings = 0;
                    bLoopPlay = FALSE;
                  }
                  FlashSettings(flashHandle, Settings);
                  break;
                }
                // [END ABA, 03/10/2002]
              }
            }

            Code = menuitem->NextSelect;
          }
          if( exitnow ) return 0;
        }
        break;

        case IDCMP_ACTIVEWINDOW:
          SetTaskPri(swfinfo.task,swfinfo.oldtaskpri);
        break;

        case IDCMP_INACTIVEWINDOW:
        {
          if( args[OPT_ACTIVEPLAY] )
          {
            /* the user has specified the 'ACTIVEPLAY' option.
            This means we only play the movie if the window is
              active. */
            TRACE("ActivePlay is on, waiting for window activation\n");
            /* PRH: I'm not 100% sure this is OK... */
            WaitPort(swfinfo.window->UserPort);
          }

          SetTaskPri(swfinfo.task,-1);
        }
        break;
      }
    }

    if( fCmd )
    {
      wakeUp = FlashExec(flashHandle, fCmd, &fEvent, &wd);
      fCmd = 0;
      fEvent.type = FeNone;
      fEvent.x = fEvent.y = 0;
      fEvent.key = (FlashKey)0;
    }

    /* Recompute delay */
    gettimeofday( &now,0 );
    delay = (wd.tv_sec-now.tv_sec)*1000 + (wd.tv_usec-now.tv_usec)/1000;
  }
}

static void swf_showinfo()
{
  char info[] = "File : %s (Flash v%ld)\nHeight = %ld (Window = %ld)\nWidth = %ld (Window = %ld)\nFrames = %ld\nRate = %ld fps";
  struct EasyStruct es = {
    sizeof (struct EasyStruct),
      0,
      (UBYTE*)"SWF Properties",
      (UBYTE*)info,
      (UBYTE*)"OK",
  };

  if (swfinfo.window)
  {
    EasyRequest(swfinfo.window, &es, NULL,
                (ULONG) swfinfo.filename,
                swfinfo.fi.version,
                swfinfo.fi.frameHeight,
                swfinfo.height,
                swfinfo.fi.frameWidth,
                swfinfo.width,
                swfinfo.fi.frameCount,
                swfinfo.fi.frameRate);
  }
}

static void swf_about()
{
  char info[] =
    "******* swfplayer *******\n"
    "A standalone Flash Player for AmigaOS\n"
    "Based on Version 0.4.10 of the Flash Plugin.\n"
    "\n"
    "Original version & Flash Plugin by\n"
    "Olivier Debon <odebon@club-internet.fr>\n"
    "\n"
    "Original Amiga port by Paul Hill <paul@lagernet.clara.co.uk>\n"
    "V0.4.10 update by Alexandre Balaban <abalaban@free.fr>\n"
    "\n"
    "http://www.geocities.com/TimesSquare/Labyrinth/5084/flash.html\n"
    "http://www.lagernet.clara.co.uk\n"
    "http://abalaban.free.fr\n";

  struct EasyStruct es = {
    sizeof (struct EasyStruct),
      0,
      (UBYTE*)"About swfplayer",
      (UBYTE*)info,
      (UBYTE*)"OK",
  };

  if (swfinfo.window)
  {
    EasyRequest(swfinfo.window, &es, NULL, NULL);
  }
}
