/* * 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.97 2013-10-25 17:22:38 rofafor Exp $ * */ #include "features.h" #include #ifdef HAVE_LIBBLURAY # include #endif #include #include #include #include #include #include #include "logdefs.h" #include "config.h" #include "menu.h" #include "menuitems.h" #include "tools/metainfo_menu.h" #include "tools/playlist.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_RESERVED 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 */ # define HOTKEY_ADELAY_UP kUp /* audio delay up */ # define HOTKEY_ADELAY_DOWN kDown /* audio delay down */ # define HOTKEY_TOGGLE_VO_ASPECT kRight #endif //#define OLD_TOGGLE_FE #define ISNUMBERKEY(k) (RAWKEY(k) >= k0 && RAWKEY(k) <= k9) //----------------------------- cMenuBluray ---------------------------------- static bool BlurayMenuSupported(const cString& Path) { bool result = false; #ifdef HAVE_LIBBLURAY BLURAY *bdh = bd_open(Path, NULL); if (bdh) { const BLURAY_DISC_INFO *di = bd_get_disc_info(bdh); if (di->bluray_detected && !di->num_unsupported_titles) result = true; bd_close(bdh); } #endif return result; } class cMenuBluray : public cOsdMenu { private: cXinelibDevice *m_Dev; cString m_Path; public: cMenuBluray(cXinelibDevice *Dev, const char *Path); virtual ~cMenuBluray() {}; virtual eOSState ProcessKey(eKeys Key); }; cMenuBluray::cMenuBluray(cXinelibDevice *Dev, const char *Path) : cOsdMenu("BluRay") { m_Dev = Dev; m_Path = Path; Add(new cOsdItem(tr("Play movie title"), osUser1)); Add(new cOsdItem(tr("Play disc"), osUser2)); Display(); } eOSState cMenuBluray::ProcessKey(eKeys Key) { eOSState state = cOsdMenu::ProcessKey(Key); switch (state) { case osUser1: cPlayerFactory::Launch(m_Dev, pmAudioVideo, cPlaylist::BuildMrl("bluray", *m_Path), NULL, true); return osEnd; case osUser2: cPlayerFactory::Launch(m_Dev, pmAudioVideo, cPlaylist::BuildMrl("bd", *m_Path), NULL, true); return osEnd; case osBack: case osEnd: return osEnd; default: break; } return state; } //--------------------------- cMenuBrowseFiles ------------------------------- class cMenuBrowseFiles : public cOsdMenu { protected: cXinelibDevice *m_Dev; const eMainMenuMode m_Mode; bool m_OnlyQueue; cString m_CurrentDir; char *m_ConfigLastDir; const char *help[4]; virtual bool ScanDir(const char *DirName); virtual eOSState Open(bool ForceOpen = false, bool Queue = false, bool Rewind = false); virtual eOSState Delete(void); virtual eOSState Info(void); virtual void Set(void); virtual void SetHelpButtons(void); cFileListItem *GetCurrent(void) { return (cFileListItem *)Get(Current()); } void StoreConfig(void); char *GetLastDir(void); public: cMenuBrowseFiles(cXinelibDevice *Dev, eMainMenuMode mode = ShowFiles, bool OnlyQueue=false); ~cMenuBrowseFiles(); virtual eOSState ProcessKey(eKeys Key); }; static cString ParentDir(const char *dir) { char *result = strdup(dir); char *pt = strrchr(result, '/'); if (pt) { *(pt+1)=0; if (pt != result) *pt = 0; } return cString(result, true); } static cString LastDir(const char *dir) { const char *pt = strrchr(dir, '/'); if (pt && pt[0] && pt[1]) return cString(pt+1); return cString(NULL); } cMenuBrowseFiles::cMenuBrowseFiles(cXinelibDevice *Dev, 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_Mode(mode) { m_Dev = Dev; m_OnlyQueue = OnlyQueue; m_ConfigLastDir = GetLastDir(); Set(); } cMenuBrowseFiles::~cMenuBrowseFiles() { cPlugin *p = cPluginManager::GetPlugin(PLUGIN_NAME_I18N); if (p) { p->SetupStore("Media.RootDir", xc.media_root_dir); } Setup.Save(); } 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 = m_ConfigLastDir; int RootDirLen = strlen(xc.media_root_dir); if (strncmp(m_CurrentDir, xc.media_root_dir, RootDirLen)) { LOGMSG("Not allowing browsing to %s (root is %s)", *m_CurrentDir, xc.media_root_dir); m_CurrentDir = xc.media_root_dir; } if (m_CurrentDir[0] != '/') { #if defined(APIVERSNUM) && (APIVERSNUM < 20102) m_CurrentDir = VideoDirectory; #else m_CurrentDir = cVideoDirectory::Name(); #endif } // find deepest accessible directory from path while (!ScanDir(m_CurrentDir) && strlen(m_CurrentDir) > 1) { m_CurrentDir = ParentDir(m_CurrentDir); } // add link to parent folder int CurrentDirLen = strlen(m_CurrentDir); if (CurrentDirLen > 1 && CurrentDirLen > RootDirLen) Add(new cFileListItem("..",true)); Sort(); SetCurrent(Get(Count()>1 && CurrentDirLen>1 ? 1 : 0)); // select last selected item cString lastParent = ParentDir(m_ConfigLastDir); if (!strncmp(m_CurrentDir, lastParent, CurrentDirLen)) { cString item = LastDir(m_ConfigLastDir); if (*item) { for (cFileListItem *it = (cFileListItem*)First(); it; it = (cFileListItem*)Next(it)) if (!strcmp(it->Name(), item)) SetCurrent(it); } } strn0cpy(m_ConfigLastDir, m_CurrentDir, sizeof(xc.browse_files_dir)); StoreConfig(); SetHelpButtons(); Display(); } void cMenuBrowseFiles::StoreConfig(void) { cPlugin *p = cPluginManager::GetPlugin(PLUGIN_NAME_I18N); if (p) { p->SetupStore("Media.BrowseMusicDir", xc.browse_music_dir); p->SetupStore("Media.BrowseFilesDir", xc.browse_files_dir); p->SetupStore("Media.BrowseImagesDir", xc.browse_images_dir); #if 1 // delete old keys (<1.0.0) p->SetupStore("BrowseMusicDir"); p->SetupStore("BrowseFilesDir"); p->SetupStore("BrowseImagesDir"); #endif } } void cMenuBrowseFiles::SetHelpButtons(void) { bool isDir = !GetCurrent() || GetCurrent()->IsDir(); bool isFile = !isDir; bool bDel = isFile && xc.media_enable_delete; if (isDir && !strcmp("..", GetCurrent()->Name())) { help[0] = help[1] = help[2] = help[3] = NULL; } else if (m_Mode == ShowMusic) { help[0] = isDir ? trVDR("Button$Play") : NULL; help[1] = tr ("Button$Queue"); help[2] = bDel ? trVDR("Button$Delete") : NULL; help[3] = isFile ? trVDR("Button$Info") : NULL; } else if (m_Mode == ShowImages) { help[0] = isDir ? trVDR("Button$Play") : NULL; help[1] = NULL; help[2] = bDel ? trVDR("Button$Delete") : NULL; help[3] = isFile ? trVDR("Button$Info") : NULL; } else { bool isDvd = GetCurrent() && (GetCurrent()->IsDvd() || GetCurrent()->IsBluRay()); bool hasResume = GetCurrent() && GetCurrent()->HasResume(); help[0] = isDir && isDvd ? trVDR("Button$Open") : NULL; help[1] = hasResume ? trVDR("Button$Rewind") : NULL; help[2] = bDel ? trVDR("Button$Delete") : NULL; help[3] = isFile ? trVDR("Button$Info") : NULL; } SetHelp(help[0], help[1], help[2], help[3]); } eOSState cMenuBrowseFiles::Delete(void) { cFileListItem *it = GetCurrent(); if (!it->IsDir()) { if (Interface->Confirm(trVDR("Delete recording?"))) { cString name = cString::sprintf("%s/%s", (const char *)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, trVDR("Error while deleting recording!")); isyslog("Error deleting file %s", *name); } } } return osContinue; } eOSState cMenuBrowseFiles::Open(bool ForceOpen, bool Queue, bool Rewind) { if (!GetCurrent()) { return osContinue; } /* parent directory */ if (!strcmp("..", GetCurrent()->Name())) { m_CurrentDir = ParentDir(m_CurrentDir); Set(); return osContinue; /* directory */ } else if (GetCurrent()->IsDir()) { if (!ForceOpen && GetCurrent()->IsDvd()) { /* play dvd */ cPlayerFactory::Launch(m_Dev, pmAudioVideo, cPlaylist::BuildMrl("dvd", *m_CurrentDir, "/", GetCurrent()->Name()), NULL, true); return osEnd; } if (!ForceOpen && GetCurrent()->IsBluRay()) { cString bd_path = cString::sprintf("%s/%s/", *m_CurrentDir, GetCurrent()->Name()); if (BlurayMenuSupported(bd_path)) { AddSubMenu(new cMenuBluray(m_Dev, bd_path)); return osContinue; } /* play BluRay disc/image */ cPlayerFactory::Launch(m_Dev, pmAudioVideo, cPlaylist::BuildMrl("bluray", *m_CurrentDir, "/", GetCurrent()->Name(), "/"), NULL, true); return osEnd; } if (ForceOpen && GetCurrent()->IsDir() && !GetCurrent()->IsDvd() && !GetCurrent()->IsBluRay()) { /* 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 || !cPlayerFactory::IsOpen()) cControl::Shutdown(); if (Queue) cPlayerFactory::Queue(m_Dev, f); else cPlayerFactory::Launch(m_Dev, m_Mode == ShowFiles ? pmAudioVideo : pmAudioOnly, f, NULL, true); return Queue ? osContinue : osEnd; } else { // TODO: show all images } } /* go to directory */ const char *d = GetCurrent()->Name(); char *buffer = NULL; if (asprintf(&buffer, "%s/%s", *m_CurrentDir, d) >= 0) { while (buffer[0] == '/' && buffer[1] == '/') memmove(buffer, buffer+1, strlen(buffer)); m_CurrentDir = cString(buffer, true); } Set(); return osContinue; /* regular file */ } else { cString f = cString::sprintf("%s/%s", *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 || !cPlayerFactory::IsOpen()) cControl::Shutdown(); if (Queue) cPlayerFactory::Queue(m_Dev, f); if (!cPlayerFactory::IsOpen()) { if (Rewind) unlink(cString::sprintf("%s.resume", *f)); if (GetCurrent()->IsBluRay()) { AddSubMenu(new cMenuBluray(m_Dev, f)); return osContinue; } if (GetCurrent()->IsDvd()) cPlayerFactory::Launch(m_Dev, pmAudioVideo, cPlaylist::BuildMrl("dvd", f), NULL, true); else cPlayerFactory::Launch(m_Dev, m_Mode == ShowFiles ? pmAudioVideo : pmAudioOnly, f, GetCurrent()->SubFile(), true); } if (Queue) return osContinue; } else { /* image */ cPlaylist *Playlist = new cPlaylist(); for (cFileListItem *it = (cFileListItem*)First(); it; it=(cFileListItem*)Next(it)) { if (!it->IsDir()) Playlist->Read(cString::sprintf("%s/%s", *m_CurrentDir, it->Name())); if (it == Get(Current())) Playlist->SetCurrent(Playlist->Last()); } cPlayerFactory::Launch(m_Dev, pmVideoOnly, Playlist, true); } return osEnd; } return osContinue; } eOSState cMenuBrowseFiles::Info(void) { if (GetCurrent() && !GetCurrent()->IsDir()) { cString filename = cString::sprintf("%s/%s", *m_CurrentDir, GetCurrent()->Name()); return AddSubMenu(new cMetainfoMenu(filename)); } 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, "..") && (e->d_name[0] != '.' || xc.show_hidden_files)) { 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 Add(new cFileListItem(e->d_name, true, false, NULL, xc.IsDvdFolder(buffer), xc.IsBluRayFolder(buffer))); // 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)); // BluRay image (.iso) } else if (m_Mode == ShowFiles && xc.IsBluRayImage(buffer)) { Add(new cFileListItem(e->d_name, false, false, NULL, false, true)); // DVD image (.iso) } else if (m_Mode == ShowFiles && xc.IsDvdImage(buffer)) { Add(new cFileListItem(e->d_name, false, false, NULL, true)); // video } else if (m_Mode == ShowFiles && xc.IsVideoFile(buffer)) { cString subfile; cString resumefile; // separate subtitles ? cString basename = cString::sprintf("%s/%s", DirName, e->d_name); const char *p = strrchr(basename, '.'); if (p) basename.Truncate(p - basename); int i; for (i=0; xc.s_subExts[i] && !*subfile; i++) { cString tmp = cString::sprintf("%s%s", *basename, xc.s_subExts[i]); if (stat(tmp, &st) == 0) subfile = tmp; } // resume file ? resumefile = cString::sprintf("%s/%s.resume", DirName, e->d_name); if (stat(resumefile, &st) != 0) resumefile = NULL; Add(new cFileListItem(e->d_name, false, *resumefile, subfile)); } } } } } 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, m_OnlyQueue); case kRed: if (help[0]) return Open(true); break; case kGreen: if (help[1]) return Open(true, m_Mode == ShowMusic ? m_OnlyQueue=true : false, m_Mode != ShowMusic); break; case kYellow: if (help[2]) return Delete(); break; case kBlue: if (help[3]) return Info(); break; default: break; } } if (state == osUnknown) state = osContinue; if (!HasSubMenu() && Key != kNone) SetHelpButtons(); return state; } //----------------------------- cMenuXinelib --------------------------------- #include "tools/display_message.h" cMenuXinelib::cMenuXinelib(cXinelibDevice *Dev) { m_Dev = Dev; compression = xc.audio_compression; autocrop = xc.autocrop; overscan = xc.overscan; hotkey_state = hkInit; novideo = m_Dev->GetPlayMode() == pmAudioOnlyBlack ? 1 : 0; Add(SeparatorItem(tr("Media"))); if (xc.media_menu_items & MEDIA_MENU_FILES) Add(SubMenuItem(tr("Play file"), osUser1)); if (xc.media_menu_items & MEDIA_MENU_MUSIC) Add(SubMenuItem(tr("Play music"), osUser2)); if (xc.media_menu_items & MEDIA_MENU_IMAGES) Add(SubMenuItem(tr("View images"), osUser3)); if (xc.media_menu_items & MEDIA_MENU_DVD) Add(SubMenuItem(tr("Play DVD disc"), osUser4)); if (xc.media_menu_items & MEDIA_MENU_BLURAY) Add(SubMenuItem(tr("Play BluRay disc"), osUser5)); if (xc.media_menu_items & MEDIA_MENU_CD) Add(SubMenuItem(tr("Play audio CD"), osUser6)); if (xc.media_menu_items & MEDIA_MENU_VIDEO_SETUP) { Add(SeparatorItem(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"))); } if (xc.media_menu_items & MEDIA_MENU_AUDIO_SETUP) { Add(SeparatorItem(tr("Audio settings"))); Add(audio_ctrl_compress = new cMenuEditTypedIntItem(tr("Audio Compression"), "%", &compression, 100, 500, NULL, tr("Off"))); Add(SubMenuItem(tr("Audio equalizer"), osUser7)); } switch (xc.main_menu_mode) { case ShowFiles: case ShowMusic: case ShowImages: AddSubMenu(new cMenuBrowseFiles(m_Dev, xc.main_menu_mode)); break; default: break; } xc.main_menu_mode = ShowMenu; } cMenuXinelib::~cMenuXinelib() { if (xc.audio_compression != compression) m_Dev->ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, xc.audio_compression, xc.audio_equalizer, xc.audio_surround, xc.speaker_type); if (xc.overscan != overscan) m_Dev->ConfigureVideo(xc.hue, xc.saturation, xc.brightness, xc.sharpness, xc.noise_reduction, xc.contrast, xc.overscan, xc.vo_aspect_ratio); if (xc.autocrop != autocrop) m_Dev->ConfigurePostprocessing("autocrop", xc.autocrop ? true : false, xc.AutocropOptions()); int dev_novideo = m_Dev->GetPlayMode() == pmAudioOnlyBlack ? 1 : 0; if (dev_novideo != novideo) m_Dev->SetPlayMode(novideo ? pmAudioOnlyBlack : pmNone); } cOsdMenu *cMenuXinelib::CreateMenuBrowseFiles(cXinelibDevice *Dev, eMainMenuMode mode, bool Queue) { return new cMenuBrowseFiles(Dev, 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(m_Dev, ShowFiles)); return osUnknown; case osUser2: AddSubMenu(new cMenuBrowseFiles(m_Dev, ShowMusic)); return osUnknown; case osUser3: AddSubMenu(new cMenuBrowseFiles(m_Dev, ShowImages)); return osContinue; case osUser4: cPlayerFactory::Launch(m_Dev, "dvd:/"); return osEnd; case osUser5: AddSubMenu(new cMenuBluray(m_Dev, NULL)); return osContinue; case osUser6: cPlayerFactory::Launch(m_Dev, "cdda:/"); return osEnd; case osUser7: if (!xc.pending_menu_action) { xc.pending_menu_action = new cEqualizer(m_Dev); return osPlugin; } return osContinue; default: ; } Key = NORMALKEY(Key); if (Key == kLeft || Key == kRight || ISNUMBERKEY(Key)) { if (item == audio_ctrl_compress) m_Dev->ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, compression, xc.audio_equalizer, xc.audio_surround, xc.speaker_type); else if (item == ctrl_overscan) m_Dev->ConfigureVideo(xc.hue, xc.saturation, xc.brightness, xc.sharpness, xc.noise_reduction, xc.contrast, overscan, xc.vo_aspect_ratio); } if (Key == kLeft || Key == kRight) { if (item == ctrl_autocrop) m_Dev->ConfigurePostprocessing("autocrop", autocrop?true:false, xc.AutocropOptions()); else if (item == ctrl_novideo) m_Dev->SetPlayMode(novideo ? pmAudioOnlyBlack : pmNone); } return state; } void cMenuXinelib::Store(void) { xc.audio_compression = compression; xc.autocrop = autocrop; xc.overscan = overscan; } eOSState cMenuXinelib::ProcessHotkey(eKeys Key) { eOSState NewState = osEnd; cString Message; time_t now = time(NULL); bool OnlyInfo = ((xc.last_hotkey_time < now-3) || xc.last_hotkey != Key); switch (Key) { case HOTKEY_DVD: cPlayerFactory::Launch(m_Dev, "dvd:/"); break; case HOTKEY_DVD_TRACK1: cPlayerFactory::Launch(m_Dev, "dvd:/1"); 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)); m_Dev->ConfigureWindow( xc.fullscreen, xc.width, xc.height, xc.modeswitch, xc.modeline, xc.display_aspect, xc.scale_video); } Message = cString::sprintf("%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; m_Dev->ConfigureWindow(xc.fullscreen, xc.width, xc.height, xc.modeswitch, xc.modeline, xc.display_aspect, xc.scale_video); } Message = cString::sprintf("%s %s %s", tr("Aspect ratio"), OnlyInfo ? ":" : "->", tr(xc.s_aspects[xc.display_aspect])); break; case HOTKEY_TOGGLE_VO_ASPECT: /* auto, square, 4:3, anamorphic or DVB */ if (!OnlyInfo) { xc.vo_aspect_ratio = (xc.vo_aspect_ratio < VO_ASPECT_count-1) ? xc.vo_aspect_ratio + 1 : 0; m_Dev->ConfigureVideo(xc.hue, xc.saturation, xc.brightness, xc.sharpness, xc.noise_reduction, xc.contrast, xc.overscan, xc.vo_aspect_ratio); } Message = cString::sprintf("%s %s %s", tr("Video aspect ratio"), OnlyInfo ? ":" : "->", tr(xc.s_vo_aspects[xc.vo_aspect_ratio])); 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; } m_Dev->ConfigurePostprocessing("autocrop", xc.autocrop ? true : false, xc.AutocropOptions()); } Message = cString::sprintf("%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"); m_Dev->ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, compression, xc.audio_equalizer, xc.audio_surround, xc.speaker_type); } Message = cString::sprintf("%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; m_Dev->ConfigurePostprocessing("upmix", xc.audio_upmix ? true : false, NULL); } Message = cString::sprintf("%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; m_Dev->ConfigurePostprocessing( xc.deinterlace_method, xc.audio_delay, xc.audio_compression, xc.audio_equalizer, xc.audio_surround, xc.speaker_type); } Message = cString::sprintf("%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; cString file = cString::sprintf("%s%s", cPlugin::ConfigDirectory("xineliboutput"), "/default_playlist"); if (lstat(file, &st) == 0) { if (S_ISLNK(st.st_mode)) { cString buffer(ReadLink(file), true); if (!*buffer || stat(buffer, &st)) { Message = tr("Default playlist not found"); } else { LOGDBG("Replaying default playlist: %s", *file); cPlayerFactory::Launch(m_Dev, buffer); } } else { Message = tr("Default playlist is not symlink"); } } else { Message = tr("Default playlist not defined"); } } break; case HOTKEY_ADELAY_UP: /* audio delay up */ if (!OnlyInfo) { xc.audio_delay++; m_Dev->ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, xc.audio_compression, xc.audio_equalizer, xc.audio_surround, xc.speaker_type); } Message = cString::sprintf("%s %s %d %s", tr("Delay"), OnlyInfo ? ":" : "->", xc.audio_delay, tr("ms")); break; case HOTKEY_ADELAY_DOWN: /* audio delay up */ if (!OnlyInfo) { xc.audio_delay--; m_Dev->ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, xc.audio_compression, xc.audio_equalizer, xc.audio_surround, xc.speaker_type); } Message = cString::sprintf("%s %s %d %s", tr("Delay"), OnlyInfo ? ":" : "->", xc.audio_delay, tr("ms")); break; default: Message = cString::sprintf(tr("xineliboutput: hotkey %s not binded"), cKey::ToString(Key)); break; } if (*Message) { if (!xc.pending_menu_action && !cRemote::HasKeys() && cRemote::CallPlugin("xineliboutput")) xc.pending_menu_action = new cDisplayMessage(Message); } xc.last_hotkey_time = now; xc.last_hotkey = Key; return NewState; }