/*
 * DV Player plugin for VDR
 *
 * Copyright (C) 2003, 2004 Erich Bachl <erich.bachl@vr-web.de>
 *
 * This code is distributed under the terms and conditions of the
 * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details.
 *
 */

#include <signal.h>
#include <errno.h>
#include <cstring>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <asm/types.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <fcntl.h>

#include "shellthread.h"

#include "i18n.h"

int  outpipe[2], pipefl;
int  inpipe[2];
int  pid;

#define DEBUGLEVEL 1
#define LOGTYPE    STDOUT
#define STDOUT            1
#define SYSLOG            2

void dx(int level, const char *fmt, ...)
{
  char    t[BUFSIZ];
  va_list ap;
  time_t  now;


  va_start(ap, fmt);

  if (DEBUGLEVEL <= level)
    switch (LOGTYPE)
    {
      case STDOUT : vsnprintf(t + 13, sizeof t - 13, fmt, ap);
                    time(&now);
                    strftime(t, sizeof t, "dv: %H:%M:%S", localtime(&now));
                    t[12] = ' ';
                    printf("%s\033[K\n", t);
                    break;
      case SYSLOG : vsnprintf(t + 4, sizeof t - 4, fmt, ap);
                    memcpy(t, "dv: ", 4);
                    syslog(LOG_DEBUG, "%s", t);
                    break;
    }

  va_end(ap);
}

cShellThread::cShellThread()
{
  dx(3, "cShellThread::cShellThread()");
  Start();
}

void cShellThread::Action(void)
{
  char   cmd[512];
  char   Message[2048];
//  int r;

  sprintf(cmd, "dvgrab -i - |/usr/local/bin/ffmpeg -v 0 -f dv -i - -f mpegts -s 352x288 -b 5000 -y %s ", FIFO);
//  sprintf(cmd, "ffmpeg -v 0 -dv1394 -f mpegts -s 352x288 -b 2000 -y %s ", FIFO);
  dx(1, cmd);

  pipefl = 0;
  if(pipe(inpipe) == -1)
  {
    dx(1, "ERROR: pipe failed for inpipe: (%d) %s", errno, strerror(errno));
    return;
  }
  pipefl |= 1 + 2;
  if(pipe(outpipe) == -1)
  {
    dx(1, "ERROR: pipe failed for outpipe: (%d) %s", errno, strerror(errno));
    return;
  }
  pipefl |= 4 + 8;

  pid = fork();

  if(pid == -1)
    return;

  if(pid == 0)
  { // child
    close(inpipe[1]);
    close(outpipe[0]);
    if(dup2(inpipe[0], STDIN_FILENO) < 0 || dup2(outpipe[1], STDOUT_FILENO) < 0 || dup2(outpipe[1],STDERR_FILENO)<0)
    {
      dx(1, "ERROR: dup2() failed in MPlayer child: (%d) %s", errno, strerror(errno));
      exit(127);
    }
    close(inpipe[0]);
    close(outpipe[1]);

    execle("/bin/sh", "sh", "-c", cmd, 0, environ);
    dx(1, "exec(%s) failed, %d:%s", cmd, errno, strerror(errno));
    exit(127);
  }
  else // parent
  {
    dx(2, "shellthread started, pid=%d", pid);
    close(inpipe[0]);
    pipefl &= ~1;
    close(outpipe[1]);
    pipefl &= ~8;
    fcntl(outpipe[0], F_SETFL, O_NONBLOCK);

    write(inpipe[1], "p\n", 2);

    m_Loop = 1;
    while(m_Loop)
    {
       read(outpipe[0], Message, sizeof(Message));
       //int r = read(outpipe[0], Message, sizeof(Message));
       //printf("%s\n", Message);
       usleep(50000);
    }
    write(inpipe[1], "\x1b\n", 2);
    //write(inpipe[1], "q\n", 2);

    if(pipefl & 1) close(inpipe[0]);
    if(pipefl & 2) close(inpipe[1]);
    if(pipefl & 4) close(outpipe[0]);
    if(pipefl & 8) close(outpipe[1]);
    pipefl = 0;
  }

  return;
}

cShellThread::~cShellThread()
{
  dx(3, "cShellThread::~cShellThread()");

  kill(pid, SIGTERM);
  waitpid(pid, 0, WNOHANG);
  Cancel(2);
}

