/*
 * Copyright (c) 2001-2003 Shiman Associates Inc. All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */
/*
 * $Id: assembler.h,v 1.4 2003/06/30 02:22:24 rocko Exp $
 *
 * Copyright (c) 2000, 2001 by Shiman Associates Inc. and Sun
 * Microsystems, Inc. All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions: The above
 * copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Except as contained in this notice, the names of the authors or
 * copyright holders shall not be used in advertising or otherwise to
 * promote the sale, use or other dealings in this Software without
 * prior written authorization from the authors or copyright holders,
 * as applicable.
 *
 * All trademarks and registered trademarks mentioned herein are the
 * property of their respective owners. No right, title or interest in
 * or to any trademark, service mark, logo or trade name of the
 * authors or copyright holders or their licensors is granted.
 *
 */

#ifndef _ASSEMBLER_H
#define _ASSEMBLER_H

/************************************************************************
 * mas_port
 *
 * Used internally by the assembler to represent MAS ports.
 *
 ************************************************************************/
struct mas_port
{
    /* A nickname, local to a device.  Usually "control", "audio in",
       etc.  Name is only unique relative to a specific device
       instance. */ 
    char              name[MAX_PORT_NAME_LENGTH];

    /* the unique port number */
    int32             portnum;

    int32             device_instance; /* port is relative to this device */
    int16             port_type; /* source, sink, reaction */
    int32             connected_port; /* the connected source or sink
					 (0 if not connected) */

    /* The characteristic matrix defines the set of configurable data
       characteristics for a port.  Each possible data characteristic
       is one row of this matrix.  This points to an entry in the
       device profile - don't free this. */
    struct mas_characteristic_matrix* characteristic_matrix;

    /* The configured data characteristic contains an array of strings
       that's set up by the assembler.  It specifies the data format that
       the assembler configured this port to communicate.  The array
       is indexed according to the key name array also specified in the
       data characteristic. */ 
    struct mas_data_characteristic* configured_data_characteristic;


    /* the start of the data queue */
    struct mas_data*  data;

    /* the tail of the data queue */
    struct mas_data*  data_tail;
};


/************************************************************************
 * mas_device_profile
 *
 * This structure's contents describe a device library.  The bulk of
 * the members are values or pointers obtained by resolving symbols in
 * the device library's object code.  There's also a handle, used by
 * the dynamic library routines, and a member for the filename of the
 * library.
 *
 ************************************************************************/
struct mas_device_profile
{
    int id;
    
    /* These profile symbols are set to the values of symbols in the
       device object code by prepending "profile_" to the name and
       resolving the symbol.  For example, "name" is the
       "profile_name" symbol in the device's object code. */
    char*         name;
    char*         purpose;
    char*         description;
    char*         build_date;
    char*         build_host;
    char*         license;
    char*         platform;
    char*         signature;
    uint8         major_version;
    uint8         minor_version;
    uint8         teeny_version;
    uint8         patchlevel;
    int8          reentrant;
    int8          mts_acc;
    int8          ntpts_acc;
    
    /* Device actions are function pointers that point to special
       functions in the object code.  They're listed by name in the
       "action_names" array. The array of function pointers "action"
       is sorted identically to the list of action names in
       "action_names". */
    u_int8 actions; /* count of number of actions */
    char** action_names;
    int (**action)( int32 , void* ); /* array of action function pointers */ 
    struct mas_stats* action_wallclock_stats;

    /* Clocks conforming to the master clock interface */
    u_int8 clocks;
    char** clock_names;
    
    /* The characteristic matrices used by this device: */
    u_int8 cmatrices;
    char** cmatrix_names;
    struct mas_characteristic_matrix* cmatrix;

    /* The statically defined ports.  These are created during device
       instantiation, but the device must still ask for them by name. */
    u_int16 ports;
    char**  port_names;
    int16*  port_types;
    char**  port_cmatrices;

    /* The handle identifies the loaded device library object code -
       meaningless except to dynamic loading lib.  Both the handle and
       the library_filename are not set from symbols resident in the
       object code of the device; they're set by the loader. */
    void*         handle;
    char          library_filename[MAX_FNAME_LENGTH];

    /* Count of the number of device instances dependent on this
       profile. */
    int           refcount;

    /* linked-list management */
    struct mas_device_profile *next, *prev;
};

/************************************************************************
 * mas_device
 *
 * A device is an instantiation of a device library with local
 * state.  The mas_device structure describes a device, containing a
 * state memory void pointer, the instance number and a pointer to the
 * device profile structure.
 *
 ************************************************************************/
struct mas_device
{
    /* assembler-assigned session-unique instantiation ID. */
    int32 instance;

    /* count of assemblages containing device */
    int32 refcount; 

    /* This device's profile.  Points to an entry in the profile
     * list. */
    struct mas_device_profile* profile;

    /* Device instance's state pointer. */
    /* This is re-cast inside the device with a locally-scoped struct
       definition.  Outside the device actions, we don't care what's
       in this. */
    void*           state;     
                               
};

/* mas_devlist_node is used by the assemblage structure to keep track
   of its member devices.  We can't just add linked-list next & prev
   to the device structure itself because it can be in more than one
   assemblage.  */
struct mas_devlist_node
{
    int32  di; /* device instance */
    struct mas_devlist_node* next;
};

/* An assemblage of devices */
struct mas_assemblage
{
    /* The assemblage name is unique in the set of all assemblages. */
    char name[MAX_ASMB_NAME_LENGTH];

    /* unique id number */
    int32 id;

    /* A list of device instances that are in this assemblage. */
    /* The list head is valid, not a placeholder. */
    /* NOTE: any device instance can belong to more than one
       assemblage. */
    struct mas_devlist_node* device_list_head;

    /* A list of additional events to do when the assemblage is terminated. */
    struct mas_event *terminate_events;

    /* assemblage linked-list management */
    struct mas_assemblage *next, *prev;
};


extern int32   mas_asm_init( void );
extern int32   mas_asm_instantiate_device(char* name, void* predicate, char* assemblage, int32* retval_instance);
extern int32   mas_asm_terminate_device_instance(int32 di, int32 secs_to_live);
extern int32   mas_asm_teardown_device_instance(int32 di);
extern int32   mas_asm_destroy_device_instance(int32 di);
extern int32   mas_asm_unload_device_library( char* device_name );
extern int32   mas_asm_make_assemblage(char* name);
extern int32   mas_asm_add_assemblage_terminate_event( char *name, struct mas_event *event );
extern int32   mas_asm_add_tracking_assemblage_terminate_event(struct mas_event* track_event, struct mas_event *event);
extern int32   mas_asm_make_tracking_assemblage(struct mas_event* event);
extern int32   mas_asm_terminate_tracking_assemblage(struct mas_event* event);
extern int32   mas_asm_terminate_assemblage(char* name, int32 secs_to_live);
extern int32   mas_asm_make_port(char* name, int16 type,
				 int32 device_instance,
				 int* retval_portnum);
extern int32   mas_asm_cleanup_port( int32 portnum );
extern int32   mas_asm_destroy_port(int portnum);
extern int32   mas_asm_connect_source_sink(int32 source, int32 sink,
					   struct mas_data_characteristic* dc );
extern int32   mas_asm_connect_ports(int32 source, int32 sink );
extern int32   mas_asm_connect_named_ports( int32 source_device, int32 sink_device, char* source_name, char* sink_name);
extern int32   mas_asm_disconnect_port( int32 portnum, int cleanup_ports );
extern int32   mas_asm_get_action_from_name(int32 di, char* name, int (**retval_action)(int32, void*) );
extern int32   mas_asm_get_action_from_index(int32 di, int16 action_index, int (**retval_action)(int32, void*) );
extern int32   mas_asm_get_action_index(int32 device_instance, char* name, int16* retval_action_index );
extern int32   mas_asm_set_event_action_index( struct mas_event* event );
extern int32   mas_asm_action_handler( struct mas_event* event );
extern int32   mas_asm_schedule_event_simple( int32 device_instance, 
					      char* action_name,
					      void* predicate );
extern int32   mas_asm_schedule_event_simple_now( struct mas_event* current, int32 device_instance,  char* action_name, void* predicate );
extern int32   mas_asm_schedule_event(int32 target_device_instance, 
				      const char* action_name, void* predicate, 
				      uint32 secs, uint32 frac, int time_is_rel,
				      int priority, uint32 period, 
				      int32 num_port_dependencies, 
				      int32* port_dependencies);
extern int32   mas_asm_schedule_event_struct( struct mas_event* event );
extern int32   mas_asm_schedule_event_periodic(int32 target_device_instance, const char* action_name, void* predicate, int priority, uint32 period, int32 clkid );
extern int32   mas_asm_is_data_on_port( int32 portnum );
extern struct mas_event* mas_asm_get_event_queue_head ( void );
extern struct mas_mc_cb* mas_asm_get_mc_cb ( void );
extern int32   mas_asm_record_action_stats( struct mas_event* event,
					    uint32 action_us );
extern int32   mas_asm_get_action_stats_ro( int32 device_instance, int16 action_index, struct mas_stats** retval_stats_ro  );
extern int32 mas_asm_get( char* key, struct mas_package* arg, int send_req_info, struct mas_package* r_package );
extern int32 mas_asm_killall( void );
extern char** mas_asm_actions( void );
extern int32 mas_asm_connect_inline(int32 srca, int32 snkb, struct mas_data_characteristic* ab_dc, int32 srcc, int32 snkd, struct mas_data_characteristic* cd_dc, int config);
extern int32 mas_asm_disconnect_inline(int32 srca, int32 snkb, int32 srcc, int32 snkd, struct mas_data_characteristic* dc, int config);
    
#endif /* _ASSEMBLER_H */


