/*
 * Analogue TV Player plugin for VDR
 *
 * Copyright (C) 2003, 2005 Andreas Kool <akool@gmx.de>
 *
 * This code is distributed under the terms and conditions of the
 * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details.
 *
 * Version: $Id: menusetup.c,v 1.80 2005/01/09 18:16:09 akool Exp $
 * Release: $Name:  $
 *
 */

#include "menusetup.h"

#include "player-analogtv.h"
#include "i18n.h"
#include "status.h"
#include "analogtv.h"
#include "pvr.h"

static void putOffset(char *ID, int offset)
{
  register char *p;

  d(3, "putOffset()");

  if ((p = strstr(s.finetune, ID))) {
    if ((p = strchr(p, '='))) {
      sprintf(p + 1, "%02d", offset);
      *(p + 3) = '|';
    }
  }
  else
    sprintf(s.finetune + strlen(s.finetune), "%s=%02d|", ID, offset);
}

static cOsdItem *b1, *b2, *b3, *b4, *b5;

static const char *Color[] =
{
  "[                                  ]",
  "[|                                 ]",
  "[||                                ]",
  "[|||                               ]",
  "[||||                              ]",
  "[|||||                             ]",
  "[||||||                            ]",
  "[|||||||                           ]",
  "[||||||||                          ]",
  "[|||||||||                         ]",
  "[||||||||||                        ]",
  "[|||||||||||                       ]",
  "[||||||||||||                      ]",
  "[|||||||||||||                     ]",
  "[||||||||||||||                    ]",
  "[|||||||||||||||                   ]",
  "[||||||||||||||||                  ]",
  "[|||||||||||||||||                 ]",
  "[||||||||||||||||||                ]",
  "[|||||||||||||||||||               ]",
  "[||||||||||||||||||||              ]",
  "[|||||||||||||||||||||             ]",
  "[||||||||||||||||||||||            ]",
  "[|||||||||||||||||||||||           ]",
  "[||||||||||||||||||||||||          ]",
  "[|||||||||||||||||||||||||         ]",
  "[||||||||||||||||||||||||||        ]",
  "[|||||||||||||||||||||||||||       ]",
  "[||||||||||||||||||||||||||||      ]",
  "[|||||||||||||||||||||||||||||     ]",
  "[||||||||||||||||||||||||||||||    ]",
  "[|||||||||||||||||||||||||||||||   ]",
  "[||||||||||||||||||||||||||||||||  ]",
  "[||||||||||||||||||||||||||||||||| ]",
  "[||||||||||||||||||||||||||||||||||]"
};

static const char *Tuning[] =
{
  "[|...............+................]",
  "[.|..............+................]",
  "[..|.............+................]",
  "[...|............+................]",
  "[....|...........+................]",
  "[.....|..........+................]",
  "[......|.........+................]",
  "[.......|........+................]",
  "[........|.......+................]",
  "[.........|......+................]",
  "[..........|.....+................]",
  "[...........|....+................]",
  "[............|...+................]",
  "[.............|..+................]",
  "[..............|.+................]",
  "[...............|+................]",
  "[................|................]",
  "[................+|...............]",
  "[................+.|..............]",
  "[................+..|.............]",
  "[................+...|............]",
  "[................+....|...........]",
  "[................+.....|..........]",
  "[................+......|.........]",
  "[................+.......|........]",
  "[................+........|.......]",
  "[................+.........|......]",
  "[................+..........|.....]",
  "[................+...........|....]",
  "[................+............|...]",
  "[................+.............|..]",
  "[................+..............|.]",
  "[................+...............|]" 
};

cMenuSetupAnalogtv::cMenuSetupAnalogtv(cPluginAnalogtv *PluginAnalogtv) :
   PluginAnalogtv(PluginAnalogtv)
{
  static const char  allowed[] = { "abcdefghijklmnopqrstuvwxyz0123456789-_/:" };
  auto         char  t[64];
  auto   const char *NO = tr("Setup.analogTV$No"), *YES = tr("Setup.analogTV$Yes");

  d(3, "cMenuSetupAnalogtv::cMenuSetupAnalogtv()");

  sx = s;
  xfreqOffset = freqOffset;

  Clear();
  SetSection(tr("Setup.analogTV$analogTV"));

  if (EncoderNeeded) {
    AddNewCategory(tr("Setup.analogTV$Picture Properties"));

    Add(b1 = new cMenuEditStraItem(tr("Setup.analogTV$Brightness"),        &sx.brightness, ENTRIES(Color), Color));
    Add(b2 = new cMenuEditStraItem(tr("Setup.analogTV$Contrast"),          &sx.contrast, ENTRIES(Color), Color));
    Add(b3 = new cMenuEditStraItem(tr("Setup.analogTV$Colour"),            &sx.colour, ENTRIES(Color), Color));
    Add(b4 = new cMenuEditStraItem(tr("Setup.analogTV$Hue"),               &sx.hue, ENTRIES(Color), Color));

    Add(b5 = new cMenuEditStraItem(tr("Setup.analogTV$Finetune"),          &xfreqOffset, ENTRIES(Tuning), Tuning));
  }

  AddNewCategory(tr("Setup.analogTV$EPG"));
#if 0 // this only confuses the user ...
  Add(new cOsdItem(         tr("Setup.analogTV$Load EPG now"),           osUser1));
#endif
  Add(new cMenuEditStraItem(tr("Setup.analogTV$EPG from"),               &sx.epg_source, 3, epgsources));
  Add(new cMenuEditStrItem( tr("Setup.analogTV$External program"),       sx.epg_external, MAX_DEV_NAME, allowed));
  Add(new cMenuEditStrItem( tr("Setup.analogTV$EPG provider"),           sx.epg_provider, 4, allowed));
  Add(new cMenuEditIntItem( tr("Setup.analogTV$Autoupdate (hours)"),     &sx.epg_autoupdate, 0, 96));
  if (sx.epg_source < 2) // hoerzu2vdr does not support this
    Add(new cMenuEditStraItem(tr("Setup.analogTV$Theme language"),       &sx.epg_language, 4, languages));

  AddNewCategory(tr("Setup.analogTV$MPEG Encoder"));
  
#if 0 // this only confuses the user ...
  if (EncoderRunning)
    Add(new cOsdItem(       tr("Setup.analogTV$Restart encoder"),        osUser2));

  if (EncoderRunning && !EncoderNeeded)
    Add(new cOsdItem(       tr("Setup.analogTV$Stop encoder"),           osUser3));
#endif

  if (!EncoderNeeded) // sorry, but its too complex at the moment to flip the encoder while running ...
    Add(new cMenuEditStraItem(tr("Setup.analogTV$Encoder"), &sx.mpeg_encoder, 11, encoders));

  Add(new cMenuEditIntItem( tr("Setup.analogTV$Video bit rate (Mbit/s)/100000"), &sx.video_bit_rate, 1, 80));
  Add(new cMenuEditIntItem( tr("Setup.analogTV$Audio bit rate (kbit/s)"),        &sx.audio_bit_rate, 0, 512));
  Add(new cMenuEditStraItem(tr("Setup.analogTV$Image size"),                     &sx.image_size, 6, imagesizes));
  Add(new cMenuEditIntItem( tr("Setup.analogTV$Audio volume"),                   &sx.mixer_volume, 0, 100));

  if (isPVRx) {
#if 0 //XXX Sorry people, this was only a _test_ ... it never worked as expected!
    Add(new cMenuEditBoolItem(tr("Setup.analogTV$Use PVR350 TV-out"),            &sx.usePVR350, NO, YES));
#endif
    Add(new cMenuEditIntItem( tr("Setup.analogTV$GOP size"),                     &sx.framespergop, 0, 25));
    Add(new cMenuEditIntItem( tr("Setup.analogTV$B frames"),                     &sx.bframes, 0, 25));
    Add(new cMenuEditStraItem(tr("Setup.analogTV$GOP"),                          &sx.gop_closure, 2, closures));
    Add(new cMenuEditStraItem(tr("Setup.analogTV$Noise removal filter"),         &sx.dnr_mode, 4, dnr_modes));
    Add(new cMenuEditIntItem( tr("Setup.analogTV$Spatial"),                      &sx.dnr_spatial, 0, 16));
    Add(new cMenuEditIntItem( tr("Setup.analogTV$Temporal"),                     &sx.dnr_temporal, 0, 16));
    Add(new cMenuEditIntItem( tr("Setup.analogTV$Type"),                         &sx.dnr_type, 0, 16));
    Add(new cMenuEditStraItem(tr("Setup.analogTV$Bitrate mode"),                 &sx.bitrate_mode, 2, bitratemodes));
    Add(new cMenuEditStraItem(tr("Setup.analogTV$Aspect"),                 	 &sx.aspect, 4, aspects));
    Add(new cMenuEditStraItem(tr("Setup.analogTV$3:2 pulldown"),                 &sx.pulldown, 2, pulldowns));
    Add(new cMenuEditStraItem(tr("Setup.analogTV$On the fly remux"),         	 &sx.remux, 3, remuxes));
    
    AddNewCategory(tr("Setup.analogTV$Hacks"));
    Add(new cMenuEditBoolItem(tr("Setup.analogTV$sync hack"),                    &sx.syncHack, NO, YES));
    Add(new cMenuEditBoolItem(tr("Setup.analogTV$wining hack"),                  &sx.winingHack, NO, YES));
    Add(new cMenuEditBoolItem(tr("Setup.analogTV$picture properties hack"),      &sx.propHack, NO, YES));
    Add(new cMenuEditBoolItem(tr("Setup.analogTV$stuttering hack"),      	 &sx.stutteringHack, NO, YES));
  }
  else {
    Add(new cMenuEditBoolItem(tr("Setup.analogTV$Clipping"),                     &sx.clipping, NO, YES));
    Add(new cMenuEditStraItem(tr("Setup.analogTV$GOP sequence"),                 &sx.gop, 3, gops));
    Add(new cMenuEditStraItem(tr("Setup.analogTV$Filter"),                       &sx.filter, 11, filters));
    Add(new cMenuEditIntItem( tr("Setup.analogTV$Motion compensation min"),      &sx.motion[0], 0, 64));
    Add(new cMenuEditIntItem( tr("Setup.analogTV$Motion compensation max"),      &sx.motion[1], 0, 64));
    Add(new cMenuEditBoolItem(tr("Setup.analogTV$Deinterlacing"),                &sx.deinterlace, NO, YES));

  //mpeg-2 mux out of order ...
  //Add(new cMenuEditBoolItem(tr("Setup.analogTV$MPEG"),                         &sx.mpeg, "1", "2"));
    Add(new cMenuEditStraItem(tr("Setup.analogTV$Test"),                         &sx.test, 11, tests));
    Add(new cMenuEditBoolItem(tr("Setup.analogTV$Link to encoder"),              &sx.link, tr("Setup.analogTV$read()"), tr("Setup.analogTV$select()")));
    Add(new cMenuEditBoolItem(tr("Setup.analogTV$Encoder always running"),       &sx.EncoderAlwaysUp, NO, YES));

    AddNewCategory(tr("Setup.analogTV$Audiodevice"));
    Add(new cMenuEditStrItem( tr("Setup.analogTV$PCM device"),                   sx.audio_device, MAX_DEV_NAME, allowed));
    Add(new cMenuEditStrItem( tr("Setup.analogTV$OSS Mixer device"),             sx.mixer_device, MAX_DEV_NAME, allowed));
    Add(new cMenuEditStraItem(tr("Setup.analogTV$OSS Mixer input"),              &sx.mixer_line, SOUND_MIXER_NRDEVICES, SoundDevices));
    Add(new cMenuEditStraItem(tr("Setup.analogTV$Audio mode"),                   &sx.audio_mode, 4, audiomodes));
    Add(new cMenuEditStraItem(tr("Setup.analogTV$Audio sample rate"),            &sx.sample_rate, 5, samplerates));
    Add(new cMenuEditStraItem(tr("Setup.analogTV$Psychoacoustic analysis"),      &sx.analysis, 3, analysismodes));
  }

  AddNewCategory(tr("Setup.analogTV$Various"));
  Add(new cMenuEditStraItem(tr("Setup.analogTV$Profile"),                        &sx.profile, 7, profiles));
  Add(new cMenuEditIntItem( tr("Setup.analogTV$Debug level"),                    &sx.debug,  0, 9));
  Add(new cMenuEditStraItem(tr("Setup.analogTV$Debug output"),                   &sx.logger, 4, loggers));
  Add(new cMenuEditBoolItem(tr("Setup.analogTV$Report"),                         &sx.report, NO, YES));
  Add(new cMenuEditBoolItem(tr("Setup.analogTV$Hide Mainmenu Entry"),            &sx.HideMainMenu, NO, YES));
#if 0 // this only confuses the user ...
  Add(new cOsdItem(         tr("Setup.analogTV$Reset"),                          osUser4));
#endif
  AddNewCategory(tr("Setup.analogTV$DigiBox control"));
  Add(new cMenuEditStraItem(tr("Setup.analogTV$Digibox Mode"), 			 &sx.enabledigibox, 4, digiboxmodes));
  Add(new cMenuEditStrItem( tr("Setup.analogTV$Redremote Device"), 		 sx.redremote_device, (int)sizeof(sx.redremote_device), tr(FileNameChars)));
  Add(new cMenuEditBoolItem(tr("Setup.analogTV$Backup Hack"), 			 &sx.backupHack, NO, YES));
  Add(new cMenuEditIntItem( tr("Setup.analogTV$Backup Interval"), 		 &sx.backupInterval, 1, 3600));
  Add(new cMenuEditBoolItem(tr("Setup.analogTV$Fast Channel Change"), 		 &sx.fastdigibox_change, NO, YES));

  AddNewCategory(           tr("Setup.analogTV$Internals"));
  Add(Item(                 tr("Setup.analogTV$[Video source]"),    (videosource == -1) ? tr("Setup.analogTV$Unknown") : sources[videosource]));
  if (!isPVRx)
    Add(Item(               tr("Setup.analogTV$[Encoder running]"), EncoderRunning ? YES : NO));
  Add(Item(                 tr("Setup.analogTV$[Encoder needed]"),  EncoderNeeded ?  YES : NO));
  
  if (frequency == -1)
    sprintf(t, "%s", tr("Setup.analogTV$Unknown"));
  else
    sprintf(t, "%d + %d = %d", frequency, (xfreqOffset - 16) * FREQDELTA, frequency + (xfreqOffset - 16) * FREQDELTA);
  Add(Item(                 tr("Setup.analogTV$[Frequency]"),       t));

  sprintf(t, "%d 0x%04x %.1f%%", sx.brightness, (int)(sx.brightness * 1927.5), (sx.brightness / 34.0 * 100.0));
  Add(Item(                 tr("Setup.analogTV$[Brightness]"),      t));
  
  sprintf(t, "%d 0x%04x %.1f%%", sx.contrast, (int)(sx.contrast * 1927.5), (sx.contrast / 34.0 * 100.0));
  Add(Item(                 tr("Setup.analogTV$[Contrast]"),        t));
  
  sprintf(t, "%d 0x%04x %.1f%%", sx.colour, (int)(sx.colour * 1927.5), (sx.colour / 34.0 * 100.0));
  Add(Item(                 tr("Setup.analogTV$[Colour]"),          t));
  
  sprintf(t, "%d 0x%04x %.1f%%", sx.hue, (int)(sx.hue * 1927.5), (sx.hue / 34.0 * 100.0));
  Add(Item(                 tr("Setup.analogTV$[Hue]"),             t));

  Add(Item(                 tr("Setup.analogTV$[CPU]"),             CPU));
  Add(Item(                 tr("Setup.analogTV$[Speed (MHz)]"),     CPUspeed));
  Add(Item(                 tr("Setup.analogTV$[memcpy() method]"), memcpys[sx.memcpy_method]));
  if (sx.clipping && !isPVRx)
    Add(Item(               tr("Setup.analogTV$[Grab size]"),       grabsizes[sx.image_size]));

  SetHelp(                                     tr("Setup.analogTV$Load EPG now"),
          ReaderLoopRunning                  ? tr("Setup.analogTV$Restart")      : NULL,
          (EncoderRunning && !EncoderNeeded) ? tr("Setup.analogTV$Stop encoder") : NULL,
                                               tr("Setup.analogTV$Reset"));

  SetCurrent(Get(1));
}

void cMenuSetupAnalogtv::AddNewCategory(const char* title)
{
  char *buffer = NULL;

  d(5, "cMenuSetupAnalogtv::AddNewCategory()");

  asprintf(&buffer, "--- %s ----------------------------------------------------------------", title );

  cOsdItem *item = new cOsdItem(buffer);
  free(buffer);

#if VDRVERSNUM < 10307
#ifdef HAVE_BEAUTYPATCH
  item->SetColor(clrScrolLine, clrBackground);
#else
  item->SetColor(clrCyan, clrBackground);
#endif
#endif

  Add(item);
}

cOsdItem *cMenuSetupAnalogtv::Item(const char *name, const int num)
{
  auto char buf[32];

  d(5, "cMenuSetupAnalogtv::Item(%d) int", num);

  snprintf(buf, sizeof(buf), "%d", num);
  return Item(name, buf);
}

cOsdItem *cMenuSetupAnalogtv::Item(const char *name, const double num)
{
  auto char buf[32];

  d(5, "cMenuSetupAnalogtv::Item(%.3f) double", num);

  snprintf(buf, sizeof(buf), "%.3f", num);
  return Item(name, buf);
}

cOsdItem *cMenuSetupAnalogtv::Item(const char *name, const char *text)
{
  char *buffer = NULL;

  d(5, "cMenuSetupAnalogtv::Item(%s) text", text);

  asprintf(&buffer, "%s:\t%s", name, text);

  cOsdItem *item = new cOsdItem(buffer, osBack);

#if VDRVERSNUM < 10307
  item->SetColor(clrWhite, clrBackground);
#endif

  free(buffer);

  return item;
}

void cMenuSetupAnalogtv::PictureProperties(void)
{
  d(3, "cMenuSetupAnalogtv::PictureProperties()");

  if (isPVRx)
    setPVR(CONTROL, -1, -1, -1, -1, sx.brightness, sx.contrast, sx.colour, sx.hue);
  else {
    setPictureProperties(sx.brightness, sx.contrast, sx.colour, sx.hue);

    if (v4l == 1)
      Restart = 1;
  }
}

void cMenuSetupAnalogtv::Finetuning()
{
  d(3, "cMenuSetupAnalogtv::Finetuning()");

  if (frequency) { // only "television" have a tuner
    if (isPVRx)
      setPVR(FREQUENCY, -1, frequency, xfreqOffset, -1, -1, -1, -1, -1);
    else {
      tune(frequency, xfreqOffset);
      
      if (v4l == 1)
        Restart = 1;
    }
  }
}

static bool check(int *cur, int ofs, int max)
{
  if (ofs == -1) {
    if (*cur > 0) {
      *cur -= 1;
      return true;
    }
  }
  else {
    if (*cur < max) {
      *cur += 1;
      return true;
    }
  } 
  
  return false; 
}

eOSState cMenuSetupAnalogtv::ProcessKey(eKeys Key)
{
  cOsdItem *item = Get(Current());
  int       val  = 0;

  d(5, "cMenuSetupAnalogtv::ProcessKey()");

  switch (Key) {
    case kLeft     : val = -1;  break;
    case kRight    : val = +1;  break;
    case k0 ... k9 : val = Key; break; 
    default        : val = 0;   break;
  }

  if (val) {
    if (item == b1) {
      if (check(&sx.brightness, val, 34))
        PictureProperties();
      return osContinue;
    }
    else if (item == b2) {
      if (check(&sx.contrast, val, 34))
        PictureProperties();
      return osContinue;
    }
    else if (item == b3) {
      if (check(&sx.colour, val, 34))
        PictureProperties();
      return osContinue;
    }
    else if (item == b4) {
      if (check(&sx.hue, val, 34))
        PictureProperties();
      return osContinue;
    }
    else if (item == b5) {
      switch (val) {
        case k1 : xfreqOffset =  0;
                  Finetuning();
                  break;

        case k9 : xfreqOffset = 32;
                  Finetuning();
                  break;

        case k0 : xfreqOffset = 16;
                  Finetuning();
                  break;

        default : if (val && check(&xfreqOffset, val, 32))
                    Finetuning();
                  break; 
      }
      return osContinue;
    }
    else if (isPVRx && EncoderNeeded) {
      d(1, "setPVR()");

      sy = s;
      s = sx;
      setPVR((PVRencoderSettingsChanged()         ? CODEC  : 0) |
             ((s.image_size != sc.image_size)     ? FORMAT : 0) |
             ((s.mixer_volume != sc.mixer_volume) ? VOLUME : 0),
             -1, -1, -1, -1, -1, -1, -1, -1);
      s = sy;
    }
  }

  eOSState state = cOsdMenu::ProcessKey(Key);

  switch (Key) {
    case kRed    : state = osUser1;
                   break; 

    case kGreen  : state = osUser2;
                   break; 

    case kYellow : state = osUser3;
                   break; 

    case kBlue   : state = osUser4;
                   break; 
    
    default      : break;
  }

  switch (state) {
    case osUnknown : if (Key == kOk) {
                       Store();
                       
                       if (isPVR && EncoderNeeded) {
                         
                         if (s.mpeg_encoder != sc.mpeg_encoder)
#if VDRVERSNUM >= 10307
                           Skins.Message(mtError, tr("Setup.analogTV$Cannot change encoder now!"));
#else
                           Interface->Error(tr("Setup.analogTV$Cannot change encoder now!"));
#endif

                         if (s.image_size != sc.image_size)
#if VDRVERSNUM >= 10307
                           Skins.Message(mtError, tr("Setup.analogTV$Cannot change image size now!"));
#else
                           Interface->Error(tr("Setup.analogTV$Cannot change image size now!"));
#endif

                         setPVR((PVRencoderSettingsChanged()         ? CODEC     : 0) |
                                ((s.image_size != sc.image_size)     ? FORMAT    : 0) |
                                ((s.mixer_volume != sc.mixer_volume) ? VOLUME    : 0),
                                -1, -1, -1, -1, -1, -1, -1, -1);
                       }
                       state = osBack;
                     }
                     break;

    case osUser1   : state = osContinue;

                     AnalogtvEPGhandler = new cAnalogtvEPGhandler;

                     if (!AnalogtvEPGhandler->Process())
#if VDRVERSNUM >= 10307
                       Skins.Message(mtError, tr("Setup.analogTV$Loading of EPG failed"));
#else
                       Interface->Error(tr("Setup.analogTV$Loading of EPG failed"));
#endif
                     else
                       epg_update = time((time_t)NULL);

                     delete AnalogtvEPGhandler;
                     AnalogtvEPGhandler = NULL;
                     state = osEnd;
                     break;

    case osUser2   : state = osContinue;

                     if (ReaderLoopRunning) {
                       Restart = 1;
                       state = osEnd;
                     }
                     else
#if VDRVERSNUM >= 10307
                       Skins.Message(mtError, tr("Setup.analogTV$Encoder does not run!"));
#else
                       Interface->Error(tr("Setup.analogTV$Encoder does not run!"));
#endif
                     break;

    case osUser3   : state = osContinue;

                     if (EncoderRunning) {
                       if (!EncoderNeeded) {
#if VDRVERSNUM >= 10307
                         if (1) { // FIXME
#else
                         if (Interface->Confirm(tr("Setup.analogTV$Really stop encoder?"))) {
#endif
                           d(2, "Shutting down encoder, not needed at the moment");

                           PluginAnalogtv->StopEncoder();

                           state = osEnd;
                         }
                       }
                       else
#if VDRVERSNUM >= 10307
                         Skins.Message(mtError, tr("Setup.analogTV$Cannot stop encoder now!"));
#else
                         Interface->Error(tr("Setup.analogTV$Cannot stop encoder now!"));
#endif
                     }
                     else
#if VDRVERSNUM >= 10307
                       Skins.Message(mtError, tr("Setup.analogTV$Encoder does not run!"));
#else
                       Interface->Error(tr("Setup.analogTV$Encoder does not run!"));
#endif
                     break;

    case osUser4   : state = osContinue;
#if VDRVERSNUM >= 10307
                     if (1) { // FIXME
#else
                     if (Interface->Confirm(tr("Setup.analogTV$Really reset analogTV plugin?"))) {
#endif
                       EncoderRunning = EncoderNeeded = 0;
                       state = osEnd;
                     }
                     break;

    case osBack    : d(1, "[Back] pressed, undoing all changes");
                     if (xfreqOffset != freqOffset) {
                       xfreqOffset = freqOffset;
                       Finetuning();
                     }

                     if ((sx.brightness != s.brightness) ||
                         (sx.contrast   != s.contrast  ) ||
                         (sx.colour     != s.colour    ) || 
                         (sx.hue        != s.hue       )) {
                       
                       sx.brightness = s.brightness;
                       sx.contrast   = s.contrast;
                       sx.colour     = s.colour;
                       sx.hue        = s.hue;
                       
                       PictureProperties();
                     }
                     break; 

    default        : break;
  }

  return state;
}

static char *cite(char *s)
{
  static char sx[1024];
  
  sprintf(sx, "\"%s", s);
  return sx;
}

void cMenuSetupAnalogtv::Store(void)
{
  d(3, "cMenuSetupAnalogtv::Store()");

  s = sx;
   
  SetupStore("debug",            s.debug);
  SetupStore("Logger",           s.logger);
  SetupStore("Report",           s.report);
  SetupStore("Encoder",          s.mpeg_encoder);
  SetupStore("PCMdevice",        cite(s.audio_device));
  SetupStore("MixerDevice",      cite(s.mixer_device));
  SetupStore("MixerInput",       s.mixer_line);
  SetupStore("MixerVolume",      s.mixer_volume);
  SetupStore("Videobitrate",     s.video_bit_rate);
  SetupStore("AudioBitRate",     s.audio_bit_rate);
  SetupStore("ImageSize",        s.image_size);
  SetupStore("Clipping",         s.clipping);
  SetupStore("GOP",              s.gop);
  SetupStore("Filter",           s.filter);
  SetupStore("MotionMin",        s.motion[0]);
  SetupStore("MotionMax",        s.motion[1]);
  SetupStore("Deinterlace",      s.deinterlace);
  SetupStore("Profile",          s.profile);
  SetupStore("MPEG",             s.mpeg);
  SetupStore("Test",             s.test);
  SetupStore("AudioMode",        s.audio_mode);
  SetupStore("SampleRate",       s.sample_rate);
  SetupStore("PsychoAnalysis",   s.analysis);
  SetupStore("Brightness",       s.brightness);
  SetupStore("Hue",              s.hue);
  SetupStore("Colour",           s.colour);
  SetupStore("Contrast",         s.contrast);
  SetupStore("HideMainMenu",     s.HideMainMenu);
  
  if (xfreqOffset != freqOffset) {
    freqOffset = xfreqOffset;
    putOffset(ID, freqOffset);
  }
  
  SetupStore("Finetune",         cite(s.finetune));
  SetupStore("EncoderAlwaysUp",  s.EncoderAlwaysUp);
  SetupStore("Link",             s.link);
  SetupStore("MemcpyMethod",     s.memcpy_method);
  SetupStore("EPGfrom",          s.epg_source);
  SetupStore("External",         cite(s.epg_external));
  SetupStore("EPGprovider",      cite(s.epg_provider));
  SetupStore("AutoUpdate",       s.epg_autoupdate);
  SetupStore("ThemeLanguage",    s.epg_language);

  SetupStore("FramesPerGOP",     s.framespergop);
  SetupStore("Bframes",          s.bframes);
  SetupStore("GOPclosure",       s.gop_closure);
  SetupStore("DNRmode",          s.dnr_mode);
  SetupStore("DNRspatial",       s.dnr_spatial);
  SetupStore("DNRtemporal",      s.dnr_temporal);
  SetupStore("DNRtype",          s.dnr_type);
  SetupStore("BitrateMode",      s.bitrate_mode);
  SetupStore("Aspect",      	 s.aspect);
  SetupStore("Pulldown",      	 s.pulldown);
    
  SetupStore("SyncHack",         s.syncHack);
  SetupStore("WiningHack",       s.winingHack);
  SetupStore("avSyncHack",       s.avHack);
  SetupStore("ppHack",           s.propHack);
  SetupStore("StutteringHack",   s.stutteringHack);
  SetupStore("Remux",   	 s.remux);
  SetupStore("usePVR350",   	 s.usePVR350);

  SetupStore("EnableDigibox",    s.enabledigibox);
  SetupStore("RedRemoteDevice",  s.redremote_device);
  SetupStore("backupHack",	 s.backupHack);
  SetupStore("FastDigiboxChange",s.fastdigibox_change);
  
  // remove old entries
  SetupStore("DontStopEnc");
  SetupStore("avSyncHack");
}
