#include "irec.h"

/* ------------------------------------------------------------------- */
/*      for cback.o startup */
/* ------------------------------------------------------------------- */

long                      __stack        = 4096;
char                      *__procname    = IREC_VERSION;
long                      __priority      = 0L;
long                      __BackGroundIO = 0;
extern BPTR               _Backstdout;

struct EasyStruct InfoReq =
       {
        0L,0L,(UBYTE *)"InputEvent Recorder",
              (UBYTE *)IREC_VERSION "\n\nFreeware By Lunqual%%MAB@wsb.freinet.de\n",
              (UBYTE *)"Beenden|Weiter",
       };

UBYTE  *version = IREC_VERSION; 
struct NewBroker  newbroker;
CxObj            *broker;  
char            **tooltypes;
struct List       action_list;
UBYTE  rec_start[STRMAXLEN];
UBYTE  rec_stop [STRMAXLEN];
UBYTE  rec_file [STRMAXLEN];
LONG   recording;
ULONG  min_delay;
BYTE   h_priority;
ULONG  i_mb,i_dl;
ULONG  max_on;
ULONG  rec_max;
ULONG  cycle1;

long              __OSlibversion = 37;

void __stdargs main(int argc,char **argv)
{
 int   end = FALSE;
 NewList(&action_list);
 {
  if(OpenBroker(argc,argv))
  {
   if(init_recorder())
   {
    if(cycle1 && rec_max && max_on)
    {
     Delay(cycle1);
     rec_start_f(rec_max + 1);
     Wait(1L << SigBit);
     rec_stop_f(rec_file);
    }
    else
    {
     while(!end)
     {
      ULONG sgs;
      sgs = Wait((1L << newbroker.nb_Port->mp_SigBit)|(1L << SigBit));
      if(sgs & 1L << SigBit)
      {
       rec_stop_f(rec_file);
      }
      if(HandleBroker() == RETURN_QUIT) end = TRUE;
     }
    }
    exit_recorder();
   }
   CloseBroker();
  }
 }
 exit(0);
}

int OpenBroker(int argc,char **argv)
{
 int     ret = FALSE;
 if(newbroker.nb_Port = CreateMsgPort())
 {
  tooltypes = ArgArrayInit(argc,argv);
  newbroker.nb_Version = NB_VERSION;
  newbroker.nb_Name    = "IREC";
  newbroker.nb_Title   = "InputEvent Recorder";
  newbroker.nb_Descr   = "Writes InputEvents to a Textfile";
  newbroker.nb_Unique  = NBU_UNIQUE | NBU_NOTIFY;
  newbroker.nb_Pri     = (BYTE)ArgInt(tooltypes,"CX_PRIORITY",0);
  min_delay            = (ULONG)ArgInt(tooltypes,"MIN_DELAY",25);
  h_priority           = (BYTE)ArgInt(tooltypes,"HANDLER_PRIORITY",60);
  rec_max              = (ULONG)ArgInt(tooltypes,"REC_MAXCHAR",0);
  cycle1               = (ULONG)ArgInt(tooltypes,"WAIT",0);

  strncpy(rec_file,ArgString(tooltypes,"RECFILE","ram:irec_file.0"),STRMAXLEN);
  if(!stricmp(ArgString(tooltypes,"INCLUDE_MB","NO"),"YES"))
   i_mb = TRUE;
  else
   i_mb = FALSE;
  if(!stricmp(ArgString(tooltypes,"INCLUDE_DELAY","NO"),"YES"))
   i_dl = TRUE;
  else
   i_dl = FALSE;
 if(!stricmp(ArgString(tooltypes,"REC_MAX_ON","NO"),"YES"))
   max_on = TRUE;
  else
   max_on = FALSE;

  if(broker = CxBroker(&newbroker,NULL))
  {
   struct a_node *node;
   if(node  = MakeActionNode(ArgString(tooltypes,"RECSTARTKEY","f4"),NULL,
                               REC_START)) AddTail(&action_list,(struct Node *)node);
   if(node  = MakeActionNode(ArgString(tooltypes,"RECSTOPKEY","shift f4"),NULL,
                               REC_STOP)) AddTail(&action_list,(struct Node *)node);
   ret = TRUE;
  }
 }
 if(ret)ActivateCxObj(broker,1L);
 return ret;
}

void CloseBroker()
{
 struct a_node *n;
 struct Message *msg;
 if(broker)
 {
   if(newbroker.nb_Port)
  {
   while(msg = GetMsg(newbroker.nb_Port))ReplyMsg(msg);
   DeletePort(newbroker.nb_Port);
  }
  while(n = (struct a_node *)RemHead(&action_list))RemActionNode(n);
  DeleteCxObjAll(broker);
  if(tooltypes)ArgArrayDone();
 }
}

struct a_node *MakeActionNode(UBYTE *key,UBYTE *file,LONG ID)
{
 struct a_node *node;
 if(node = (struct a_node *)AllocVec(sizeof(struct a_node),MEMF_PUBLIC | MEMF_CLEAR))
 {
  strncpy(node->an_action.hotkey,key,STRMAXLEN);
  strncpy(node->an_action.file,file,STRMAXLEN);
  node->an_action.id = ID;
  if(node->an_action.key = CxFilter(node->an_action.hotkey))
  {
   AttachCxObj(broker,node->an_action.key);
   if(node->an_action.sender = CxSender(newbroker.nb_Port,ID))
   {
    AttachCxObj(node->an_action.key,node->an_action.sender);
    if(node->an_action.translate = (CxTranslate(NULL)))
    {
     AttachCxObj(node->an_action.key,node->an_action.translate);
    }
   }
  }
 }
 return node;   
}

void  RemActionNode(struct a_node *node)
{
 DeleteCxObjAll(node->an_action.key);
 FreeVec(node); 
}

int HandleBroker()
{
 LONG id,type;
 int rc = RETURN_IS_OK;
 CxMsg *msg;
 if(msg = (CxMsg *)GetMsg(newbroker.nb_Port))
 {
  id    = CxMsgID(msg);
  type  = CxMsgType(msg);
  ReplyMsg((struct Message *)msg);
  switch(type)
  {
   case CXM_IEVENT   : switch(id)
                       {
                        case REC_START : rec_start_f((rec_max && max_on) ? rec_max + 1 : 0);
                                         break;
                        case REC_STOP  : rec_stop_f(rec_file);
                                         break;
                       }
                       break;
   case CXM_COMMAND  :
        switch(id)
        {
         case CXCMD_DISABLE   : ActivateCxObj(broker,0L);
                                break;
         case CXCMD_ENABLE    : ActivateCxObj(broker,1L);
                                break;
         case CXCMD_KILL      : if(EasyRequest(NULL,&InfoReq,NULL) == 1)rc = RETURN_QUIT;
                                break;
         case CXCMD_UNIQUE    : rc = RETURN_QUIT;
                                break; 
         default     : break;
        }
        break;     
   default           : break;
  }
 }
 return rc;
}
