/*$cb
 *    This file is a part of libopenmhp.
 *
 *    Copyright (C) 2005 Mikko Novaro <miknov@gmail.com>
 *
 *    See main header file (libopenmhp/openmhp.h) for licensing and
 *    contact information.
 $ce*/

#include <jni.h>
#include "libopenmhp_Grabber.h"
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/msg.h>

#define WIDTH   720
#define HEIGHT  576
#define LAYER_COUNT 2
#define BYTES_PER_PIXEL 4
#define SHM_SZ  WIDTH*HEIGHT*LAYER_COUNT*BYTES_PER_PIXEL
// #define DEBUG

int shmkey = 0;
int shmid = -1;
int *shm;

JNIEXPORT jboolean JNICALL Java_libopenmhp_Grabber_initSharing
  (JNIEnv *env, jclass cls)
{
  /* Initiate sharing images by creating and attaching a shared
   * memory segment for image data and a message queue for senging
   * image update messages. */

  /* LIBOPENMHP_PATHNAME and LIBOPENMHP_PROJID from libopenmhp Makefile
     ("make java_jni") through jni_compile.sh . */
  shmkey = ftok(LIBOPENMHP_PATHNAME, LIBOPENMHP_PROJID);
  shmid = shmget(shmkey, SHM_SZ, 0600 | IPC_CREAT);
  if (shmid == -1) {
    printf("LIBOPENMHP/JAVA-JNI: shmget failed\n");
    return JNI_FALSE;
  }
  void *shm_addr = shmat(shmid, NULL, SHM_RND);
  if (shm_addr == (void *)-1) {
    shmid = -1;
    printf("LIBOPENMHP/JAVA-JNI: shmat failed\n");
    return JNI_FALSE;
  }
      
  shm = (int *)shm_addr;

  printf("LIBOPENMHP/JAVA-JNI: shared memory attached succesfully\n");

  return JNI_TRUE;
}

JNIEXPORT void JNICALL Java_libopenmhp_Grabber_endSharing
  (JNIEnv *env, jclass cls)
{
  /* Detach shared memory and msg queue. Actual removing
   * is done at the client side. */
   
  shmid = -1;
  shmdt(shm);
  shm = NULL;
}


JNIEXPORT void JNICALL Java_libopenmhp_Grabber_shareSnapshot
  (JNIEnv *env, jclass cls, jintArray snapshot, jint layerIndex)
{
  /* Copy a pixel array of a captured image into shared memory */
	
  int i = 0;
  int layerOffset = layerIndex * WIDTH * HEIGHT;
  // shared memory not attached
  if (shmid == -1) {
#ifdef DEBUG
    printf("LIBOPENMHP/JAVA-JNI: sharing not initialized\n");
#endif
    return;
  }
  
#ifdef DEBUG
  printf("begin: image --> shared memory...\n");
#endif

  jsize len = (*env)->GetArrayLength(env, snapshot);

  jint *body = (*env)->GetIntArrayElements(env, snapshot, JNI_FALSE);
  for (i=0; i<len; i++) {
    shm[i+layerOffset] = body[i]; // copy pixel to shared memory
  }

  (*env)->ReleaseIntArrayElements(env, snapshot, body, JNI_ABORT);

#ifdef DEBUG
  printf("             ...done.\n");
#endif

  return;
}
