/*
    GDAM - Geoff & Dave's Audio Mixer
    Copyright (C) 1999    Dave Benson, Geoff Matters.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA

    Contact:
        daveb@ffem.org <Dave Benson>
        geoff@ugcs.caltech.edu <Geoff Matters>
*/
#ifndef __GDAM_PROTOCOL_H_
#define __GDAM_PROTOCOL_H_


/*
 * Define as much of the protocol as possible
 * in a way that gdam-server and gdam-client can
 * use it.
 */

/* Bitmasks to turn various types of server logging on and off. */
typedef enum
{
  GDAM_LOG_LEVEL_ERROR = (1<<0),
  GDAM_LOG_LEVEL_DEBUG = (1<<1),
  GDAM_LOG_LEVEL_MISS_DATA = (1<<2)
} GdamLogLevel;

#define GDAM_PROTOCOL_PROFILE_FFT_MAX_LOG_BANDS		7

/* Various types of "profiles" - ways to get raw
 * samples from a buffer */
typedef enum
{
  GDAM_PROTOCOL_PROFILE_AVERAGE,
  GDAM_PROTOCOL_PROFILE_LEFT,
  GDAM_PROTOCOL_PROFILE_RIGHT,
  GDAM_PROTOCOL_PROFILE_STEREO,
  GDAM_PROTOCOL_PROFILE_MIN_MAX,
  GDAM_PROTOCOL_PROFILE_FFT,
  GDAM_PROTOCOL_PROFILE_FFT_LAST
      = GDAM_PROTOCOL_PROFILE_FFT + GDAM_PROTOCOL_PROFILE_FFT_MAX_LOG_BANDS - 1,
} GdamProtocolProfileMode;

/* These are really just ripped off from ladspa.
 * (But differently valued). */
typedef enum
{
  GDAM_PROTOCOL_CONTROL_LOGARITHMIC 		= (1<<0),
  GDAM_PROTOCOL_CONTROL_INTEGER 		= (1<<1),
  GDAM_PROTOCOL_CONTROL_HAS_MIN_VALUE 		= (1<<2),
  GDAM_PROTOCOL_CONTROL_HAS_MAX_VALUE 		= (1<<3),
  GDAM_PROTOCOL_CONTROL_IS_BOOLEAN 		= (1<<4),
  GDAM_PROTOCOL_CONTROL_IS_SAMPLE_RATE 		= (1<<5),
  GDAM_PROTOCOL_CONTROL_IS_LOGARITHMIC 		= (1<<6),
  GDAM_PROTOCOL_CONTROL_IS_INTEGER 		= (1<<7)
} GdamProtocolControlHints;

typedef enum
{
  GDAM_PROTOCOL_SOURCE_ARG = 3060,
  GDAM_PROTOCOL_BUFFER_ARG,
  GDAM_PROTOCOL_SINK_ARG,
  GDAM_PROTOCOL_COMPUTATION_ARG
} GdamProtocolArgMode;


typedef enum
{
  GDAM_PROTOCOL_GET_ALL_ONLY_VITAL	= 1,
  GDAM_PROTOCOL_GET_ALL_DEPRECATED	= 2,
} GdamProtocolGetAllFlags;

/*
 * The Message Types.
 *
 * All communication is done is packets [even the initial
 * authentication etc.]
 *
 *
 * Packets are big-endian, 4-byte length-prefixed data.
 * The length includes the length of the prefix.
 *
 * Initially, 
 * The next 4-bytes are a big-endian GdamMessageType.
 *
 * These are categorized:
 *
 *        GDAM_MESSAGE_*       client => server commands
 *        GDAM_RESPONSE_*      server => client command returns.
 *        GDAM_EVENT_*         server-event initiated communication.
 *
 * Down below, for each message type, we describe the packet layout.
 */
typedef enum _GdamMessageType
{
  GDAM_MESSAGE_FIRST_MESSAGE = 400,
  GDAM_MESSAGE_OPEN_DEVICE,       /* see below */
  GDAM_MESSAGE_FEED_DEVICE,
  GDAM_MESSAGE_CLOSE_DEVICE,

  GDAM_MESSAGE_CREATE,            /* followed by ArgMode
				   * followed by type name
				   * followed by num arguments
				   * followed by arguments. */
  GDAM_MESSAGE_DETACH_SOURCE,

  GDAM_MESSAGE_SUBSCRIBE_SOURCE,  /* followed by source_id
				   * followed by subscription type. */
  GDAM_MESSAGE_UNSUBSCRIBE,       /* followed by connection id */
  GDAM_MESSAGE_CONFIGURE_SOURCE,  /* followed by source_id
				   * followed by GdamConfigureType
				   * [configuration-specific data] */

  GDAM_MESSAGE_GET_SERVER_INT,    /* followed by namespace
				   * followed by key. */
  GDAM_MESSAGE_START_CACHING,     /* followed by soundspec */
  GDAM_MESSAGE_UNCACHE,           /* followed by buffer_id */

  GDAM_MESSAGE_GET_CACHE_PROFILE, /* followed by buffer id
				   * followed by GdamProtocolProfileMode
				   * followed by start
				   * followed by selection length
				   * followed by number of outputs.
				   * return is GDAM_RESPONSE_DATA_SUCCESS
				       followed by num_ints
				       followed by [array of ints] */

  GDAM_MESSAGE_SYNCHRONIZE,       /* followed by mobile source id
				   * followed by fixed source id
				   * followed by mobile's beat period
				   *       in samples * GdamFixed_ONE
				   *       as a 64-bit number
				   * followed by mobile's start beat
				   *       in number samples  (64-bits)
				   * followed by fixed's beat period
				   *       in samples * GdamFixed_ONE
				   *       as a 64-bit number
				   * followed by fixed's start beat
				   *       in number samples  (64-bits)
				   */
  GDAM_MESSAGE_SYNC_PREVIEW,      /* like `sync' */

  GDAM_MESSAGE_SOURCE,            /* followed by asciiz typename
				   * followed by number of args
				   * followed by name of arg1
				   * followed by type as GDAM_ARG_TYPE_*
				   * followed by value of arg1
				   * ...
				   */

  GDAM_MESSAGE_SET_ARGS,          /* 
				   * followed by type of object
				   *         (GDAM_PROTOCOL_*_ARG)
				   * followed by source/buffer id
				   * followed by number of args
				   * followed by name of arg1
				   * followed by type as GDAM_ARG_TYPE_*
				   * followed by value of arg1
				   * ... */
  GDAM_MESSAGE_GET_ARGS,          /*
				   * followed by type of object
				   *         (GDAM_PROTOCOL_*_ARG)
				   * followed by source/buffer id
				   * followed by num args
				   * followed by asciiz args */
  GDAM_MESSAGE_GET_ALL_ARGS,      /* followed by type of object
				   * followed by source id
				   * followed by flags:
				   *     1: only_vital
				   *     2: get_deprecated */
  GDAM_MESSAGE_REOPEN_DEVICE,     /* followed by sink_id */

  GDAM_MESSAGE_CALL_FUNCTION,     /* followed by type of object
				   * followed by source id
				   * followed by asciiz function name
				   * followed by num args
				   * followed by arguments (as in set_arg)
				   * --
				   * return:
				   * num return arguments
				   * array of name/typed-values. */
  GDAM_MESSAGE_REF,               /* followed by type of object
				   * followed by id, */
  GDAM_MESSAGE_UNREF,             /* followed by type of object
				   * followed by id, */
  GDAM_MESSAGE_GET_NAMED_BUFFERS, /* followed by nothing.
				   * return is 
				   *   #named buffers
				   *   asciiz of name1
				   *   ...
				   * the buffer ids are always
				   * 1,2,3... */
  GDAM_MESSAGE_CALL_CLASS_FUNCTION,/* followed by class name
				   * followed by asciiz function name
				   * followed by num args
				   * followed by arguments (as in set_arg)
				   * --
				   * return:
				   * num return arguments
				   * array of name/typed-values. */
  GDAM_MESSAGE_SET_LOG_LEVEL,     /* followed by bitwise-OR of
				   *    GDAM_LOG_LEVEL_* flags */
  GDAM_MESSAGE_CHAT,              /* followed by remote-username \0
				   * followed by text */
  GDAM_MESSAGE_SET_USERNAME,      /* followed by remote-username
				   * followed by text */
  GDAM_MESSAGE_PACKAGE    = 500,

  GDAM_RESPONSE_FAILED    = 600,
  GDAM_RESPONSE_TIME_SUCCESS,     /* followed by 8-byte int64 timecode */
  GDAM_RESPONSE_INT_SUCCESS,      /* followed by 4-byte int32 */
  GDAM_RESPONSE_2INT_SUCCESS,     /* followed by 2 4-byte int32s */
  GDAM_RESPONSE_STRING_ARRAY_SUCCESS,
  GDAM_RESPONSE_DATA_SUCCESS,     /* followed by data length
				   * followed by data. */
  GDAM_RESPONSE_SUCCESS,
  GDAM_RESPONSE_ARG_SUCCESS,      /* followed by num arguments
				   * followed by arguments. */
  GDAM_RESPONSE_CACHING_STARTED,  /* followed by cache-buffer id
				   * followed by event-connnection id */
  GDAM_RESPONSE_PACKAGE,

  /* dummy: demark the first event id */
  GDAM_EVENT_FIRST,

  GDAM_EVENT_SOURCE_ENDED,        /* followed by connection id */
  GDAM_EVENT_SOURCE_TIMER,        /* followed by connection id
				   * followed by time */
  GDAM_EVENT_CACHE_BUFFER_FINISH, /* followed by connection id
				   * followed by buffer id */
  GDAM_EVENT_ERROR_MESSAGE,       /* the int `0'.
				   * followed by general purpose
				   * error message string. */
  GDAM_EVENT_SOURCE_CREATED,      /* followed by connection id
				   * followed by source id */
  GDAM_EVENT_CHAT_MESSAGE,        /* followed by 0,
				   * follow by an ascii-0 username
				   * follow by an ascii-0 string */
  GDAM_EVENT_COMPUTATION_DONE,	  /* followed by connection id */
  GDAM_EVENT_COMPUTATION_FAILED,  /* followed by connection id */
  GDAM_MESSAGE_LAST_MESSAGE
} GdamMessageType;
#define GDAM_MESSAGE_FIRST_RESPONSE GDAM_RESPONSE_FAILED

typedef enum
{
  GDAM_CFG_MIX_ADD,               /* followed by:
                                   *     int:source id to add to mix
                                   *     time:when or -1 */
  GDAM_CFG_GET_TIME,
  GDAM_CFG_SOURCE_SEEK_RELATIVE,  /* followed by:
                                   *     time:how_much */
  GDAM_CFG_SEQUENCE_CHANGE
} GdamConfigureType;

typedef enum
{
  GDAM_SUBSCRIPTION_ENDED,        /* the end-of-file event. */
  GDAM_SUBSCRIPTION_TIMER         /* followed by period in millis */
} GdamSubscriptionType;

const char *gdam_protocol_get_enum_name(const char* family,
                                        int v);

/* GDAM_MESSAGE_OPEN_DEVICE
   string:device_name 
   string:device_opts        */
/* GDAM_RESPONSE_OPEN_DEVICE_SUCCEEDED
   int:device_id */
/* GDAM_FEED_DEVICE
   int:sink_id
   int:source_id */
/* GDAM_MESSAGE_GET_DEFAULT_DEVICE */
                /* Response is GDAM_RESPONSE_FAILED
                            or GDAM_RESPONSE_OPEN_DEVICE_SUCCEEDED */
/* GDAM_RESPONSE_FAILED
   int:message_id */
/* GDAM_MESSAGE_CREATE_SOURCE
   int:source_type (GDAM_PROTOSOURCE_...)
   (source specific data...) */
/* GDAM_RESPONSE_CREATE_SOURCE_SUCCEEDED
   int:source_id        [newly created source id] */


#endif
