/*
 *  IR-Send V1.0
 *
 *  Purpose: Send a command (or more than one) directly
 *           (without ir-runner)
 */
#include <libraries/irbase.h>

#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/utility.h>
#include <proto/infrared.h>

#include <mike_h/packer.h>
#include <mike_h/listsupport.h>
#include <stdlib.h>

#define VERSION "1.0"

/*
 *  static protos
 */
static BOOL  setuplist( char * );
static void freelist( void );
static void sendcommand( char * );

/*
 *  static data
 */
struct List list;

static char version[] = "$VER: IR-Send "VERSION;
static char usage[]   = "IR-Send "VERSION" ©1994 by Michael Watzl\n\nUsage: IR-Send project.irm $name1 $name2\nor     IR-Send project.irm 5 1\n";

static char file_code[]    = "IRMD";    // file code version 1.0 is to be attached

// see GNRENDER_ defines
static char *type_string[] = {"Gfx2-node","Gfx1-node","Text-node"};

// see TYP_ defines
static char *ir_string[]   = {"37 kHz","45 kHz","Unpulsed","66 kHz","Control_L","Rapid","Shell-Command","Conrad-Relaicard","Audio-DMA"};


struct Library *IRBase;

int main( int argc , char **argv )
{
    int i;

    switch( argc ){
    case 0:         // No WBstart, please; perhaps you can insert an requester here...
        return(0);
    case 1:
    case 2:
        PutStr( usage );
        return(5);
    default:
        if( IRBase = OpenLibrary( "InfraRed.library",0)){
            NewList( &list );

            IRsetversion(1);    // version 0 == 1.00 to 2.61
                                // version 1 == 3.00 to...

            if( setuplist( argv[1] )){
                for( i=2;i<argc;i++){
                    sendcommand( argv[i] );
                    Delay(10);
                }
                freelist();
            }
            CloseLibrary( IRBase );
        } else Printf("Can't open \"%s\"\n","InfraRed.library");
        return(0);
    }
}

static BOOL
setuplist( char *name )
{
    BPTR fh;

    if( fh = Open( name , MODE_OLDFILE )){
        char temp[1024];

        Read( fh , temp , 4 );                          // read file_code
        if( !Strnicmp( temp ,file_code , 4)){           // compare it
            Read( fh , temp , 3 );                      // read file code version
            if( !Strnicmp( temp , "1.0" , 3)){          // & compare
                unsigned short size;
                unsigned short usize;
                struct GNode *gn;

                Read( fh , &size , 2 );                // size of packed project header
                Seek( fh , size  , OFFSET_CURRENT );   // skip the project header (not used, 'cause we do not)
                                                       // want to open a window...

                while( Read( fh , &size , 2 ) == 2 ){   // get length of packed gnode
                    Read( fh , temp , size );           // get packed gnode

                    if( gn = malloc( sizeof( struct GNode ))){
                        // simple ByteRun1 dempack algorithm - not included to the source
                        UnPackData( temp , (char *)gn , size , sizeof( struct GNode ));

                        Read( fh , &size , 2 );         // size of packed renderdata (eiher imagedata or text)
                        switch( gn->gn_gnrender ){
                        case GNRENDER_TEXT:
                            Read( fh , &usize , 2 );    // get unpacked size of renderdata
                            if( gn->gn_renderdata = malloc( usize )){
                                Read( fh, temp , size );
                                UnPackData( temp , gn->gn_renderdata , size , usize );
                            }
                            break;
                        case GNRENDER_GFX1:
                        case GNRENDER_GFX2:
                        default:
                            gn->gn_renderdata = 0;
                            Seek( fh , 2 , OFFSET_CURRENT );    // don't read the image data in this case
                            Seek( fh , size , OFFSET_CURRENT ); // if you would like to show it - you have
                            break;                              // to alloc chip and set the ImageData pointer...
                        }
                        AddGTail( &list , gn );
                    } else PutStr("Out of memory\n");
                }
            } else Printf("Sorry, I can't read version %s of IR-Master datafiles.\n",temp);
        } else Printf("\"%s\" is not a IR-Master data file.\n",name);
        Close( fh );
    } else Printf("Can't open \"%s\".\n",name);

    return( (BOOL)!IsListEmpty( &list ) );
}

static void
freelist( void )
{
    struct GNode *gn;

    while( gn = GetGHead( &list ) ){
        RemoveG( gn );
        if( gn->gn_renderdata ) free( gn->gn_renderdata );
        free( gn );
    }
}

static void
sendcommand( char *name )
{
    char *buffer;
    struct GNode *gn = GetGHead( &list );

    if( name[0] == '$' ){                                   // search by a name or by number
        while( gn ){
            if( gn->gn_gnrender == GNRENDER_TEXT ){       // only text-nodes support named search
                if(!Stricmp(gn->gn_renderdata,&name[1])){
                    break;
                }
            }
            gn = GetGSucc( gn );
        }
    } else {
        int n = atoi( name );                               // get number
        if( n <= GetGNodeNum( &list , GetGTail( &list ) ) ){ // is number valid?
            gn = GetGNodeAddr( &list , n );                  // get node by number
        } else gn = NULL;
    }
    if( gn ){
        switch( gn->gn_type ){
        case TYP_CONRAD:
        case TYP_COMMAND:
        case TYP_RAPID_CODE:
        case TYP_CONTROL_L:
            PutStr("Nodetype not supported by this sender.\n"); // this is still internal...
            return;
        case TYP_DMASEND:
            if( buffer = malloc( IRgetlen( gn->gn_irdata ))){
                IRdma( gn->gn_irdata , buffer , gn->gn_multisend , gn->gn_type );
                free( buffer );
            }
            break;
        case TYP_KHZ66:
        case TYP_NOPULSE:
        case TYP_KHZ45:
        case TYP_KHZ37:
            if( buffer = malloc( IRgetlen( gn->gn_irdata ))){
                IRmain( gn->gn_irdata , buffer , gn->gn_multisend , gn->gn_type , gn->gn_channel );
                free( buffer );
            }
            break;
        }
    }
}
