/*
 * watch-focus.c
 *
 * $Revision: 0.1 $
 *
 * Command line program to trace which app has ViaVoice speech focus
 *
 * Copyright (c) 2002, Michael Kosowsky
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

/*
 * 
 * compile with -I/usr/lib/ViaVoice/include -lsmapi -lpopt
 *
*/



#include <stdio.h>
#include <smapi.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <unistd.h>
#include <popt.h>

#ifndef TRUE
#define TRUE (1)
#endif
#ifndef FALSE
#define FALSE (0)
#endif


#define appName "watch-focus"
#define DEBUG


#ifdef DEBUG
#define dbgprintf(x) do {		\
  printf("%s: ", __FUNCTION__);		\
    printf x ;				\
} while (0)
#else
#define dbgprintf(x)
#endif


#define  TRY(p)	CHECK(p, SM_RC_OK)

#define CHECK(p, c)				\
    do {					\
      rc = (p);					\
      if (rc != (c)) {				\
	dbgprintf(("%s: %d\n", #p, rc));	\
        exit (-1); }				\
    } while (0)

#define CHECK2(p, c1, c2)			\
    do {					\
      rc = (p);					\
      if (rc != (c1) && rc != (c2)) {		\
	dbgprintf(("%s: %d\n", #p, rc));	\
        exit (-1); }				\
    } while (0)


static int exit_val = 0;


/* These are passed to us from the ViaVoice lib
 * through the notifier callback, and we use them to
 * talk to the engine.
 */

static int smapi_socket = 0;
static int ( * smapi_fn ) ( ) = NULL;
static void * smapi_data = NULL;


int main (int argc, const char **argv)
{
  fd_set        rfds;
  int           retval, rc, j;
  SM_MSG        reply;
  unsigned long state;
  char          *app;
  static int    Connect(char* lib);

  /* audiolib must match whatever the other voice apps have set;
     this string is what xvoice sets by default */
  if (Connect("pcm;audoss.so;;foo") != 0) exit(-1);

  TRY( SmSet(SM_NOTIFY_FOCUS_STATE, TRUE, &reply) );


  while (1) {
    /* wait for input on smapi_socket, then read it with SmReceiveMsg,
       rather than bother with callbacks */
    FD_ZERO(&rfds);
    FD_SET(smapi_socket, & rfds);
    if (!select(smapi_socket + 1, &rfds, NULL, NULL, (struct timeval *) NULL))
      continue;

    TRY( SmReceiveMsg(0, &reply) );
    TRY( SmGetMsgType(reply, &j) );

    if (j == SM_FOCUS_STATE) {
      SmGetFocusState(reply, &state);
      SmGetApplication(reply, &app);
      dbgprintf(("app %s state %d %s\n", app, state,
	       state == SM_NOTIFY_FOCUS_REQUESTED? "REQUESTED"
	     : state == SM_NOTIFY_FOCUS_GRANTED?   "GRANTED"
	     : state == SM_NOTIFY_FOCUS_DENIED?    "DENIED"
	     : state == SM_NOTIFY_FOCUS_RELEASED?  "RELEASED"
	     :                                     "??"));
    }
    else {
      dbgprintf(("message %d\n", j));
      continue; }
  }
}


static int notifier ( int socket_handle, int ( * recv_fn ) ( ), void * recv_data, void * client_data )
{
  smapi_socket = socket_handle;
  smapi_fn     = recv_fn;
  smapi_data   = recv_data;

  return ( 0 );
}


static int Connect(char* lib)
{
  static int first = TRUE;
  int        rc;
  int        smc;
  SmArg      smargs [ 30 ];
  char       * cp;
  static int input_id;
  SM_MSG     reply;

  dbgprintf(("started\n"));

  if ( first )
  {
    smc = 0;
    SmSetArg ( smargs [ smc ], SmNapplicationName,  appName );  smc++;
    SmSetArg ( smargs [ smc ], SmNexternalNotifier, notifier ); smc++;

    rc = SmOpen ( smc, smargs );
    if ( rc != SM_RC_OK )
    {
      dbgprintf(("SmOpen %d\n", rc ));
      return rc;
    }

    first = FALSE;
  }

  smc = 0;
  SmSetArg ( smargs [ smc ], SmNuserId,       SM_USE_CURRENT );  smc++;
  SmSetArg ( smargs [ smc ], SmNenrollId,     SM_USE_CURRENT );  smc++;
  SmSetArg ( smargs [ smc ], SmNtask,         SM_USE_CURRENT );  smc++;
  SmSetArg ( smargs [ smc ], SmNrecognize,    TRUE           );  smc++;
  SmSetArg ( smargs [ smc ], SmNoverrideLock, TRUE           );  smc++;
  SmSetArg ( smargs [ smc ], SmNaudioHost,    lib            );  smc++;

  rc = SmConnect(smc, smargs, &reply);
  if (rc != SM_RC_OK) {
    dbgprintf(("SmConnect %d\n", rc));
    if (rc == SM_RC_ENOSERVER)
      fprintf(stderr, "%s", "Did you . vvsetenv?\n");
    return rc;
  }
  return 0;
}
