Logo Search packages:      
Sourcecode: vdr-plugin-xineliboutput version File versions  Download package

menu.c

/*
 * menu.c: Main Menu
 *
 * See the main source file 'xineliboutput.c' for copyright information and
 * how to reach the author.
 *
 * $Id: menu.c,v 1.35 2007/05/17 13:36:40 phintuka Exp $
 *
 */

#include <dirent.h>

#include <vdr/config.h>
#include <vdr/i18n.h>
#include <vdr/interface.h>
#include <vdr/menu.h>
#include <vdr/plugin.h>
#include <vdr/videodir.h>

#include "logdefs.h"
#include "config.h"
#include "menu.h"
#include "menuitems.h"
#include "device.h"
#include "media_player.h"
#include "equalizer.h"

#ifndef HOTKEY_START
# define HOTKEY_START        kRed

# define HOTKEY_DVD          k0    /* */
# define HOTKEY_DVD_TRACK1   k1    /* */
# define HOTKEY_DVD_SPU      k2    /* */

# define HOTKEY_NEXT_ASPECT  k3    /* auto, 4:3, 16:9 */
# define HOTKEY_TOGGLE_CROP  k4    /* off, force, auto */
# define HOTKEY_UPMIX        k5    /* off, on */
# define HOTKEY_DOWNMIX      k6    /* off, on */
# define HOTKEY_DEINTERLACE  k7    /* off, on */
# define HOTKEY_LOCAL_FE     k8    /* off, on */

# define HOTKEY_PLAYLIST     k9    /* Start replaying playlist or file pointed by
                              symlink $(CONFDIR)/plugins/xineliboutput/default_playlist */
#endif

//#define OLD_SPU_MENU
//#define OLD_TOGGLE_FE

#define ISNUMBERKEY(k) (RAWKEY(k) >= k0 && RAWKEY(k) <= k9)

//--------------------------- cMenuBrowseFiles -------------------------------

class cMenuBrowseFiles : public cOsdMenu 
{
  protected:
    eMainMenuMode m_Mode;
    bool          m_OnlyQueue;
    char         *m_CurrentDir;
    char         *m_ConfigLastDir;

    virtual bool ScanDir(const char *DirName);
    virtual eOSState Open(bool ForceOpen = false, bool Parent = false, bool Queue = false);
    virtual eOSState Delete(void);
    virtual eOSState Info(void);
    virtual void Set(void);
    virtual void SetHelpButtons(void);
    cFileListItem *GetCurrent() { return (cFileListItem *)Get(Current()); }
    void StoreConfig(void);
    char *GetLastDir(void);

  public:
    cMenuBrowseFiles(eMainMenuMode mode = ShowFiles, bool OnlyQueue=false);
    ~cMenuBrowseFiles();

    virtual eOSState ProcessKey(eKeys Key);
};

static char *ParentDir(const char *dir)
{
  char *result = strdup(dir);
  char *pt = strrchr(result, '/');
  if(pt) {
    *(pt+1)=0;
    if(pt != result)
      *pt = 0;
  }
  return result;
}

static char *LastDir(const char *dir)
{
  char *pt = strrchr(dir, '/');
  if(pt && pt[0] && pt[1])
    return strdup(pt+1);
  return NULL;
}

cMenuBrowseFiles::cMenuBrowseFiles(eMainMenuMode mode, bool OnlyQueue) :
    cOsdMenu( ( mode==ShowImages ? tr("Images") :
            mode==ShowMusic ? (!OnlyQueue ? tr("Play music") : tr("Add to playlist")) :
            /*mode==ShowFiles ?*/ tr("Play file")),
            2, 4)
{
  m_CurrentDir = NULL;
  m_Mode       = mode;
  m_OnlyQueue  = OnlyQueue;

  m_ConfigLastDir = GetLastDir();
  Set();
}

cMenuBrowseFiles::~cMenuBrowseFiles()
{
  Setup.Save();
  free(m_CurrentDir);
}

char *cMenuBrowseFiles::GetLastDir(void)
{
  switch(m_Mode) {
    case ShowMusic:  return xc.browse_music_dir;
    case ShowImages: return xc.browse_images_dir;
    default:
    case ShowFiles:  return xc.browse_files_dir;
  }
  return xc.browse_files_dir;
}

void cMenuBrowseFiles::Set(void)
{
  Clear();

  if(!m_CurrentDir) 
    m_CurrentDir = strdup(m_ConfigLastDir);

  if(m_CurrentDir[0] != '/') {
    free(m_CurrentDir);
    m_CurrentDir = strdup(VideoDirectory);
  }

  // find deepest accessible directory from path
  while(!ScanDir(m_CurrentDir) && strlen(m_CurrentDir) > 1) {
    char *n = ParentDir(m_CurrentDir);
    free(m_CurrentDir);
    m_CurrentDir = n;
  }

  // add link to parent folder
  if(strlen(m_CurrentDir) > 1)
    Add(new cFileListItem("..",true));

  Sort();

  SetCurrent(Get(Count()>1 && strlen(m_CurrentDir)>1 ? 1 : 0));

  // select last selected item

  char *lastParent = ParentDir(m_ConfigLastDir);
  if(!strncmp(m_CurrentDir,lastParent,strlen(m_CurrentDir))) {
    char *item = LastDir(m_ConfigLastDir);
    if(item) {
      for(cFileListItem *it = (cFileListItem*)First(); it; it = (cFileListItem*)Next(it))
      if(!strcmp(it->Name(),item))
        SetCurrent(it);
      free(item);
    }
  }
  free(lastParent);

  strn0cpy(m_ConfigLastDir, m_CurrentDir, sizeof(xc.browse_files_dir));
  StoreConfig();

  SetHelpButtons();
}

void cMenuBrowseFiles::StoreConfig(void)
{
  cPluginManager::GetPlugin(PLUGIN_NAME_I18N)->SetupStore("Media.BrowseMusicDir",  
                                            xc.browse_music_dir);
  cPluginManager::GetPlugin(PLUGIN_NAME_I18N)->SetupStore("Media.BrowseFilesDir",  
                                            xc.browse_files_dir);
  cPluginManager::GetPlugin(PLUGIN_NAME_I18N)->SetupStore("Media.BrowseImagesDir", 
                                            xc.browse_images_dir);
#if 1
  cPluginManager::GetPlugin(PLUGIN_NAME_I18N)->SetupStore("Media.CacheImplicitPlaylists", 
                                            xc.cache_implicit_playlists);
  cPluginManager::GetPlugin(PLUGIN_NAME_I18N)->SetupStore("Media.EnableID3Scanner", 
                                            xc.enable_id3_scanner);
#endif
}

void cMenuBrowseFiles::SetHelpButtons(void)
{
  bool isDir = !GetCurrent() || GetCurrent()->IsDir();
  bool isDvd = GetCurrent() && GetCurrent()->IsDvd();
  SetHelp((isDir && isDvd) ? tr("Button$Open") : !m_OnlyQueue ? tr("Button$Play"): NULL,
        (m_Mode == ShowMusic) ? tr("Button$Queue") : 
                 strlen(m_CurrentDir)>1 ? "[..]" : NULL,
        (isDir && !isDvd) ? NULL : tr("Button$Delete"),
        isDir ? NULL : tr("Button$Info"));
  Display();
}

eOSState cMenuBrowseFiles::Delete(void)
{
  cFileListItem *it = GetCurrent();
  if(!it->IsDir()) {
    if (Interface->Confirm(tr("Delete recording?"))) {
      cString name = cString::sprintf("%s/%s", m_CurrentDir, it->Name());
      if(!unlink(name)) {
        isyslog("file %s deleted", *name);
      if(m_Mode != ShowImages) {
        name = cString::sprintf("%s.resume", *name);
        unlink(name);
      }
        cOsdMenu::Del(Current());
      SetHelpButtons();
        Display();
      } else {
        Skins.Message(mtError, tr("Error while deleting recording!"));
        isyslog("Error deleting file %s", *name);
      }
    }
  }
  return osContinue;
}

eOSState cMenuBrowseFiles::Open(bool ForceOpen, bool Parent, bool Queue)
{
  if(!GetCurrent()) {
    return osContinue;
  }

  /* parent directory */
  if(Parent || !strcmp("..", GetCurrent()->Name())) {
    char *n = ParentDir(m_CurrentDir);
    free(m_CurrentDir);
    m_CurrentDir = n;
    Set();
    return osContinue;

  /* directory */
  } else if (GetCurrent()->IsDir()) {

    if(!ForceOpen && GetCurrent()->IsDvd()) {
      /* play dvd */
      cString f = cString::sprintf("dvd:%s/%s", m_CurrentDir, GetCurrent()->Name());
      cControl::Shutdown();
      cControl::Launch(new cXinelibDvdPlayerControl(f));
      return osEnd;
    }
    if(ForceOpen && GetCurrent()->IsDir() && !GetCurrent()->IsDvd()) {
      /* play all files */ 
      if(m_Mode != ShowImages) {

      if(m_OnlyQueue && !Queue)
        return osContinue;

      cString f = cString::sprintf("%s/%s/", m_CurrentDir, GetCurrent()->Name());

      if(!Queue || !cXinelibPlayerControl::IsOpen())
        cControl::Shutdown();
      if(Queue)
        cXinelibPlayerControl::Queue(f);
      else 
        cControl::Launch(new cXinelibPlayerControl(m_Mode, f));
      return Queue ? osContinue : osEnd;

      } else {
      // TODO: show all images
      }
    }
    const char *d = GetCurrent()->Name();
    char *buffer = NULL;
    asprintf(&buffer, "%s/%s", m_CurrentDir, d);
    while(buffer[0] == '/' && buffer[1] == '/')
      strcpy(buffer, buffer+1);
    free(m_CurrentDir);
    m_CurrentDir = buffer;
    Set();
    return osContinue;
    
  /* regular file */
  } else {
    cString f = cString::sprintf("%s%s/%s", 
                         GetCurrent()->IsDvd() ? "dvd:" : "",
                         m_CurrentDir, GetCurrent()->Name());
    strn0cpy(m_ConfigLastDir, f, sizeof(xc.browse_files_dir));
    StoreConfig();

    if(m_Mode != ShowImages) {
      /* video/audio */
      if(m_OnlyQueue && !Queue)
      return osContinue;
      if(!Queue || !cXinelibPlayerControl::IsOpen())
      cControl::Shutdown();
      if(Queue)
      cXinelibPlayerControl::Queue(f);
      if(!cXinelibPlayerControl::IsOpen())
      cControl::Launch(GetCurrent()->IsDvd()
                   ? new cXinelibDvdPlayerControl(f)
                   : new cXinelibPlayerControl(m_Mode, f));
      if(Queue)
      return osContinue;
    } else {
      /* image */
      char **files = new char*[Count()+1];
      int i = 0, index = 0;
      memset(files, 0, sizeof(char*)*(Count()+1));
      for(cFileListItem *it = (cFileListItem*)First(); it; it=(cFileListItem*)Next(it)) {
      if(it==Get(Current()))
        index = i;
      if(!it->IsDir())
        asprintf(&files[i++], "%s/%s", m_CurrentDir, it->Name());
      }
      cControl::Shutdown();
      cControl::Launch(new cXinelibImagesControl(files, index, i));
    }
    return osEnd;
  }
  return osContinue;
}

eOSState cMenuBrowseFiles::Info(void)
{
  if(GetCurrent() && !GetCurrent()->IsDir()) {
    cString cmd = cString::sprintf("'%s/%s'", m_CurrentDir, GetCurrent()->Name());
    if(xc.IsPlaylistFile(GetCurrent()->Name()))
      cmd = cString::sprintf("file -b %s; cat %s", *cmd, *cmd);
    else if(xc.IsAudioFile(GetCurrent()->Name()))
      cmd = cString::sprintf("mp3info -x %s ; file -b %s", *cmd, *cmd);
    else if(xc.IsVideoFile(GetCurrent()->Name()))
      cmd = cString::sprintf("file -b %s; midentify %s", *cmd, *cmd);
    else if(xc.IsImageFile(GetCurrent()->Name()))
      cmd = cString::sprintf("file -b %s; identify %s", *cmd, *cmd);
    else
      cmd = cString::sprintf("file -b %s", *cmd);

    cPipe p;
    if(p.Open(*cmd, "r")) {
      char buf[4096];
      int n = fread(buf, 1, sizeof(buf)-1, p);
      if(n>0) {
        buf[n] = 0;
        strreplace(buf, ',', '\n');
        return AddSubMenu(new cMenuText(GetCurrent()->Name(), buf));
      }
    }
  }

  return osContinue;
}

bool cMenuBrowseFiles::ScanDir(const char *DirName)
{
  DIR *d = opendir(DirName);
  if (d) {
    struct dirent *e;
    while ((e = readdir(d)) != NULL) {
      if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) {
      cString buffer = cString::sprintf("%s/%s", DirName, e->d_name);
        struct stat st;
        if (stat(buffer, &st) == 0) {

        // check symlink destination
          if (S_ISLNK(st.st_mode)) {
          buffer = ReadLink(buffer);
          if (!*buffer || stat(buffer, &st))
            continue;
        }

        // folders
          if (S_ISDIR(st.st_mode)) {

          if(m_Mode == ShowImages || m_Mode == ShowMusic)
            Add(new cFileListItem(e->d_name, true));
          else {
            // check if DVD
              bool dvd = false;
            buffer = cString::sprintf("%s/%s/VIDEO_TS/VIDEO_TS.IFO", DirName, e->d_name);
              if (stat(buffer, &st) == 0)
                dvd = true;
            else {
            buffer = cString::sprintf("%s/%s/video_ts/video_ts.ifo", DirName, e->d_name);
            if (stat(buffer, &st) == 0)
              dvd = true;
            }
            Add(new cFileListItem(e->d_name, true, false, false, dvd));
          }

          // regular files
          } else if(e->d_name[0] != '.') {

          // audio
          if (m_Mode == ShowMusic && xc.IsAudioFile(buffer)) {
            Add(new cFileListItem(e->d_name, false));

          // images
            } else if(m_Mode == ShowImages && xc.IsImageFile(buffer)) {
            Add(new cFileListItem(e->d_name, false));

          // video
          } else if (m_Mode == ShowFiles && xc.IsVideoFile(buffer)) {
            bool resume = false, subs = false, dvd = false;
            char *pos = strrchr(e->d_name, '.');

            if(pos) {
            // .iso image -> dvd
            if(pos && !strcasecmp(pos, ".iso"))
              dvd = true;

            // separate subtitles ?
            cString sub = cString::sprintf("%s/%s____", DirName, e->d_name);
            char *p = strrchr(sub, '.');
            if( p ) {
              int i;
              for(i=0; xc.s_subExts[i] && !subs; i++) {
                strcpy(p, xc.s_subExts[i]);
                if (stat(sub, &st) == 0)
                  subs = true;
              }
            }
            }

            // resume file ?
            buffer = cString::sprintf("%s/%s.resume", DirName, e->d_name);
            if (stat(buffer, &st) == 0)
            resume = true;

            Add(new cFileListItem(e->d_name, false, resume, subs, dvd));
          }
          }
        }
      }
    }
    closedir(d);
    return true;
  }
  return false;
}

eOSState cMenuBrowseFiles::ProcessKey(eKeys Key)
{
  eOSState state = cOsdMenu::ProcessKey(Key);

  if (state == osUnknown) {
     switch (Key) {
       case kPlay:   
       case kOk:     return Open(false, false, m_OnlyQueue);
       case kRed:    return Open(true);
       case kGreen:  return Open(true, m_Mode != ShowMusic, 
                         m_Mode==ShowMusic ? m_OnlyQueue=true : false);
       case kYellow: return Delete();
       case kBlue:   return Info();
       default: break;
       }
     }

  if (state == osUnknown)
    state = osContinue;

  if(!HasSubMenu())
    SetHelpButtons();

  return state;
}


//-------------------------- cDvdSpuTrackSelect ------------------------------

#ifdef OLD_SPU_MENU
class cDvdSpuTrackSelect : public cOsdMenu
{
  public:
    cDvdSpuTrackSelect(void);
    virtual eOSState ProcessKey(eKeys Key);
};

cDvdSpuTrackSelect::cDvdSpuTrackSelect(void) : 
      cOsdMenu(tr("Select subtitle track")) 
{
  int count = cXinelibDevice::Instance().NumDvdSpuTracks();
  int id = 0;
  int current = cXinelibDevice::Instance().GetCurrentDvdSpuTrack();
  Add(new cOsdItem("None", osUser1));

  while(count && id < 64) {
    const tTrackId *track = cXinelibDevice::Instance().GetDvdSpuTrack(id);
    if(track) {
      cString name = "";
      if(track->language[0])
      name = cString::sprintf(": %s", track->language);
      name = cString::sprintf("Track %d%s", id, *name);
      Add(new cOsdItem(name, osUser1));
      count--;
      if(id == current)
      SetCurrent(Get(Count()-1));
    }
    id++;
  }
}

eOSState cDvdSpuTrackSelect::ProcessKey(eKeys Key)
{
  eOSState state = cOsdMenu::ProcessKey(Key);

  switch(state) {
    case osUser1: 
      {
      const char *txt = Get(Current())->Text();
      int id = -1; /* -> DVD SPU off */
      sscanf(txt, "Track %d", &id);
      cXinelibDevice::Instance().SetCurrentDvdSpuTrack(id);
      AddSubMenu(new cMenuBrowseFiles());
      return osEnd;
      }
    default: break;
  }
  return state;
}
#else

//
// cDisplaySpuTracks : almost identical copy of VDR 1.4.5 cDisplayTracks
//

#define TRACKTIMEOUT 5000 //ms

class cDisplaySpuTracks : public cOsdObject {
private:
  cSkinDisplayTracks *displayTracks;
  cTimeMs timeout;
  eTrackType types[64+2];
  char *descriptions[64+2];
  int numTracks, track;
  static cDisplaySpuTracks *currentDisplayTracks;
  virtual void Show(void);
  cDisplaySpuTracks(void);
public:
  virtual ~cDisplaySpuTracks();
  static bool IsOpen(void) { return currentDisplayTracks != NULL; }
  static cDisplaySpuTracks *Create(void);
  static void Process(eKeys Key);
  eOSState ProcessKey(eKeys Key);
  };

cDisplaySpuTracks *cDisplaySpuTracks::currentDisplayTracks = NULL;

cDisplaySpuTracks::cDisplaySpuTracks(void) : cOsdObject(true)
{
  currentDisplayTracks = this;
  numTracks = track = 0;
  int CurrentTrack = cXinelibDevice::Instance().GetCurrentDvdSpuTrack();

  track = numTracks;
  types[numTracks] = eTrackType(-1);
  descriptions[numTracks] = strdup("(none)");
  numTracks++;

  for (int i = 0; i <= 63; i++) {
      const tTrackId *TrackId = cXinelibDevice::Instance().GetDvdSpuTrack(i);
      if (TrackId && TrackId->id) {
         types[numTracks] = eTrackType(i);
         descriptions[numTracks] = strdup(*TrackId->description ? TrackId->description : *TrackId->language ? TrackId->language : *itoa(i));
         if (i == CurrentTrack)
            track = numTracks;
         numTracks++;
         }
      }
  timeout.Set(TRACKTIMEOUT);
  displayTracks = NULL;
}

cDisplaySpuTracks::~cDisplaySpuTracks()
{
  delete displayTracks;
  currentDisplayTracks = NULL;
  for (int i = 0; i < numTracks; i++)
      free(descriptions[i]);
}

void cDisplaySpuTracks::Show(void)
{
  if(!displayTracks)
    displayTracks = Skins.Current()->DisplayTracks(tr("Subtitles"), numTracks, descriptions);

  displayTracks->SetTrack(track, descriptions);
  displayTracks->SetAudioChannel(-1);
  displayTracks->Flush();
}

cDisplaySpuTracks *cDisplaySpuTracks::Create(void)
{
  if (cXinelibDevice::Instance().NumDvdSpuTracks() > 0) {
     if (!currentDisplayTracks)
        new cDisplaySpuTracks;
     return currentDisplayTracks;
     }
  return NULL;
}

void cDisplaySpuTracks::Process(eKeys Key)
{
  if (currentDisplayTracks)
     currentDisplayTracks->ProcessKey(Key);
}

eOSState cDisplaySpuTracks::ProcessKey(eKeys Key)
{
  if(!displayTracks) {
    Show();
  }

  int oldTrack = track;
  switch (Key) {
    case kUp|k_Repeat:
    case kUp:
    case kDown|k_Repeat:
    case kDown:
         if (NORMALKEY(Key) == kUp && track > 0)
            track--;
         else if (NORMALKEY(Key) == kDown && track < numTracks - 1)
            track++;
         timeout.Set(TRACKTIMEOUT);
         break;
    case kNext:
    //case kSubtitle|k_Repeat:
    //case kSubtitle:
         if (++track >= numTracks)
            track = 0;
         timeout.Set(TRACKTIMEOUT);
         break;
    case kOk:
         if (track != cXinelibDevice::Instance().GetCurrentDvdSpuTrack())
            oldTrack = -1; // make sure we explicitly switch to that track
         timeout.Set();
         break;
    case kNone: break;
    default: if ((Key & k_Release) == 0)
                return osEnd;
    }
  if (track != oldTrack)
     Show();
  if (track != oldTrack) {
     cXinelibDevice::Instance().SetCurrentDvdSpuTrack(types[track], true);
     }
  return timeout.TimedOut() ? osEnd : osContinue;
}
#endif

//----------------------------- cMenuXinelib ---------------------------------

#include "tools/display_message.h"

static cOsdItem *NewTitle(const char *s)
{
  cString str = cString::sprintf("----- %s -----", s);
  cOsdItem *tmp = new cOsdItem(str);
  tmp->SetSelectable(false);
  return tmp;
}


extern cOsdObject *g_PendingMenuAction;

time_t cMenuXinelib::g_LastHotkeyTime = 0;
eKeys  cMenuXinelib::g_LastHotkey = kNone;

cMenuXinelib::cMenuXinelib()
{
  field_order = xc.field_order;
  compression = xc.audio_compression;
  headphone = xc.headphone;
  autocrop = xc.autocrop;
  overscan = xc.overscan;

  hotkey_state = hkInit;

  novideo = cXinelibDevice::Instance().GetPlayMode() == pmAudioOnlyBlack ? 1 : 0;

  Add(NewTitle(tr("Media")));
  Add(new cOsdItem(tr("Play file >>"), osUser1));
  Add(new cOsdItem(tr("Play music >>"), osUser2));
  Add(new cOsdItem(tr("View images >>"), osUser3));
  if(xc.remote_mode)
    Add(new cOsdItem(tr("Play remote DVD >>"), osUser4));
  else
    Add(new cOsdItem(tr("Play DVD disc >>"), osUser4));
  if(xc.remote_mode)
    Add(new cOsdItem(tr("Play remote CD >>"), osUser6));
  else
    Add(new cOsdItem(tr("Play audio CD >>"), osUser6));
  if(cXinelibDevice::Instance().NumDvdSpuTracks() > 0)
    Add(new cOsdItem(tr("Select subtitle track >>"), osUser5));

  Add(NewTitle(tr("Video settings")));
  Add(ctrl_novideo = new cMenuEditBoolItem(tr("Play only audio"), 
                                 &novideo));
  Add(ctrl_autocrop = new cMenuEditBoolItem(tr("Crop letterbox 4:3 to 16:9"), 
                                  &autocrop));
  Add(ctrl_overscan = new cMenuEditTypedIntItem(tr("Overscan (crop image borders)"), "%",
                                    &overscan, 0, 10,
                                    tr("Off")));
#ifdef HAVE_XV_FIELD_ORDER
  Add(video_ctrl_interlace_order = new cMenuEditStraI18nItem(tr("Interlaced Field Order"), 
                                               &field_order, 2, xc.s_fieldOrder));
#endif

  Add(NewTitle(tr("Audio settings")));
#ifdef ENABLE_TEST_POSTPLUGINS
  Add(ctrl_headphone = new cMenuEditBoolItem(tr("Headphone audio mode"), 
                                   &headphone));
#else
  ctrl_headphone = NULL;
#endif

  Add(audio_ctrl_compress = new cMenuEditTypedIntItem(tr("Audio Compression"),"%", 
                                          &compression, 100, 500, NULL, tr("Off")));

  Add(new cOsdItem(tr("Audio equalizer >>"), osUser7));

  switch(xc.main_menu_mode) {
    case ShowFiles:  AddSubMenu(new cMenuBrowseFiles(ShowFiles)); break;
    case ShowMusic:  AddSubMenu(new cMenuBrowseFiles(ShowMusic)); break;
    case ShowImages: AddSubMenu(new cMenuBrowseFiles(ShowImages)); break;
    default: break;
  }

  xc.main_menu_mode = ShowMenu;
}

cMenuXinelib::~cMenuXinelib()
{
#ifdef HAVE_XV_FIELD_ORDER
  if(xc.field_order != field_order )
    cXinelibDevice::Instance().ConfigureWindow(xc.fullscreen, xc.width, xc.height, 
                                     xc.modeswitch, xc.modeline, xc.display_aspect, 
                                     xc.scale_video, xc.field_order);
#endif

  if(xc.audio_compression != compression)
    cXinelibDevice::Instance().ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, 
                                           xc.audio_compression, xc.audio_equalizer, 
                                           xc.audio_surround, xc.speaker_type);

  if(xc.overscan != overscan)
    cXinelibDevice::Instance().ConfigureVideo(xc.hue, xc.saturation, xc.brightness,
                                    xc.contrast, xc.overscan);

  if(xc.headphone != headphone)
    cXinelibDevice::Instance().ConfigurePostprocessing("headphone", 
                                           xc.headphone ? true : false);

  if(xc.autocrop != autocrop)
    cXinelibDevice::Instance().ConfigurePostprocessing("autocrop", 
                                           xc.autocrop ? true : false,
                                           xc.AutocropOptions());

  int dev_novideo = cXinelibDevice::Instance().GetPlayMode() == pmAudioOnlyBlack ? 1 : 0;
  if(dev_novideo != novideo) 
    cXinelibDevice::Instance().SetPlayMode(novideo ? pmAudioOnlyBlack : pmNone);
}

cOsdMenu *cMenuXinelib::CreateMenuBrowseFiles(eMainMenuMode mode, bool Queue)
{
  return new cMenuBrowseFiles(mode, true);
}

eOSState cMenuXinelib::ProcessKey(eKeys Key)
{
  /* Hot key support */
  if(hotkey_state == hkInit && Key == kNone)
    return osContinue;
  if(hotkey_state == hkInit && Key == HOTKEY_START) {
    hotkey_state = hkSeen;
    return osContinue;
  } else if(hotkey_state == hkSeen && Key != kNone) {
    hotkey_state = hkNone;
    return ProcessHotkey(Key);
  }
  hotkey_state = hkNone;
    
  cOsdItem *item = Get(Current());

  eOSState state = cMenuSetupPage::ProcessKey(Key);

  if(HasSubMenu())
    return state;

  switch(state) {
    case osUser1:
      AddSubMenu(new cMenuBrowseFiles(ShowFiles));
      return osUnknown;
    case osUser2:
      AddSubMenu(new cMenuBrowseFiles(ShowMusic));
      return osUnknown;
    case osUser3:
      AddSubMenu(new cMenuBrowseFiles(ShowImages));
      return osContinue;
    case osUser4:
      cControl::Shutdown();
      cControl::Launch(new cXinelibDvdPlayerControl("dvd:/"));
      return osEnd;
    case osUser6:
      cControl::Shutdown();
      cControl::Launch(new cXinelibPlayerControl(ShowMusic, "cdda:/"));
      return osEnd;
    case osUser5:
#ifdef OLD_SPU_MENU
      AddSubMenu(new cDvdSpuTrackSelect());
      return osContinue;
#else
      if(!g_PendingMenuAction) {
      g_PendingMenuAction = cDisplaySpuTracks::Create();
      return osPlugin;
      }
      return osContinue;
#endif
    case osUser7:
      if(!g_PendingMenuAction) {
      g_PendingMenuAction = new cEqualizer();
      return osPlugin;
      }
      return osContinue;
    default: ;
  }

  Key = NORMALKEY(Key);

  if(Key==kLeft || Key==kRight || ISNUMBERKEY(Key)) {
    if(item == audio_ctrl_compress)
      cXinelibDevice::Instance().ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, 
                                           compression, xc.audio_equalizer, 
                                           xc.audio_surround, xc.speaker_type);
    else if(item == ctrl_overscan)
      cXinelibDevice::Instance().ConfigureVideo(xc.hue, xc.saturation, xc.brightness,
                                                xc.contrast, overscan);
  }
  if(Key==kLeft || Key==kRight) {
    if(item == ctrl_headphone)
      cXinelibDevice::Instance().ConfigurePostprocessing("headphone", headphone?true:false);    
    else if(item == ctrl_autocrop)
      cXinelibDevice::Instance().ConfigurePostprocessing("autocrop", autocrop?true:false,
                                           xc.AutocropOptions());
    else if(item == ctrl_novideo)
      cXinelibDevice::Instance().SetPlayMode(novideo ? pmAudioOnlyBlack : pmNone);
#ifdef HAVE_XV_FIELD_ORDER
    else if(video_ctrl_interlace_order && item == video_ctrl_interlace_order)
      cXinelibDevice::Instance().ConfigureWindow(xc.fullscreen, xc.width, xc.height, 
                                     xc.modeswitch, xc.modeline, 
                                     xc.display_aspect, xc.scale_video, 
                                     field_order);
#endif
  }
  
  return state;
}
  
void cMenuXinelib::Store(void)
{
#ifdef HAVE_XV_FIELD_ORDER
  xc.field_order = field_order;
#endif
  xc.audio_compression = compression;
  xc.autocrop = autocrop;
  xc.overscan = overscan;
  xc.headphone = headphone;
}

#if APIVERSNUM < 10404
#  warning Using hotkeys may segfault with VDR version < 1.4.3-2
#endif

eOSState cMenuXinelib::ProcessHotkey(eKeys Key)
{
  eOSState NewState = osEnd;
  char    *Message  = NULL;
  time_t   now      = time(NULL);
  bool     OnlyInfo = ((g_LastHotkeyTime < now-3) || g_LastHotkey != Key);

  switch(Key) {
    case HOTKEY_DVD:
      cControl::Shutdown();
      cControl::Launch(new cXinelibDvdPlayerControl("dvd:/"));
      break;

    case HOTKEY_DVD_TRACK1:
      cControl::Shutdown();
      cControl::Launch(new cXinelibDvdPlayerControl("dvd:/1"));
      break;

    case HOTKEY_DVD_SPU:
#ifdef OLD_SPU_MENU
      {
      int count = cXinelibDevice::Instance().NumDvdSpuTracks();
      int current = cXinelibDevice::Instance().GetCurrentDvdSpuTrack();
      if(!OnlyInfo) {
        current++;
        if(current == count)
          current = -1;
        cXinelibDevice::Instance().SetCurrentDvdSpuTrack(current);
      }
      const char *lang = cXinelibDevice::Instance().GetDvdSpuLang(current); 
      if(current == -1) lang = "default";
      if(count<1)
        asprintf(&Message, "%s", tr("No subtitles available!"));
      if(lang && lang[0])
        asprintf(&Message, "%s %s %s (%d)", tr("Subtitles"), 
               OnlyInfo ? ":" : "->",
               lang, current);
      else
        asprintf(&Message, "%s %s %d", tr("Subtitles"), 
               OnlyInfo ? ":" : "->", 
               current);
      }
#else
      /* use audio track display menu */
      if(!g_PendingMenuAction) {
      bool WasOpen = cDisplaySpuTracks::IsOpen();
      g_PendingMenuAction = cDisplaySpuTracks::Create();
      if(g_PendingMenuAction) {
        cRemote::CallPlugin("xineliboutput");
        if(WasOpen || !OnlyInfo) cRemote::Put(kNext);
      } else {
        asprintf(&Message, "%s", tr("No subtitles available!"));
      }
      }
#endif
      break;

    case HOTKEY_LOCAL_FE:
      /* off, on */
      {
      int local_frontend = strstra(xc.local_frontend, xc.s_frontends, 0);

#ifndef OLD_TOGGLE_FE
      if(local_frontend==FRONTEND_NONE)
        // no need to show current frontend if there is no output device ...
        OnlyInfo = false;
#endif
      if(!OnlyInfo) {
#ifndef OLD_TOGGLE_FE
        static int orig_frontend = -1;
        if(orig_frontend < 0)
          orig_frontend = local_frontend;

        if(orig_frontend == FRONTEND_NONE) {
          // no frontends were loaded at startup -> loop thru all frontends
          local_frontend++;
        } else {
          // frontend was loaded at startup -> toggle it on/off 
          if(local_frontend == FRONTEND_NONE)
            local_frontend = orig_frontend;
          else
            local_frontend = FRONTEND_NONE;
        }
#else
        local_frontend++;
#endif
        if(local_frontend >= FRONTEND_count)
          local_frontend = 0;
        strn0cpy(xc.local_frontend, xc.s_frontends[local_frontend], sizeof(xc.local_frontend));
        cXinelibDevice::Instance().ConfigureWindow(
            xc.fullscreen, xc.width, xc.height, xc.modeswitch, xc.modeline, 
            xc.display_aspect, xc.scale_video, xc.field_order);
      }
      asprintf(&Message, "%s %s %s", tr("Local Frontend"), 
             OnlyInfo ? ":" : "->", 
             xc.s_frontendNames[local_frontend]);
      }
      break;

    case HOTKEY_NEXT_ASPECT:
      /* auto, 4:3, 16:9, ... */
      if(!OnlyInfo) {
      xc.display_aspect = (xc.display_aspect < ASPECT_count-1) ? xc.display_aspect+1 : 0;
      cXinelibDevice::Instance().ConfigureWindow(xc.fullscreen, xc.width, xc.height, 
                                       xc.modeswitch, xc.modeline, xc.display_aspect, 
                                       xc.scale_video, xc.field_order);      
      }
      asprintf(&Message, "%s %s %s", tr("Aspect ratio"), 
             OnlyInfo ? ":" : "->",
             tr(xc.s_aspects[xc.display_aspect]));
      break;

    case HOTKEY_TOGGLE_CROP:    
      /* off, force, auto */
      if(!OnlyInfo) {
      if(!xc.autocrop) {
        xc.autocrop = 1;
        xc.autocrop_autodetect = 1;
      } else if(xc.autocrop_autodetect) {
        xc.autocrop_autodetect = 0;
      } else {
        xc.autocrop = 0;
      }
      cXinelibDevice::Instance().ConfigurePostprocessing("autocrop", 
                                             xc.autocrop ? true : false,
                                             xc.AutocropOptions());
      }

      asprintf(&Message, "%s %s %s", tr("Crop letterbox 4:3 to 16:9"), 
             OnlyInfo ? ":" : "->",
             !xc.autocrop ? tr("Off") : xc.autocrop_autodetect ? tr("automatic") : tr("On"));
      break;

    case HOTKEY_DEINTERLACE:    
      {
      /* off, on */
      int off = !strcmp(xc.deinterlace_method, "none");
      if(!OnlyInfo) {
        off = !off;
        if(off)
          strcpy(xc.deinterlace_method, "none");
        else
          strcpy(xc.deinterlace_method, "tvtime");
        cXinelibDevice::Instance().ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, 
                                               compression, xc.audio_equalizer, 
                                               xc.audio_surround, xc.speaker_type);
      }
      asprintf(&Message, "%s %s %s", tr("Deinterlacing"), 
             OnlyInfo ? ":" : "->", 
             tr(off ? "Off":"On"));
      }
      break;

    case HOTKEY_UPMIX:    
      /* off, on */
      if(!OnlyInfo) {
      xc.audio_upmix = xc.audio_upmix ? 0 : 1;
      cXinelibDevice::Instance().ConfigurePostprocessing(
              "upmix", xc.audio_upmix ? true : false, NULL);
      }
      asprintf(&Message, "%s %s %s", 
             tr("Upmix stereo to 5.1"), 
             OnlyInfo ? ":" : "->",
             tr(xc.audio_upmix ? "On" : "Off"));
      break;

    case HOTKEY_DOWNMIX:    
      /* off, on */
      if(!OnlyInfo) {
      xc.audio_surround = xc.audio_surround ? 0 : 1;
      cXinelibDevice::Instance().ConfigurePostprocessing(
          xc.deinterlace_method, xc.audio_delay, xc.audio_compression, 
          xc.audio_equalizer, xc.audio_surround, xc.speaker_type);
      }
      asprintf(&Message, "%s %s %s", 
             tr("Downmix AC3 to surround"), 
             OnlyInfo ? ":" : "->",
             tr(xc.audio_surround ? "On":"Off"));
      break;

      case HOTKEY_PLAYLIST:
      /* Start replaying playlist or file pointed by 
         symlink $(CONFDIR)/plugins/xineliboutput/default_playlist */
      {
        struct stat st;
        char *file;
        asprintf(&file, "%s%s", cPlugin::ConfigDirectory("xineliboutput"), "/default_playlist");
        if (lstat(file, &st) == 0) {
          if (S_ISLNK(st.st_mode)) {
            char *buffer = ReadLink(file);
            if (!buffer || stat(buffer, &st)) {
            asprintf(&Message, tr("Default playlist not found"));
            } else {
            LOGDBG("Replaying default playlist: %s", file);
            cControl::Shutdown();
            cControl::Launch(new cXinelibPlayerControl(CloseOsd, buffer));
            }
            free(buffer);
          } else {
            asprintf(&Message, tr("Default playlist is not symlink"));
          }
        } else {
          asprintf(&Message, tr("Default playlist not defined"));
        }
        free(file);
      }
      break;

    default:
      asprintf(&Message, tr("xineliboutput: hotkey %s not binded"), cKey::ToString(Key));
      break;
  }

  if(Message) {
    if(!g_PendingMenuAction &&
       !cRemote::HasKeys() &&
       cRemote::CallPlugin("xineliboutput"))
      g_PendingMenuAction = new cDisplayMessage(Message);
    free(Message);
  }

  g_LastHotkeyTime = now;
  g_LastHotkey = Key;

  return NewState;
}

Generated by  Doxygen 1.6.0   Back to index