/*
 * snapshot.c: A plugin for the Video Disk Recorder
 *
 * See the README file for copyright information and how to reach the author.
 *
 * $Id$
 */

#include <stdio.h>
#include <string.h>

#include <vdr/plugin.h>
#include <vdr/device.h>
#include <vdr/interface.h>
#include <vdr/skins.h>
#include <vdr/thread.h>
#include <vdr/tools.h>
#include <vdr/status.h>
#include <vdr/videodir.h>

#include "i18n.h"

static const char *VERSION        = "0.4.5";
static const char *DESCRIPTION    = "Snapshot";
static const char *MAINMENUENTRY  = "Take Snapshot";

// --------------- Setup menu -------------------

#include <vdr/menuitems.h>

class cPluginSnapshot;

class cMenuSetupSnapshot : public cMenuSetupPage
{
  private:
    cPluginSnapshot *m_Plugin;

    int   m_HideMainMenuEntry;
    int   m_Jpeg;
    int   m_Quality;
    int   m_SizeX;
    int   m_SizeY;
    char  m_DestDir[1024];

  protected:
    virtual void Store(void);

  public:
    cMenuSetupSnapshot(cPluginSnapshot *Plugin);
};

// --------------- Plugin -----------------------

class cPluginSnapshot : public cPlugin, public cStatus 
{
  private:

  protected:
    bool    m_HideMainMenuEntry;
    bool    m_Jpeg;
    int     m_Quality;
    int     m_SizeX;
    int     m_SizeY;
    cString m_DestDir;

    bool    m_HaveSetup;

    char    m_Current[4096];   // current program or channel
    bool    m_SnapshotPending;

    void SaveSetup(void);
    void TakeSnapshot(void);

    friend class cMenuSetupSnapshot;

  public:

    // cPlugin
    cPluginSnapshot(void);
    virtual ~cPluginSnapshot() {};
    virtual const char *Version(void) { return VERSION; }
    virtual const char *Description(void) { return tr(DESCRIPTION); }
    virtual const char *CommandLineHelp(void);
    virtual bool ProcessArgs(int argc, char *argv[]);
    virtual bool Initialize(void);
    virtual bool Start(void);
    virtual const char *MainMenuEntry(void) { return m_HideMainMenuEntry ? NULL : tr(MAINMENUENTRY); }
    virtual cOsdObject *MainMenuAction(void);
    virtual cMenuSetupPage *SetupMenu(void);
    virtual bool SetupParse(const char *Name, const char *Value);
    
  protected:

    // cStatus
    virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber);
    virtual void Replaying(const cControl *Control, const char *Name, 
			   const char *FileName, bool On);
};

cPluginSnapshot::cPluginSnapshot(void)
{
  // Initialize any member variables here.
  // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
  // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
  m_HideMainMenuEntry = false;
  m_Jpeg    = true;
  m_Quality = -1;
  m_DestDir = cString::sprintf("%s/%s", VideoDirectory, "/snapshots/");
  m_SizeX   = 720;
  m_SizeY   = 576;

  m_HaveSetup = false;

  m_Current[0] = 0;
  m_SnapshotPending = false;
}

const char *cPluginSnapshot::CommandLineHelp(void)
{
  // Return a string that describes all known command line options.
  return NULL;
}

bool cPluginSnapshot::ProcessArgs(int argc, char *argv[])
{
  // Implement command line argument processing here if applicable.
  return true;
}

bool cPluginSnapshot::Initialize(void)
{
  // Initialize any background activities the plugin shall perform.
  return true;
}

bool cPluginSnapshot::Start(void)
{
  // Start any background activities the plugin shall perform.

  SaveSetup();
  RegisterI18n(Phrases);

  return true;
}

cOsdObject *cPluginSnapshot::MainMenuAction(void)
{
  // Perform the action when selected from the main VDR menu.
  if(m_SnapshotPending) {
    m_SnapshotPending = false;
    TakeSnapshot();
  } else {
    m_SnapshotPending = true;
    cRemote::CallPlugin("snapshot");
  }
  return NULL;
}

void cPluginSnapshot::TakeSnapshot(void)
{
  if(cDevice::PrimaryDevice()) {
    time_t now = time(NULL);
    struct tm tm_r;
    struct tm *t = localtime_r(&now, &tm_r);
    cString FileName = cString::sprintf("%s/%s_%04d-%02d-%02d_%02d%02d%02d.%s", 
					*m_DestDir, m_Current,
					t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 
					t->tm_hour, t->tm_min, t->tm_sec,
					m_Jpeg ? "jpeg" : "pnm");

    if(cDevice::PrimaryDevice()->GrabImageFile(FileName, m_Jpeg, m_Quality, m_SizeX, m_SizeY))
      Skins.Message(mtInfo, tr("Snapshot saved"));
    else
      Skins.Message(mtInfo, tr("Error saving snapshot"));
  }
}

cMenuSetupPage *cPluginSnapshot::SetupMenu(void)
{
  // Return a setup menu in case the plugin supports one.
  return new cMenuSetupSnapshot(this);
}

bool cPluginSnapshot::SetupParse(const char *Name, const char *Value)
{
  // Parse your own setup parameters and store their values.

  m_HaveSetup = true;

  if(!strcmp(Name,"HideMainMenuEntry")) m_HideMainMenuEntry = atoi(Value) ? true : false;
  else if(!strcmp(Name,"Jpeg"))     m_Jpeg    = atoi(Value) ? true : false;
  else if(!strcmp(Name,"Quality"))  m_Quality = atoi(Value);
  else if(!strcmp(Name,"SizeX"))    m_SizeX   = atoi(Value);
  else if(!strcmp(Name,"SizeY"))    m_SizeY   = atoi(Value);
  else if(!strcmp(Name,"DestDir"))  m_DestDir = Value;
  else return false;
  return true;
}

void cPluginSnapshot::SaveSetup(void)
{
  SetupStore("HideMainMenuEntry", m_HideMainMenuEntry);
  SetupStore("Jpeg", m_Jpeg);
  SetupStore("Quality", m_Quality);
  SetupStore("SizeX", m_SizeX);
  SetupStore("SizeY", m_SizeY);
  SetupStore("DestDir", m_DestDir);

  MakeDirs(m_DestDir, true);
}

VDRPLUGINCREATOR(cPluginSnapshot); // Don't touch this!

// cStatus

void cPluginSnapshot::ChannelSwitch(const cDevice *Device, int ChannelNumber) 
{
  if(cDevice::PrimaryDevice() == Device && ChannelNumber > 0) {
    m_Current[0] = 0;
    if(Channels.GetByNumber(ChannelNumber)->Name()) {
      strn0cpy(m_Current, Channels.GetByNumber(ChannelNumber)->Name(), sizeof(m_Current));
      if(strchr(m_Current, ';'))
	*strchr(m_Current, ';') = 0;
    }
  }
}

void cPluginSnapshot:: Replaying(const cControl *Control, const char *Name, 
				 const char *FileName, bool On) 
{
  if(On && Name)
    strn0cpy(m_Current, Name, sizeof(m_Current));
  else
    m_Current[0] = 0;
}



// --------------- Setup menu -------------------

const char *sImageFormats[] =
  {"PNM", "JPEG", NULL};

static inline const char * int_to_str(int i)
{
  static char buf[64];
  sprintf(buf, "%d", i);
  return buf;
}

void cMenuSetupSnapshot::Store(void)
{
  m_Plugin->SetupParse("HideMainMenuEntry", int_to_str(m_HideMainMenuEntry ? 0 : 1));
  m_Plugin->SetupParse("Jpeg", int_to_str(m_Jpeg));
  m_Plugin->SetupParse("Quality", int_to_str(m_Quality));
  m_Plugin->SetupParse("SizeX", int_to_str(m_SizeX));
  m_Plugin->SetupParse("SizeY", int_to_str(m_SizeY));
  m_Plugin->SetupParse("DestDir", m_DestDir);
  m_Plugin->SaveSetup();
}

cMenuSetupSnapshot::cMenuSetupSnapshot(cPluginSnapshot *Plugin)
{
  m_Plugin = Plugin;

  m_HideMainMenuEntry = m_Plugin->m_HideMainMenuEntry ? 0 : 1;
  m_Jpeg    = m_Plugin->m_Jpeg ? 1 : 0;
  m_Quality = m_Plugin->m_Quality;
  m_SizeX   = m_Plugin->m_SizeX;
  m_SizeY   = m_Plugin->m_SizeY;
  strcpy(m_DestDir, m_Plugin->m_DestDir);

  Add(new cMenuEditBoolItem(tr("Show in main menu"),     
			    &m_HideMainMenuEntry));
  Add(new cMenuEditStrItem( tr("Save snapshots to"),        
			    m_DestDir, 255, FileNameChars));
  Add(new cMenuEditStraItem(tr("Image format"),             
			    &m_Jpeg,     2, sImageFormats));
  Add(new cMenuEditIntItem( tr("Jpeg compression quality"), 
			    &m_Quality, -1, 0xff));
  Add(new cMenuEditIntItem( tr("Image width"),              
			    &m_SizeX,    1, 2048));
  Add(new cMenuEditIntItem( tr("Image height"),             
			    &m_SizeY,    1, 2048));
}



