Ticket #11533: themedmenu.patch
| File themedmenu.patch, 110.5 KB (added by , 13 years ago) |
|---|
-
mythtv/libs/libmythtv/tv_actions.h
commit df6f98bb109e584c37da6818472d12234f15636f Author: Jim Stichnoth <stichnot@localhost> Date: Thu May 9 09:47:00 2013 -0700 Initial implementation of Themed Menus. Themed Menus allows customization of menus through a hierarchical xml description, consisting of actions, action groups, and submenus. An action group is essentially a macro that expands into a possibly context-dependent list of actions. This is demonstrated by replacing the deeply complex and hierarchical Playback OSD menu with a themed version, defined in menu_playback.xml. In addition, a "compact" version of the Playback OSD menu is supported, with the MENUCOMPACT action and an associated key binding to display it. When more menus are converted to themed versions, the MenuBase class should be moved out of tv_play.cpp and tv_play.h into a new file. diff --git a/mythtv/libs/libmythtv/tv_actions.h b/mythtv/libs/libmythtv/tv_actions.h index b2ffe61..34edf37 100644a b 3 3 4 4 #define ACTION_EXITSHOWNOPROMPTS "EXITSHOWNOPROMPTS" 5 5 6 #define ACTION_MENUCOMPACT "MENUCOMPACT" 6 7 #define ACTION_PLAYBACK "PLAYBACK" 7 8 #define ACTION_STOP "STOPPLAYBACK" 8 9 #define ACTION_DAYLEFT "DAYLEFT" -
mythtv/libs/libmythtv/tv_play.cpp
diff --git a/mythtv/libs/libmythtv/tv_play.cpp b/mythtv/libs/libmythtv/tv_play.cpp index 1575a6c..aad11f0 100644
a b using namespace std; 16 16 #include <QEvent> 17 17 #include <QFile> 18 18 #include <QDir> 19 #include <QDomDocument> 20 #include <QDomElement> 21 #include <QDomNode> 22 23 Q_DECLARE_METATYPE(QDomNode) 19 24 20 25 #include "signalhandling.h" 21 26 #include "mythdb.h" … … void TV::InitKeys(void) 569 574 570 575 REG_KEY("TV Playback", "BACK", QT_TRANSLATE_NOOP("MythControls", 571 576 "Exit or return to DVD menu"), "Esc"); 577 REG_KEY("TV Playback", ACTION_MENUCOMPACT, QT_TRANSLATE_NOOP("MythControls", 578 "Playback Compact Menu"), "Alt+M"); 572 579 REG_KEY("TV Playback", ACTION_CLEAROSD, QT_TRANSLATE_NOOP("MythControls", 573 580 "Clear OSD"), "Backspace"); 574 581 REG_KEY("TV Playback", ACTION_PAUSE, QT_TRANSLATE_NOOP("MythControls", … … bool TV::ActiveHandleAction(PlayerContext *ctx, 4481 4488 ChangeTimeStretch(ctx, -1); 4482 4489 else if (has_action("MENU", actions)) 4483 4490 ShowOSDMenu(ctx); 4491 else if (has_action(ACTION_MENUCOMPACT, actions)) 4492 ShowOSDMenu(ctx, true); 4484 4493 else if (has_action("INFO", actions) || 4485 4494 has_action("INFOWITHCUTLIST", actions)) 4486 4495 { … … void TV::customEvent(QEvent *e) 9177 9186 { 9178 9187 DialogCompletionEvent *dce = 9179 9188 reinterpret_cast<DialogCompletionEvent*>(e); 9180 OSDDialogEvent(dce->GetResult(), dce->GetResultText(), 9181 dce->GetData().toString()); 9189 if (dce->GetData().userType() == qMetaTypeId<QDomNode>()) 9190 { 9191 QDomNode data = qVariantValue<QDomNode>(dce->GetData()); 9192 if (dce->GetResult() == -1) // menu exit/back 9193 MenuShow(data.parentNode(), data); 9194 else 9195 MenuShow(data, QDomNode()); 9196 } 9197 else 9198 OSDDialogEvent(dce->GetResult(), dce->GetResultText(), 9199 dce->GetData().toString()); 9182 9200 return; 9183 9201 } 9184 9202 … … void TV::OSDDialogEvent(int result, QString text, QString action) 10593 10611 action.remove("DIALOG_"); 10594 10612 QStringList desc = action.split("_"); 10595 10613 bool valid = desc.size() == 3; 10596 if (valid && desc[0] == "MENU") 10597 { 10598 ShowOSDMenu(actx, desc[1], text); 10599 hide = false; 10600 } 10601 else if (valid && desc[0] == ACTION_JUMPREC) 10614 if (valid && desc[0] == ACTION_JUMPREC) 10602 10615 { 10603 10616 FillOSDMenuJumpRec(actx, desc[1], desc[2].toInt(), text); 10604 10617 hide = false; … … void TV::HandleOSDInfo(PlayerContext *ctx, QString action) 10959 10972 } 10960 10973 } 10961 10974 10962 void TV::ShowOSDMenu(const PlayerContext *ctx, const QString category, 10963 const QString selected) 10975 bool MenuBase::MenuLoadFromFile(const QString &filename, 10976 const QString &menuname, 10977 const char *translationContext, 10978 const QString &keyBindingContext) 10964 10979 { 10965 QString cat = category.isEmpty() ? "MAIN" : category;10980 bool result = false; 10966 10981 10967 OSD *osd = GetOSDLock(ctx); 10968 if (osd) 10969 { 10970 osd->DialogShow(OSD_DLG_MENU, tr("Playback Menu")); 10971 QString currenttext = QString(); 10972 QString back = QString(); 10973 10974 FillOSDMenuAudio (ctx, osd, cat, selected, currenttext, back); 10975 FillOSDMenuVideo (ctx, osd, cat, selected, currenttext, back); 10976 FillOSDMenuSubtitles(ctx, osd, cat, selected, currenttext, back); 10977 FillOSDMenuPlayback (ctx, osd, cat, selected, currenttext, back); 10978 FillOSDMenuNavigate (ctx, osd, cat, selected, currenttext, back); 10979 FillOSDMenuSchedule (ctx, osd, cat, selected, currenttext, back); 10980 FillOSDMenuSource (ctx, osd, cat, selected, currenttext, back); 10981 FillOSDMenuJobs (ctx, osd, cat, selected, currenttext, back); 10982 10983 if (!currenttext.isEmpty()) 10984 osd->DialogSetText(currenttext); 10985 if (!back.isEmpty() && !category.isEmpty()) 10986 osd->DialogBack(cat, QString("DIALOG_MENU_%1_0").arg(back)); 10987 } 10988 ReturnOSDLock(ctx, osd); 10989 } 10990 10991 void TV::FillOSDMenuAudio(const PlayerContext *ctx, OSD *osd, 10992 QString category, const QString selected, 10993 QString ¤ttext, QString &backaction) 10994 { 10995 QStringList tracks; 10996 uint curtrack = ~0; 10997 bool avsync = true; 10998 bool visual = false; 10999 QString active = QString(""); 11000 bool upmixing = false; 11001 bool canupmix = false; 11002 ctx->LockDeletePlayer(__FILE__, __LINE__); 11003 if (ctx->player) 11004 { 11005 visual = ctx->player->CanVisualise(); 11006 active = ctx->player->GetVisualiserName(); 11007 tracks = ctx->player->GetTracks(kTrackTypeAudio); 11008 if (!tracks.empty()) 11009 curtrack = (uint) ctx->player->GetTrack(kTrackTypeAudio); 11010 avsync = (ctx->player->GetTrackCount(kTrackTypeVideo) > 0) && 11011 !tracks.empty(); 11012 upmixing = ctx->player->GetAudio()->IsUpmixing(); 11013 canupmix = ctx->player->GetAudio()->CanUpmix(); 11014 } 11015 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 11016 11017 if (tracks.empty()) // No audio 11018 return; 11019 11020 if (category == "MAIN") 11021 { 11022 osd->DialogAddButton(tr("Audio"), "DIALOG_MENU_AUDIO_0", 11023 true, selected == "AUDIO"); 11024 } 11025 else if (category == "AUDIO") 10982 m_translationContext = translationContext; 10983 m_keyBindingContext = keyBindingContext; 10984 const QStringList searchpath = GetMythUI()->GetThemeSearchPath(); 10985 QStringList::const_iterator it = searchpath.begin(); 10986 for (; !result && it != searchpath.end(); ++it) 11026 10987 { 11027 // TODO Add mute and volume 11028 backaction = "MAIN"; 11029 currenttext = tr("Audio"); 11030 if (tracks.size() > 1) 11031 { 11032 osd->DialogAddButton(tr("Select Audio Track"), 11033 "DIALOG_MENU_AUDIOTRACKS_0", true, 11034 selected == "AUDIOTRACKS"); 11035 } 11036 if (avsync) 11037 osd->DialogAddButton(tr("Adjust Audio Sync"), ACTION_TOGGELAUDIOSYNC); 11038 if (visual) 10988 QString themefile = *it + filename; 10989 LOG(VB_PLAYBACK, LOG_INFO, 10990 LOC + QString("Loading menu %1").arg(themefile)); 10991 QFile file(themefile); 10992 if (file.open(QIODevice::ReadOnly)) 11039 10993 { 11040 osd->DialogAddButton(tr("Visualisation"), 11041 "DIALOG_MENU_VISUALISATIONS_0", true, 11042 selected == "VISUALISATIONS"); 11043 } 11044 11045 if (canupmix) 11046 { 11047 if (upmixing) 10994 m_menuDocument = new QDomDocument(); 10995 if (m_menuDocument->setContent(&file)) 11048 10996 { 11049 osd->DialogAddButton(tr("Disable Audio Upmixer"), 11050 ACTION_DISABLEUPMIX); 10997 result = true; 10998 m_menuName = 10999 MenuTranslate(MenuGetRoot().attribute("text", menuname)); 11000 QDomElement root = MenuGetRoot(); 11001 MenuProcessIncludes(root); 11051 11002 } 11052 11003 else 11053 11004 { 11054 osd->DialogAddButton(tr("Enable Audio Upmixer"),11055 ACTION_ENABLEUPMIX);11005 delete m_menuDocument; 11006 m_menuDocument = NULL; 11056 11007 } 11008 file.close(); 11057 11009 } 11058 11059 } 11060 else if (category == "AUDIOTRACKS") 11061 { 11062 backaction = "AUDIO"; 11063 currenttext = tr("Select Audio Track"); 11064 for (uint i = 0; i < (uint)tracks.size(); i++) 11010 if (!result) 11065 11011 { 11066 osd->DialogAddButton(tracks[i], 11067 "SELECTAUDIO_" + QString::number(i), 11068 false, i == curtrack); 11012 LOG(VB_FILE, LOG_ERR, LOC + "No theme file " + themefile); 11069 11013 } 11070 11014 } 11071 else if (category == "VISUALISATIONS") 11015 11016 return result; 11017 } 11018 11019 void MenuBase::MenuProcessIncludes(QDomElement &root) 11020 { 11021 const int maxRecursion = 10; 11022 for (QDomNode n = root.firstChild(); !n.isNull(); n = n.nextSibling()) 11072 11023 { 11073 backaction = "AUDIO"; 11074 currenttext = tr("Visualisation"); 11075 osd->DialogAddButton(tr("None"), 11076 ACTION_DISABLEVISUALISATION, false, 11077 active.isEmpty()); 11078 QStringList visualisers; 11079 ctx->LockDeletePlayer(__FILE__, __LINE__); 11080 if (ctx->player) 11081 visualisers = ctx->player->GetVisualiserList(); 11082 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 11083 for (int i = 0; i < visualisers.size(); i++) 11024 if (n.isElement()) 11084 11025 { 11085 osd->DialogAddButton(visualisers[i], 11086 "VISUALISER_" + visualisers[i], false, 11087 active == visualisers[i]); 11026 QDomElement e = n.toElement(); 11027 if (e.tagName() == "include") 11028 { 11029 QString include = e.attribute("file", ""); 11030 int level = m_recursionLevel + 1; 11031 if (level > maxRecursion) 11032 { 11033 LOG(VB_GENERAL, LOG_ERR, 11034 QString("Maximum include depth (%1) " 11035 "exceeded for %2") 11036 .arg(maxRecursion).arg(include)); 11037 return; 11038 } 11039 MenuBase menu; 11040 menu.m_recursionLevel = level; 11041 if (menu.MenuLoadFromFile(include, include, 11042 m_translationContext, 11043 m_keyBindingContext)) 11044 { 11045 QDomNode newChild = menu.MenuGetRoot(); 11046 newChild = m_menuDocument->importNode(newChild, true); 11047 root.replaceChild(newChild, n); 11048 n = newChild; 11049 } 11050 } 11051 else if (e.tagName() == "menu") 11052 { 11053 MenuProcessIncludes(e); 11054 } 11088 11055 } 11089 11056 } 11090 11057 } 11091 11058 11092 void TV::FillOSDMenuVideo(const PlayerContext *ctx, OSD *osd, 11093 QString category, const QString selected, 11094 QString ¤ttext, QString &backaction) 11059 MenuBase::~MenuBase() 11095 11060 { 11096 QStringList tracks; 11097 //uint curtrack = ~0; 11098 uint sup = kPictureAttributeSupported_None; 11099 bool studio_levels = false; 11100 bool autodetect = false; 11101 AdjustFillMode adjustfill = kAdjustFill_Off; 11102 AspectOverrideMode aspectoverride = kAspect_Off; 11103 FrameScanType scan_type = kScan_Ignore; 11104 bool scan_type_locked = false; 11105 bool stereoallowed = false; 11106 StereoscopicMode stereomode = kStereoscopicModeNone; 11107 11108 ctx->LockDeletePlayer(__FILE__, __LINE__); 11109 if (ctx->player) 11061 if (m_menuDocument) 11110 11062 { 11111 tracks = ctx->player->GetTracks(kTrackTypeVideo); 11112 aspectoverride = ctx->player->GetAspectOverride(); 11113 adjustfill = ctx->player->GetAdjustFill(); 11114 scan_type = ctx->player->GetScanType(); 11115 scan_type_locked = ctx->player->IsScanTypeLocked(); 11116 //if (!tracks.empty()) 11117 // curtrack = (uint) ctx->player->GetTrack(kTrackTypeVideo); 11118 VideoOutput *vo = ctx->player->GetVideoOutput(); 11119 if (vo) 11120 { 11121 sup = vo->GetSupportedPictureAttributes(); 11122 studio_levels = vo->GetPictureAttribute(kPictureAttribute_StudioLevels) > 0; 11123 autodetect = !vo->hasHWAcceleration(); 11124 stereoallowed = vo->StereoscopicModesAllowed(); 11125 stereomode = vo->GetStereoscopicMode(); 11126 } 11063 delete m_menuDocument; 11064 m_menuDocument = NULL; 11127 11065 } 11128 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 11066 } 11129 11067 11130 if (tracks.empty()) // No video 11131 return; 11068 QDomElement MenuBase::MenuGetRoot(void) const 11069 { 11070 return m_menuDocument->documentElement(); 11071 } 11132 11072 11133 if (category == "MAIN") 11073 QString MenuBase::MenuTranslate(const QString &text) const 11074 { 11075 return qApp->translate(m_translationContext, text.toUtf8(), NULL, 11076 QCoreApplication::UnicodeUTF8); 11077 } 11078 11079 bool MenuBase::MenuShowHelper(const QDomNode &node, 11080 const QDomNode &selected, 11081 bool doDisplay) 11082 { 11083 bool hasSelected = false; 11084 bool displayed = false; 11085 for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) 11134 11086 { 11135 osd->DialogAddButton(tr("Video"), "DIALOG_MENU_VIDEO_0",11136 true, selected == "VIDEO");11087 if (n == selected) 11088 hasSelected = true; 11137 11089 } 11138 else if (category == "VIDEO")11090 for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) 11139 11091 { 11140 // TODO Add deinterlacer, filters, video track 11141 backaction = "MAIN"; 11142 currenttext = tr("Video"); 11143 if (ctx == GetPlayer(ctx, 0)) 11092 if (n.isElement()) 11144 11093 { 11145 osd->DialogAddButton(tr("Change Aspect Ratio"), 11146 "DIALOG_MENU_VIDEOASPECT_0", true, 11147 selected == "VIDEOASPECT"); 11148 osd->DialogAddButton(tr("Adjust Fill"), 11149 "DIALOG_MENU_ADJUSTFILL_0", true, 11150 selected == "ADJUSTFILL"); 11151 osd->DialogAddButton(tr("Manual Zoom Mode"), "TOGGLEMANUALZOOM"); 11152 if (sup != kPictureAttributeSupported_None) 11094 QDomElement e = n.toElement(); 11095 QString text = e.attribute("text", ""); 11096 text = MenuTranslate(text); 11097 QString show = e.attribute("show", ""); 11098 MenuShowContext showContext = 11099 (show == "active" ? kMenuShowActive : 11100 show == "inactive" ? kMenuShowInactive : kMenuShowAlways); 11101 QString current = e.attribute("current", ""); 11102 bool currentActive = (current == "active") && !hasSelected; 11103 if (e.tagName() == "menu") 11153 11104 { 11154 osd->DialogAddButton(tr("Adjust Picture"), 11155 "DIALOG_MENU_ADJUSTPICTURE_0", true, 11156 selected == "ADJUSTPICTURE"); 11105 MenuItemContext c(n, text, (hasSelected && n == selected), 11106 doDisplay); 11107 displayed |= MenuDisplayItem(c); 11108 } 11109 else if (e.tagName() == "item") 11110 { 11111 QString action = e.attribute("action", ""); 11112 MenuItemContext c(n, showContext, currentActive, action, 11113 text, doDisplay); 11114 displayed |= MenuDisplayItem(c); 11115 } 11116 else if (e.tagName() == "itemlist") 11117 { 11118 QString actiongroup = e.attribute("actiongroup", ""); 11119 MenuItemContext c(n, showContext, currentActive, 11120 actiongroup, doDisplay); 11121 displayed |= MenuDisplayItem(c); 11157 11122 } 11158 11123 } 11159 if (stereoallowed) 11160 { 11161 osd->DialogAddButton(tr("3D"), "DIALOG_MENU_3D_0", 11162 true, selected == "3D"); 11163 } 11164 osd->DialogAddButton(tr("Advanced"), "DIALOG_MENU_ADVANCEDVIDEO_0", 11165 true, selected == "ADVANCEDVIDEO"); 11124 if (!doDisplay && displayed) 11125 break; // early exit optimization 11166 11126 } 11167 else if (category == "VIDEOASPECT") 11168 { 11169 backaction = "VIDEO"; 11170 currenttext = tr("Change Aspect Ratio"); 11127 return displayed; 11128 } 11171 11129 11172 for (int j = kAspect_Off; j < kAspect_END; j++) 11173 { 11174 // swap 14:9 and 16:9 11175 int i = ((kAspect_14_9 == j) ? kAspect_16_9 : 11176 ((kAspect_16_9 == j) ? kAspect_14_9 : j)); 11177 osd->DialogAddButton(toString((AspectOverrideMode) i), 11178 QString("TOGGLEASPECT%1").arg(i), false, 11179 aspectoverride == i); 11180 } 11181 } 11182 else if (category == "ADJUSTFILL") 11183 { 11184 backaction = "VIDEO"; 11185 currenttext = tr("Adjust Fill"); 11130 static bool matchesGroup(const QString &name, const QString &inPrefix, 11131 MenuCategory category, QString &outPrefix) 11132 { 11133 outPrefix = name; 11134 return ((category == kMenuCategoryItem && name.startsWith(inPrefix)) || 11135 (category == kMenuCategoryItemlist && name == inPrefix)); 11136 } 11186 11137 11187 if (autodetect) 11188 { 11189 osd->DialogAddButton(tr("Auto Detect"), "AUTODETECT_FILL", 11190 false, (adjustfill == kAdjustFill_AutoDetect_DefaultHalf) || 11191 (adjustfill == kAdjustFill_AutoDetect_DefaultOff)); 11192 } 11193 for (int i = kAdjustFill_Off; i < kAdjustFill_END; i++) 11194 { 11195 osd->DialogAddButton(toString((AdjustFillMode) i), 11196 QString("TOGGLEFILL%1").arg(i), false, 11197 adjustfill == i); 11198 } 11199 } 11200 else if (category == "ADJUSTPICTURE") 11138 static void addButton(const MenuItemContext &c, OSD *osd, bool active, 11139 bool &result, const QString &action, 11140 const QString &defaultTextActive, 11141 const QString &defaultTextInactive = "", 11142 bool isMenu = false) 11143 { 11144 if (c.m_category == kMenuCategoryItemlist || action == c.m_action) 11201 11145 { 11202 backaction = "VIDEO"; 11203 currenttext = tr("Adjust Picture"); 11204 for (int i = kPictureAttribute_MIN; i < kPictureAttribute_MAX; i++) 11146 if ((c.m_showContext != kMenuShowInactive && active) || 11147 (c.m_showContext != kMenuShowActive && !active)) 11205 11148 { 11206 if (toMask((PictureAttribute)i) & sup) 11149 result = true; 11150 if (c.m_doDisplay) 11207 11151 { 11208 if ((PictureAttribute)i == kPictureAttribute_StudioLevels) 11209 { 11210 QString msg = studio_levels ? tr("Disable studio levels") : 11211 tr("Enable studio levels"); 11212 osd->DialogAddButton(msg, ACTION_TOGGLESTUDIOLEVELS); 11213 } 11214 else 11215 { 11216 osd->DialogAddButton(toString((PictureAttribute) i), 11217 QString("TOGGLEPICCONTROLS%1").arg(i)); 11218 } 11152 QString text = c.m_actionText; 11153 if (text.isEmpty()) 11154 text = (active || defaultTextInactive.isEmpty()) ? 11155 defaultTextActive : defaultTextInactive; 11156 osd->DialogAddButton(text, action, isMenu, 11157 active && c.m_setCurrentActive); 11219 11158 } 11220 11159 } 11221 osd->DialogAddButton(11222 gCoreContext->GetNumSetting("NightModeEnabled", 0) ?11223 tr("Disable Night Mode") : tr("Enable Night Mode"),11224 ACTION_TOGGLENIGHTMODE);11225 }11226 else if (category == "3D")11227 {11228 backaction = "VIDEO";11229 currenttext = tr("3D");11230 osd->DialogAddButton(tr("None"),11231 ACTION_3DNONE, false,11232 stereomode == kStereoscopicModeNone);11233 osd->DialogAddButton(tr("Side by Side"),11234 ACTION_3DSIDEBYSIDE, false,11235 stereomode == kStereoscopicModeSideBySide);11236 osd->DialogAddButton(tr("Discard Side by Side"),11237 ACTION_3DSIDEBYSIDEDISCARD, false,11238 stereomode == kStereoscopicModeSideBySideDiscard);11239 osd->DialogAddButton(tr("Top and Bottom"),11240 ACTION_3DTOPANDBOTTOM, false,11241 stereomode == kStereoscopicModeTopAndBottom);11242 osd->DialogAddButton(tr("Discard Top and Bottom"),11243 ACTION_3DTOPANDBOTTOMDISCARD, false,11244 stereomode == kStereoscopicModeTopAndBottomDiscard);11245 }11246 else if (category == "ADVANCEDVIDEO")11247 {11248 osd->DialogAddButton(tr("Video Scan"),11249 "DIALOG_MENU_VIDEOSCAN_0", true,11250 selected == "VIDEOSCAN");11251 if (kScan_Progressive != scan_type)11252 {11253 osd->DialogAddButton(tr("Deinterlacer"),11254 "DIALOG_MENU_DEINTERLACER_0", true,11255 selected == "DEINTERLACER");11256 }11257 backaction = "VIDEO";11258 currenttext = tr("Advanced");11259 }11260 else if (category == "DEINTERLACER")11261 {11262 backaction = "ADVANCEDVIDEO";11263 currenttext = tr("Deinterlacer");11264 11265 QStringList deinterlacers;11266 QString currentdeinterlacer;11267 bool doublerate = false;11268 ctx->LockDeletePlayer(__FILE__, __LINE__);11269 if (ctx->player && ctx->player->GetVideoOutput())11270 {11271 ctx->player->GetVideoOutput()->GetDeinterlacers(deinterlacers);11272 currentdeinterlacer = ctx->player->GetVideoOutput()->GetDeinterlacer();11273 doublerate = ctx->player->CanSupportDoubleRate();11274 }11275 ctx->UnlockDeletePlayer(__FILE__, __LINE__);11276 11277 foreach (QString deint, deinterlacers)11278 {11279 if ((deint.contains("doublerate") ||11280 deint.contains("doubleprocess") ||11281 deint.contains("bobdeint")) && !doublerate)11282 {11283 continue;11284 }11285 QString trans = VideoDisplayProfile::GetDeinterlacerName(deint);11286 osd->DialogAddButton(trans, "DEINTERLACER_" + deint, false,11287 deint == currentdeinterlacer);11288 }11289 }11290 else if (category == "VIDEOSCAN")11291 {11292 backaction = "ADVANCEDVIDEO";11293 currenttext = tr("Video Scan");11294 11295 QString cur_mode = "";11296 if (!scan_type_locked)11297 {11298 if (kScan_Interlaced == scan_type)11299 cur_mode = tr("(I)", "Interlaced (Normal)");11300 else if (kScan_Intr2ndField == scan_type)11301 cur_mode = tr("(i)", "Interlaced (Reversed)");11302 else if (kScan_Progressive == scan_type)11303 cur_mode = tr("(P)", "Progressive");11304 cur_mode = " " + cur_mode;11305 scan_type = kScan_Detect;11306 }11307 11308 osd->DialogAddButton(tr("Detect") + cur_mode, "SELECTSCAN_0", false,11309 scan_type == kScan_Detect);11310 osd->DialogAddButton(tr("Progressive"), "SELECTSCAN_3", false,11311 scan_type == kScan_Progressive);11312 osd->DialogAddButton(tr("Interlaced (Normal)"), "SELECTSCAN_1", false,11313 scan_type == kScan_Interlaced);11314 osd->DialogAddButton(tr("Interlaced (Reversed)"), "SELECTSCAN_2", false,11315 scan_type == kScan_Intr2ndField);11316 }11317 }11318 11319 void TV::FillOSDMenuSubtitles(const PlayerContext *ctx, OSD *osd,11320 QString category, const QString selected,11321 QString ¤ttext, QString &backaction)11322 {11323 uint capmode = 0;11324 QStringList av_tracks;11325 QStringList cc708_tracks;11326 QStringList cc608_tracks;11327 QStringList ttx_tracks;11328 QStringList ttm_tracks;11329 QStringList text_tracks;11330 uint av_curtrack = ~0;11331 uint cc708_curtrack = ~0;11332 uint cc608_curtrack = ~0;11333 uint ttx_curtrack = ~0;11334 uint text_curtrack = ~0;11335 bool havetext = false;11336 bool forcedon = true;11337 bool enabled = false;11338 ctx->LockDeletePlayer(__FILE__, __LINE__);11339 if (ctx->player)11340 {11341 capmode = ctx->player->GetCaptionMode();11342 enabled = ctx->player->GetCaptionsEnabled();11343 havetext = ctx->player->HasTextSubtitles();11344 forcedon = ctx->player->GetAllowForcedSubtitles();11345 av_tracks = ctx->player->GetTracks(kTrackTypeSubtitle);11346 cc708_tracks = ctx->player->GetTracks(kTrackTypeCC708);11347 cc608_tracks = ctx->player->GetTracks(kTrackTypeCC608);11348 ttx_tracks = ctx->player->GetTracks(kTrackTypeTeletextCaptions);11349 ttm_tracks = ctx->player->GetTracks(kTrackTypeTeletextMenu);11350 text_tracks = ctx->player->GetTracks(kTrackTypeRawText);11351 if (!av_tracks.empty())11352 av_curtrack = (uint) ctx->player->GetTrack(kTrackTypeSubtitle);11353 if (!cc708_tracks.empty())11354 cc708_curtrack = (uint) ctx->player->GetTrack(kTrackTypeCC708);11355 if (!cc608_tracks.empty())11356 cc608_curtrack = (uint) ctx->player->GetTrack(kTrackTypeCC608);11357 if (!ttx_tracks.empty())11358 ttx_curtrack = (uint) ctx->player->GetTrack(kTrackTypeTeletextCaptions);11359 if (!text_tracks.empty())11360 text_curtrack = (uint) ctx->player->GetTrack(kTrackTypeRawText);11361 11160 } 11362 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 11161 } 11363 11162 11364 bool have_subs = !av_tracks.empty() || havetext || !cc708_tracks.empty() || 11365 !cc608_tracks.empty() || !ttx_tracks.empty() || 11366 !text_tracks.empty(); 11163 #define BUTTON(action, text) \ 11164 addButton(c, osd, active, result, (action), (text)) 11165 #define BUTTON2(action, textActive, textInactive) \ 11166 addButton(c, osd, active, result, (action), (textActive), (textInactive)) 11167 #define BUTTON3(action, textActive, textInactive, isMenu) \ 11168 addButton(c, osd, active, result, (action), (textActive), \ 11169 (textInactive), (isMenu)) 11367 11170 11368 if (category == "MAIN") 11171 // Returns true if at least one item should be displayed. 11172 bool TV::MenuDisplayItem(const MenuItemContext &c) 11173 { 11174 MenuCategory category = c.m_category; 11175 const QString &actionName = c.m_action; 11176 11177 bool result = false; 11178 bool active = true; 11179 PlayerContext *ctx = m_tvmCtx; 11180 OSD *osd = m_tvmOsd; 11181 if (!osd) 11182 return result; 11183 if (category == kMenuCategoryMenu) 11369 11184 { 11370 if (have_subs || !ttm_tracks.empty()) 11185 result = MenuShowHelper(c.m_node, QDomNode(), false); 11186 if (result && c.m_doDisplay) 11371 11187 { 11372 osd->DialogAddButton(tr("Subtitles"),11373 "DIALOG_MENU_SUBTITLES_0",11374 true, selected == "SUBTITLES");11188 QVariant v; 11189 v.setValue(c.m_node); 11190 osd->DialogAddButton(c.m_menuName, v, true, c.m_setCurrentActive); 11375 11191 } 11192 return result; 11376 11193 } 11377 else if (category == "SUBTITLES") 11194 ctx->LockDeletePlayer(__FILE__, __LINE__); 11195 QString prefix; 11196 if (matchesGroup(actionName, "VISUALISER_", category, prefix)) 11378 11197 { 11379 backaction = "MAIN"; 11380 currenttext = tr("Subtitles"); 11381 11382 uint capmode = ctx->player->GetCaptionMode(); 11383 if (have_subs && enabled) 11384 osd->DialogAddButton(tr("Disable Subtitles"), ACTION_DISABLESUBS); 11385 else if (have_subs && !enabled) 11386 osd->DialogAddButton(tr("Enable Subtitles"), ACTION_ENABLESUBS); 11387 if (!av_tracks.empty() || !text_tracks.empty()) 11388 { 11389 if (forcedon) 11390 { 11391 osd->DialogAddButton(tr("Disable Forced Subtitles"), 11392 ACTION_DISABLEFORCEDSUBS); 11393 } 11394 else 11395 { 11396 osd->DialogAddButton(tr("Enable Forced Subtitles"), 11397 ACTION_ENABLEFORCEDSUBS); 11398 } 11399 if (!av_tracks.empty()) 11400 osd->DialogAddButton(tr("Select Subtitle"), 11401 "DIALOG_MENU_AVSUBTITLES_0", 11402 true, selected == "AVSUBTITLES"); 11403 } 11404 if (havetext || !text_tracks.empty()) 11198 for (int i = 0; i < m_tvm_visualisers.size(); i++) 11405 11199 { 11406 osd->DialogAddButton(tr("Text Subtitles"),11407 "DIALOG_MENU_TEXTSUBTITLES_0",11408 true, selected == "TEXTSUBTITLES");11200 QString action = prefix + m_tvm_visualisers[i]; 11201 active = (m_tvm_active == m_tvm_visualisers[i]); 11202 BUTTON(action, m_tvm_visualisers[i]); 11409 11203 } 11410 if (!cc708_tracks.empty())11411 {11412 osd->DialogAddButton(tr("Select ATSC CC"),11413 "DIALOG_MENU_708SUBTITLES_0",11414 true, selected == "708SUBTITLES");11415 }11416 if (!cc608_tracks.empty())11417 {11418 osd->DialogAddButton(tr("Select VBI CC"),11419 "DIALOG_MENU_608SUBTITLES_0",11420 true, selected == "608SUBTITLES");11421 }11422 if (!ttx_tracks.empty())11423 {11424 osd->DialogAddButton(tr("Select Teletext CC"),11425 "DIALOG_MENU_TTXSUBTITLES_0",11426 true, selected == "TTXSUBTITLES");11427 }11428 if (!ttm_tracks.empty())11429 osd->DialogAddButton(tr("Toggle Teletext Menu"), "TOGGLETTM");11430 if (enabled)11431 osd->DialogAddButton(tr("Adjust Subtitle Zoom"),11432 ACTION_TOGGLESUBTITLEZOOM);11433 if (enabled &&11434 (capmode == kDisplayRawTextSubtitle ||11435 capmode == kDisplayTextSubtitle))11436 osd->DialogAddButton(tr("Adjust Subtitle Delay"),11437 ACTION_TOGGLESUBTITLEDELAY);11438 11204 } 11439 else if ( category == "AVSUBTITLES")11205 else if (matchesGroup(actionName, "TOGGLEASPECT", category, prefix)) 11440 11206 { 11441 backaction = "SUBTITLES"; 11442 currenttext = tr("Select Subtitle"); 11443 for (uint i = 0; i < (uint)av_tracks.size(); i++) 11207 if (ctx == GetPlayer(ctx, 0)) 11444 11208 { 11445 osd->DialogAddButton(av_tracks[i], 11446 "SELECTSUBTITLE_" + QString::number(i), 11447 false, i == av_curtrack); 11209 for (int j = kAspect_Off; j < kAspect_END; j++) 11210 { 11211 // swap 14:9 and 16:9 11212 int i = ((kAspect_14_9 == j) ? kAspect_16_9 : 11213 ((kAspect_16_9 == j) ? kAspect_14_9 : j)); 11214 QString action = prefix + QString::number(i); 11215 active = (m_tvm_aspectoverride == i); 11216 BUTTON(action, toString((AspectOverrideMode) i)); 11217 } 11448 11218 } 11449 11219 } 11450 else if ( category == "TEXTSUBTITLES")11220 else if (matchesGroup(actionName, "TOGGLEFILL", category, prefix)) 11451 11221 { 11452 backaction = "SUBTITLES"; 11453 currenttext = tr("Text Subtitles"); 11454 if (havetext) 11222 if (ctx == GetPlayer(ctx, 0)) 11455 11223 { 11456 if (capmode == kDisplayTextSubtitle) 11457 { 11458 osd->DialogAddButton(tr("Disable External Subtitles"), 11459 ACTION_DISABLEEXTTEXT); 11460 } 11461 else 11224 for (int i = kAdjustFill_Off; i < kAdjustFill_END; i++) 11462 11225 { 11463 osd->DialogAddButton(tr("Enable External Subtitles"), 11464 ACTION_ENABLEEXTTEXT); 11226 QString action = prefix + QString::number(i); 11227 active = (m_tvm_adjustfill == i); 11228 BUTTON(action, toString((AdjustFillMode) i)); 11465 11229 } 11466 11230 } 11467 if (!text_tracks.empty()) 11231 } 11232 else if (matchesGroup(actionName, "TOGGLEPICCONTROLS", category, prefix)) 11233 { 11234 if (ctx == GetPlayer(ctx, 0)) 11468 11235 { 11469 for ( uint i = 0; i < (uint)text_tracks.size(); i++)11236 for (int i = kPictureAttribute_MIN; i < kPictureAttribute_MAX; i++) 11470 11237 { 11471 osd->DialogAddButton(text_tracks[i], 11472 "SELECTRAWTEXT_" + QString::number(i), 11473 false, i == text_curtrack); 11238 if (toMask((PictureAttribute)i) & m_tvm_sup) 11239 { 11240 QString action = prefix + 11241 QString::number(i - kPictureAttribute_MIN); 11242 active = m_tvm_studio_levels; 11243 if ((PictureAttribute)i == kPictureAttribute_StudioLevels) 11244 BUTTON(ACTION_TOGGLESTUDIOLEVELS, 11245 toString((AdjustFillMode) i)); 11246 else 11247 BUTTON(action, toString((PictureAttribute) i)); 11248 } 11474 11249 } 11475 11250 } 11476 11251 } 11477 else if ( category == "708SUBTITLES")11252 else if (matchesGroup(actionName, "3D", category, prefix)) 11478 11253 { 11479 backaction = "SUBTITLES"; 11480 currenttext = tr("Select ATSC CC"); 11481 for (uint i = 0; i < (uint)cc708_tracks.size(); i++) 11254 if (m_tvm_stereoallowed) 11482 11255 { 11483 osd->DialogAddButton(cc708_tracks[i], 11484 "SELECTCC708_" + QString::number(i), 11485 false, i == cc708_curtrack); 11256 active = (m_tvm_stereomode == kStereoscopicModeNone); 11257 BUTTON(ACTION_3DNONE, tr("None")); 11258 active = (m_tvm_stereomode == kStereoscopicModeSideBySide); 11259 BUTTON(ACTION_3DSIDEBYSIDE, tr("Side by Side")); 11260 active = (m_tvm_stereomode == kStereoscopicModeSideBySideDiscard); 11261 BUTTON(ACTION_3DSIDEBYSIDEDISCARD, tr("Discard Side by Side")); 11262 active = (m_tvm_stereomode == kStereoscopicModeTopAndBottom); 11263 BUTTON(ACTION_3DTOPANDBOTTOM, tr("Top and Bottom")); 11264 active = (m_tvm_stereomode == kStereoscopicModeTopAndBottomDiscard); 11265 BUTTON(ACTION_3DTOPANDBOTTOMDISCARD, tr("Discard Top and Bottom")); 11486 11266 } 11487 11267 } 11488 else if ( category == "608SUBTITLES")11268 else if (matchesGroup(actionName, "SELECTSCAN_", category, prefix)) 11489 11269 { 11490 backaction = "SUBTITLES";11491 currenttext = tr("Select VBI CC");11492 for (uint i = 0; i < (uint)cc608_tracks.size(); i++)11493 {11494 osd->DialogAddButton(cc608_tracks[i],11495 "SELECTCC608_" + QString::number(i),11496 false, i == cc608_curtrack);11497 }11270 active = (m_tvm_scan_type_unlocked == kScan_Detect); 11271 BUTTON("SELECTSCAN_0", tr("Detect") + m_tvm_cur_mode); 11272 active = (m_tvm_scan_type_unlocked == kScan_Progressive); 11273 BUTTON("SELECTSCAN_3", tr("Progressive")); 11274 active = (m_tvm_scan_type_unlocked == kScan_Interlaced); 11275 BUTTON("SELECTSCAN_1", tr("Interlaced (Normal)")); 11276 active = (m_tvm_scan_type_unlocked == kScan_Intr2ndField); 11277 BUTTON("SELECTSCAN_2", tr("Interlaced (Reversed)")); 11498 11278 } 11499 else if ( category == "TTXSUBTITLES")11279 else if (matchesGroup(actionName, "DEINTERLACER_", category, prefix)) 11500 11280 { 11501 backaction = "SUBTITLES"; 11502 currenttext = tr("Select Teletext CC"); 11503 for (uint i = 0; i < (uint)ttx_tracks.size(); i++) 11281 if (m_tvm_scan_type != kScan_Progressive) 11504 11282 { 11505 osd->DialogAddButton(ttx_tracks[i], 11506 "SELECTTTC_" + QString::number(i), 11507 false, i == ttx_curtrack); 11508 } 11509 } 11510 } 11511 11512 void TV::FillOSDMenuNavigate(const PlayerContext *ctx, OSD *osd, 11513 QString category, const QString selected, 11514 QString ¤ttext, QString &backaction) 11515 { 11516 int num_chapters = GetNumChapters(ctx); 11517 int num_titles = GetNumTitles(ctx); 11518 int num_angles = GetNumAngles(ctx); 11519 TVState state = ctx->GetState(); 11520 bool isdvd = state == kState_WatchingDVD; 11521 bool isbd = ctx->buffer && ctx->buffer->IsBD() && 11522 ctx->buffer->BD()->IsHDMVNavigation(); 11523 bool islivetv = StateIsLiveTV(state); 11524 bool isrecording = state == kState_WatchingPreRecorded || 11525 state == kState_WatchingRecording; 11526 bool previouschan = false; 11527 if (islivetv) 11528 { 11529 QString prev_channum = ctx->GetPreviousChannel(); 11530 QString cur_channum = QString(); 11531 if (ctx->tvchain) 11532 cur_channum = ctx->tvchain->GetChannelName(-1); 11533 if (!prev_channum.isEmpty() && prev_channum != cur_channum) 11534 previouschan = true; 11283 foreach (QString deint, m_tvm_deinterlacers) 11284 { 11285 if ((deint.contains("doublerate") || 11286 deint.contains("doubleprocess") || 11287 deint.contains("bobdeint")) && !m_tvm_doublerate) 11288 { 11289 continue; 11290 } 11291 QString action = prefix + deint; 11292 active = (deint == m_tvm_currentdeinterlacer); 11293 QString trans = VideoDisplayProfile::GetDeinterlacerName(deint); 11294 BUTTON(action, trans); 11295 } 11296 } 11297 } 11298 else if (matchesGroup(actionName, "SELECTSUBTITLE_", category, prefix) || 11299 matchesGroup(actionName, "SELECTRAWTEXT_", category, prefix) || 11300 matchesGroup(actionName, "SELECTCC708_", category, prefix) || 11301 matchesGroup(actionName, "SELECTCC608_", category, prefix) || 11302 matchesGroup(actionName, "SELECTTTC_", category, prefix) || 11303 matchesGroup(actionName, "SELECTAUDIO_", category, prefix)) 11304 { 11305 int i = 0; 11306 TrackType type = kTrackTypeUnknown; 11307 if (prefix == "SELECTSUBTITLE_") 11308 type = kTrackTypeSubtitle; 11309 else if (prefix == "SELECTRAWTEXT_") 11310 type = kTrackTypeRawText; 11311 else if (prefix == "SELECTCC708_") 11312 type = kTrackTypeCC708; 11313 else if (prefix == "SELECTCC608_") 11314 type = kTrackTypeCC608; 11315 else if (prefix == "SELECTTTC_") 11316 type = kTrackTypeTeletextCaptions; 11317 else if (prefix == "SELECTAUDIO_") 11318 { 11319 type = kTrackTypeAudio; 11320 if (m_tvm_tracks[type].size() <= 1) 11321 i = 1; // don't show choices if only 1 audio track 11322 } 11323 11324 for (; i < m_tvm_tracks[type].size(); i++) 11325 { 11326 QString action = prefix + QString::number(i); 11327 active = (i == m_tvm_curtrack[type]); 11328 BUTTON(action, m_tvm_tracks[type][i]); 11329 } 11330 } 11331 else if (matchesGroup(actionName, "ADJUSTSTRETCH", category, prefix)) 11332 { 11333 static struct { 11334 int speedX100; 11335 QString suffix; 11336 QString trans; 11337 } speeds[] = { 11338 { 0, "", tr("Adjust")}, 11339 { 50, "0.5", tr("0.5x")}, 11340 { 90, "0.9", tr("0.9x")}, 11341 {100, "1.0", tr("1.0x")}, 11342 {110, "1.1", tr("1.1x")}, 11343 {120, "1.2", tr("1.2x")}, 11344 {130, "1.3", tr("1.3x")}, 11345 {140, "1.4", tr("1.4x")}, 11346 {150, "1.5", tr("1.5x")}, 11347 }; 11348 for (uint i = 0; i < sizeof(speeds) / sizeof(*speeds); ++i) 11349 { 11350 QString action = prefix + speeds[i].suffix; 11351 active = (m_tvm_speedX100 == speeds[i].speedX100); 11352 BUTTON(action, speeds[i].trans); 11353 } 11354 } 11355 else if (matchesGroup(actionName, "TOGGLESLEEP", category, prefix)) 11356 { 11357 active = false; 11358 if (sleepTimerId) 11359 BUTTON(ACTION_TOGGLESLEEP + "ON", tr("Sleep Off")); 11360 BUTTON(ACTION_TOGGLESLEEP + "30", tr("%n minute(s)", "", 30)); 11361 BUTTON(ACTION_TOGGLESLEEP + "60", tr("%n minute(s)", "", 60)); 11362 BUTTON(ACTION_TOGGLESLEEP + "90", tr("%n minute(s)", "", 90)); 11363 BUTTON(ACTION_TOGGLESLEEP + "120", tr("%n minute(s)", "", 120)); 11535 11364 } 11536 11537 bool jump = !num_chapters && !isdvd && !isbd && 11538 ctx->buffer->IsSeekingAllowed(); 11539 bool show = isdvd || num_chapters || num_titles || previouschan || 11540 isrecording || num_angles || jump; 11541 11542 if (category == "MAIN") 11365 else if (matchesGroup(actionName, "CHANGROUP_", category, prefix)) 11543 11366 { 11544 if ( show)11367 if (db_use_channel_groups) 11545 11368 { 11546 osd->DialogAddButton(tr("Navigate"), "DIALOG_MENU_NAVIGATE_0", 11547 true, selected == "NAVIGATE"); 11369 active = false; 11370 BUTTON("CHANGROUP_ALL_CHANNELS", tr("All Channels")); 11371 ChannelGroupList::const_iterator it; 11372 for (it = db_channel_groups.begin(); 11373 it != db_channel_groups.end(); ++it) 11374 { 11375 QString action = prefix + QString::number(it->grpid); 11376 active = ((int)(it->grpid) == channelGroupId); 11377 BUTTON(action, it->name); 11378 } 11548 11379 } 11549 11380 } 11550 else if ( category == "NAVIGATE")11381 else if (matchesGroup(actionName, "TOGGLECOMMSKIP", category, prefix)) 11551 11382 { 11552 backaction = "MAIN"; 11553 currenttext = tr("Navigate"); 11554 if (jump) 11555 { 11556 osd->DialogAddButton(tr("Jump Ahead"), ACTION_JUMPFFWD, false, false); 11557 osd->DialogAddButton(tr("Jump Back"), ACTION_JUMPRWND, false, false); 11558 } 11559 if (isrecording) 11560 { 11561 osd->DialogAddButton(tr("Commercial Auto-Skip"), 11562 "DIALOG_MENU_COMMSKIP_0", 11563 true, selected == "COMMSKIP"); 11564 } 11565 if (isbd) 11566 { 11567 osd->DialogAddButton(tr("Top menu"), ACTION_JUMPTODVDROOTMENU); 11568 osd->DialogAddButton(tr("Popup menu"), ACTION_JUMPTOPOPUPMENU); 11569 } 11570 if (isdvd) 11383 static uint cas_ord[] = { 0, 2, 1 }; 11384 if (m_tvm_isrecording || m_tvm_isrecorded) 11571 11385 { 11572 osd->DialogAddButton(tr("DVD Root Menu"), ACTION_JUMPTODVDROOTMENU); 11573 osd->DialogAddButton(tr("DVD Title Menu"), ACTION_JUMPTODVDTITLEMENU); 11574 osd->DialogAddButton(tr("DVD Chapter Menu"), ACTION_JUMPTODVDCHAPTERMENU); 11575 } 11576 if (previouschan) 11577 { 11578 osd->DialogAddButton(tr("Previous Channel"), "PREVCHAN"); 11579 } 11580 if (num_chapters) 11581 { 11582 osd->DialogAddButton(tr("Chapter"), "DIALOG_MENU_AVCHAPTER_0", 11583 true, selected == "AVCHAPTER"); 11584 } 11585 if (num_angles > 1) 11586 { 11587 osd->DialogAddButton(tr("Angle"), "DIALOG_MENU_AVANGLE_0", 11588 true, selected == "AVANGLE"); 11589 } 11590 if (num_titles) 11591 { 11592 osd->DialogAddButton(tr("Title"), "DIALOG_MENU_AVTITLE_0", 11593 true, selected == "AVTITLE"); 11386 for (uint i = 0; i < sizeof(cas_ord)/sizeof(cas_ord[0]); i++) 11387 { 11388 const CommSkipMode mode = (CommSkipMode) cas_ord[i]; 11389 QString action = prefix + QString::number(cas_ord[i]); 11390 active = (mode == m_tvm_curskip); 11391 BUTTON(action, toString((CommSkipMode) cas_ord[i])); 11392 } 11594 11393 } 11595 11394 } 11596 else if ( category == "AVCHAPTER")11395 else if (matchesGroup(actionName, "JUMPTOCHAPTER", category, prefix)) 11597 11396 { 11598 backaction = "NAVIGATE"; 11599 currenttext = tr("Chapter"); 11600 int current_chapter = GetCurrentChapter(ctx); 11601 QList<long long> times; 11602 GetChapterTimes(ctx, times); 11603 if (num_chapters == times.size()) 11397 if (m_tvm_num_chapters && 11398 m_tvm_num_chapters == m_tvm_chapter_times.size()) 11604 11399 { 11605 int size = QString::number( num_chapters).size();11606 for (int i = 0; i < num_chapters; i++)11400 int size = QString::number(m_tvm_num_chapters).size(); 11401 for (int i = 0; i < m_tvm_num_chapters; i++) 11607 11402 { 11608 int hours = times[i] / 60 / 60;11609 int minutes = ( times[i] / 60) - (hours * 60);11610 int secs = times[i] % 60;11403 int hours = m_tvm_chapter_times[i] / 60 / 60; 11404 int minutes = (m_tvm_chapter_times[i] / 60) - (hours * 60); 11405 int secs = m_tvm_chapter_times[i] % 60; 11611 11406 QString chapter1 = QString("%1").arg(i+1, size, 10, QChar(48)); 11612 11407 QString chapter2 = QString("%1").arg(i+1, 3 , 10, QChar(48)); 11613 11408 QString desc = chapter1 + QString(" (%1:%2:%3)") 11614 .arg(hours, 2, 10, QChar(48)).arg(minutes, 2, 10, QChar(48)) 11615 .arg(secs, 2, 10, QChar(48)); 11616 osd->DialogAddButton(desc, ACTION_JUMPCHAPTER + chapter2, 11617 false, current_chapter == (i + 1)); 11409 .arg(hours, 2, 10, QChar(48)) 11410 .arg(minutes, 2, 10, QChar(48)) 11411 .arg(secs, 2, 10, QChar(48)); 11412 QString action = prefix + chapter2; 11413 active = (m_tvm_current_chapter == (i + 1)); 11414 BUTTON(action, desc); 11618 11415 } 11619 11416 } 11620 11417 } 11621 else if ( category == "AVTITLE")11418 else if (matchesGroup(actionName, "SWITCHTOANGLE", category, prefix)) 11622 11419 { 11623 backaction = "NAVIGATE"; 11624 currenttext = tr("Title"); 11625 int current_title = GetCurrentTitle(ctx); 11626 11627 for (int i = 0; i < num_titles; i++) 11420 if (m_tvm_num_angles > 1) 11421 { 11422 for (int i = 1; i <= m_tvm_num_angles; i++) 11423 { 11424 QString angleIdx = QString("%1").arg(i, 3, 10, QChar(48)); 11425 QString desc = GetAngleName(ctx, i); 11426 QString action = prefix + angleIdx; 11427 active = (m_tvm_current_angle == i); 11428 BUTTON(action, desc); 11429 } 11430 } 11431 } 11432 else if (matchesGroup(actionName, "JUMPTOTITLE", category, prefix)) 11433 { 11434 for (int i = 0; i < m_tvm_num_titles; i++) 11628 11435 { 11629 11436 if (GetTitleDuration(ctx, i) < 120) // Ignore < 2 minutes long 11630 11437 continue; 11631 11438 11632 11439 QString titleIdx = QString("%1").arg(i, 3, 10, QChar(48)); 11633 11440 QString desc = GetTitleName(ctx, i); 11634 osd->DialogAddButton(desc, ACTION_SWITCHTITLE + titleIdx, 11635 false, current_title == i); 11441 QString action = prefix + titleIdx; 11442 active = (m_tvm_current_title == i); 11443 BUTTON(action, desc); 11636 11444 } 11637 11445 } 11638 else if ( category == "AVANGLE")11446 else if (matchesGroup(actionName, "SWITCHTOINPUT_", category, prefix)) 11639 11447 { 11640 backaction = "NAVIGATE"; 11641 currenttext = tr("Angle"); 11642 int current_angle = GetCurrentAngle(ctx); 11643 11644 for (int i = 1; i <= num_angles; i++) 11448 if (ctx->recorder) 11645 11449 { 11646 QString angleIdx = QString("%1").arg(i, 3, 10, QChar(48)); 11647 QString desc = GetAngleName(ctx, i); 11648 osd->DialogAddButton(desc, ACTION_SWITCHANGLE + angleIdx, 11649 false, current_angle == i); 11650 } 11651 } 11652 else if (category == "COMMSKIP") 11653 { 11654 backaction = "NAVIGATE"; 11655 currenttext = tr("Commercial Auto-Skip"); 11656 uint cas_ord[] = { 0, 2, 1 }; 11657 ctx->LockDeletePlayer(__FILE__, __LINE__); 11658 CommSkipMode cur = kCommSkipOff; 11659 if (ctx->player) 11660 cur = ctx->player->GetAutoCommercialSkip(); 11661 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 11450 vector<uint> cardids = CardUtil::GetCardList(); 11451 uint cardid = ctx->GetCardID(); 11452 vector<uint> excluded_cardids; 11453 stable_sort(cardids.begin(), cardids.end()); 11454 excluded_cardids.push_back(cardid); 11455 vector<uint>::const_iterator it = cardids.begin(); 11456 InfoMap info; 11457 ctx->recorder->GetChannelInfo(info); 11458 uint sourceid = info["sourceid"].toUInt(); 11459 for (; it != cardids.end(); ++it) 11460 { 11461 vector<InputInfo> inputs = 11462 RemoteRequestFreeInputList(*it, excluded_cardids); 11662 11463 11663 for (uint i = 0; i < sizeof(cas_ord)/sizeof(uint); i++) 11664 { 11665 const CommSkipMode mode = (CommSkipMode) cas_ord[i]; 11666 osd->DialogAddButton(toString((CommSkipMode) cas_ord[i]), 11667 QString("TOGGLECOMMSKIP%1").arg(cas_ord[i]), 11668 false, mode == cur); 11669 } 11670 } 11671 } 11464 for (uint i = 0; i < inputs.size(); i++) 11465 { 11466 // don't add current input to list 11467 if ((inputs[i].cardid == cardid) && 11468 (inputs[i].sourceid == sourceid)) 11469 { 11470 continue; 11471 } 11672 11472 11673 void TV::FillOSDMenuSource(const PlayerContext *ctx, OSD *osd, 11674 QString category, const QString selected, 11675 QString ¤ttext, QString &backaction) 11676 { 11677 QMap<uint,InputInfo> sources; 11678 vector<uint> cardids; 11679 uint cardid = 0; 11680 vector<uint> excluded_cardids; 11681 uint sourceid = 0; 11473 QString name = CardUtil::GetDisplayName(inputs[i].inputid); 11474 if (name.isEmpty()) 11475 { 11476 name = tr("C", "Card") + ":" + 11477 QString::number(*it) + " " + 11478 tr("I", "Input") + ":" + inputs[i].name; 11479 } 11682 11480 11683 if ((category == "SOURCE" || category == "INPUTSWITCHING"|| 11684 category == "SOURCESWITCHING") && ctx->recorder) 11481 QString action = prefix + 11482 QString::number(inputs[i].inputid); 11483 active = false; 11484 BUTTON(action, name); 11485 } 11486 } 11487 } 11488 } 11489 else if (matchesGroup(actionName, "SWITCHTOSOURCE_", category, prefix)) 11685 11490 { 11686 cardids = CardUtil::GetCardList(); 11687 cardid = ctx->GetCardID(); 11688 // The cardids are already in the preferred order. Don't 11689 // alter it if switching sources. 11690 if (category != "SOURCESWITCHING") 11691 stable_sort(cardids.begin(), cardids.end()); 11692 excluded_cardids.push_back(cardid); 11693 InfoMap info; 11694 ctx->recorder->GetChannelInfo(info); 11695 sourceid = info["sourceid"].toUInt(); 11696 11697 if (category != "INPUTSWITCHING") 11491 if (ctx->recorder) 11698 11492 { 11493 QMap<uint,InputInfo> sources; 11494 vector<uint> cardids; 11495 uint cardid = 0; 11496 vector<uint> excluded_cardids; 11497 uint sourceid = 0; 11498 cardids = CardUtil::GetCardList(); 11499 cardid = ctx->GetCardID(); 11500 excluded_cardids.push_back(cardid); 11501 InfoMap info; 11502 ctx->recorder->GetChannelInfo(info); 11503 sourceid = info["sourceid"].toUInt(); 11699 11504 // Get sources available on other cards 11700 11505 vector<uint>::const_iterator it = cardids.begin(); 11701 11506 for (; it != cardids.end(); ++it) 11702 11507 { 11703 11508 vector<InputInfo> inputs = 11704 RemoteRequestFreeInputList(*it, excluded_cardids);11509 RemoteRequestFreeInputList(*it, excluded_cardids); 11705 11510 if (inputs.empty()) 11706 11511 continue; 11707 11512 11708 11513 for (uint i = 0; i < inputs.size(); i++) 11709 11514 if (!sources.contains(inputs[i].sourceid)) 11710 sources[inputs[i].sourceid] = inputs[i];11515 sources[inputs[i].sourceid] = inputs[i]; 11711 11516 } 11712 11517 // Get other sources available on this card 11713 11518 vector<uint> currentinputs = CardUtil::GetInputIDs(cardid); … … void TV::FillOSDMenuSource(const PlayerContext *ctx, OSD *osd, 11725 11530 } 11726 11531 // delete current source from list 11727 11532 sources.remove(sourceid); 11533 QMap<uint,InputInfo>::const_iterator sit = sources.begin(); 11534 for (; sit != sources.end(); ++sit) 11535 { 11536 QString action = QString("SWITCHTOINPUT_%1").arg((*sit).inputid); 11537 BUTTON(action, SourceUtil::GetSourceName((*sit).sourceid)); 11538 } 11728 11539 } 11729 11540 } 11730 11731 if (category == "MAIN") 11732 { 11733 osd->DialogAddButton(tr("Source"), "DIALOG_MENU_SOURCE_0", 11734 true, selected == "SOURCE"); 11735 } 11736 else if (category == "SOURCE") 11541 else if (category == kMenuCategoryItem) 11737 11542 { 11738 backaction = "MAIN"; 11739 currenttext = tr("Source"); 11740 osd->DialogAddButton(tr("Jump to Program"), 11741 "DIALOG_MENU_" + ACTION_JUMPREC + "_0", 11742 true, selected == ACTION_JUMPREC); 11743 11744 vector<uint>::const_iterator it = cardids.begin(); 11745 for (; it != cardids.end(); ++it) 11543 if (actionName == "TOGGLEAUDIOSYNC") 11544 { 11545 BUTTON(actionName, tr("Adjust Audio Sync")); 11546 } 11547 else if (actionName == "DISABLEVISUALISATION") 11746 11548 { 11747 vector<InputInfo> inputs = RemoteRequestFreeInputList( 11748 *it, excluded_cardids); 11749 uint testsize = 0; 11750 for (uint i = 0; i < inputs.size(); i++) 11549 if (m_tvm_visual) 11550 BUTTON(actionName, tr("None")); 11551 } 11552 else if (actionName == "DISABLEUPMIX") 11553 { 11554 if (m_tvm_canupmix) 11751 11555 { 11752 if ((inputs[i].cardid == cardid) && 11753 (inputs[i].sourceid == sourceid)) 11754 { 11755 testsize = 1; 11756 break; 11757 } 11556 active = !m_tvm_upmixing; 11557 BUTTON(actionName, tr("Disable Audio Upmixer")); 11758 11558 } 11759 if (inputs.size() <= testsize)11760 continue;11761 osd->DialogAddButton(tr("Switch Input"),11762 "DIALOG_MENU_INPUTSWITCHING_0",11763 true, selected == "INPUTSWITCHING");11764 break;11765 11559 } 11766 if (!sources.empty())11560 else if (actionName == "ENABLEUPMIX") 11767 11561 { 11768 osd->DialogAddButton(tr("Switch Source"), 11769 "DIALOG_MENU_SOURCESWITCHING_0", 11770 true, selected == "SOURCESWITCHING"); 11562 if (m_tvm_canupmix) 11563 { 11564 active = m_tvm_upmixing; 11565 BUTTON(actionName, tr("Auto Detect")); 11566 } 11771 11567 } 11772 } 11773 else if (category == ACTION_JUMPREC) 11774 { 11775 backaction = "SOURCE"; 11776 currenttext = tr("Jump to Program"); 11777 osd->DialogAddButton(tr("Recorded Program"), 11778 "DIALOG_" + ACTION_JUMPREC + "_X_0", 11779 true, selected == ACTION_JUMPREC + "2"); 11780 if (lastProgram != NULL) 11568 else if (actionName == "AUTODETECT_FILL") 11781 11569 { 11782 if (lastProgram->GetSubtitle().isEmpty()) 11783 osd->DialogAddButton(lastProgram->GetTitle(), ACTION_JUMPPREV); 11784 else 11785 osd->DialogAddButton(QString("%1: %2") 11786 .arg(lastProgram->GetTitle()) 11787 .arg(lastProgram->GetSubtitle()), ACTION_JUMPPREV); 11570 if (m_tvm_fill_autodetect) 11571 { 11572 active = 11573 (m_tvm_adjustfill == kAdjustFill_AutoDetect_DefaultHalf) || 11574 (m_tvm_adjustfill == kAdjustFill_AutoDetect_DefaultOff); 11575 BUTTON(actionName, tr("Auto Detect")); 11576 } 11788 11577 } 11789 } 11790 else if (category == "INPUTSWITCHING") 11791 { 11792 backaction = "SOURCE"; 11793 currenttext = tr("Switch Input"); 11794 vector<uint>::const_iterator it = cardids.begin(); 11795 for (; it != cardids.end(); ++it) 11578 else if (actionName == "TOGGLEMANUALZOOM") 11796 11579 { 11797 vector<InputInfo> inputs = RemoteRequestFreeInputList( 11798 *it, excluded_cardids);; 11799 11800 for (uint i = 0; i < inputs.size(); i++) 11580 BUTTON(actionName, tr("Manual Zoom Mode")); 11581 } 11582 else if (actionName == "TOGGLENIGHTMODE") 11583 { 11584 if (m_tvm_sup != kPictureAttributeSupported_None) 11801 11585 { 11802 // don't add current input to list 11803 if ((inputs[i].cardid == cardid) && 11804 (inputs[i].sourceid == sourceid)) 11805 { 11806 continue; 11807 } 11808 11809 QString name = CardUtil::GetDisplayName(inputs[i].inputid); 11810 if (name.isEmpty()) 11811 { 11812 name = tr("C", "Card") + ":" + QString::number(*it) + " " + 11813 tr("I", "Input") + ":" + inputs[i].name; 11814 } 11815 11816 osd->DialogAddButton(name, 11817 QString("SWITCHTOINPUT_%1").arg(inputs[i].inputid)); 11586 active = gCoreContext->GetNumSetting("NightModeEnabled", 0); 11587 BUTTON2(actionName, 11588 tr("Disable Night Mode"), tr("Enable Night Mode")); 11818 11589 } 11819 11590 } 11820 } 11821 else if (category == "SOURCESWITCHING") 11822 { 11823 backaction = "SOURCE"; 11824 currenttext = tr("Switch Source"); 11825 QMap<uint,InputInfo>::const_iterator sit = sources.begin(); 11826 for (; sit != sources.end(); ++sit) 11591 else if (actionName == "DISABLESUBS") 11827 11592 { 11828 osd->DialogAddButton(SourceUtil::GetSourceName((*sit).sourceid), 11829 QString("SWITCHTOINPUT_%1").arg((*sit).inputid)); 11593 active = !m_tvm_subs_enabled; 11594 if (m_tvm_subs_have_subs) 11595 BUTTON(actionName, tr("Disable Subtitles")); 11830 11596 } 11831 } 11832 } 11833 11834 void TV::FillOSDMenuJobs(const PlayerContext *ctx, OSD *osd, 11835 QString category, const QString selected, 11836 QString ¤ttext, QString &backaction) 11837 { 11838 TVState state = ctx->GetState(); 11839 bool islivetv = StateIsLiveTV(state); 11840 bool isrecorded = state == kState_WatchingPreRecorded; 11841 bool isrecording = state == kState_WatchingRecording; 11842 bool isvideo = state == kState_WatchingVideo; 11843 11844 if (category == "MAIN") 11845 { 11846 if (islivetv || isrecording || isrecorded || isvideo) 11597 else if (actionName == "ENABLESUBS") 11847 11598 { 11848 osd->DialogAddButton(tr("Jobs"), "DIALOG_MENU_JOBS_0", 11849 true, selected == "JOBS"); 11599 active = m_tvm_subs_enabled; 11600 if (m_tvm_subs_have_subs) 11601 BUTTON(actionName, tr("Enable Subtitles")); 11850 11602 } 11851 } 11852 else if (category == "JOBS") 11853 { 11854 backaction = "MAIN"; 11855 currenttext = tr("Jobs"); 11856 11857 ctx->LockPlayingInfo(__FILE__, __LINE__); 11858 bool is_on = ctx->playingInfo->QueryAutoExpire() != kDisableAutoExpire; 11859 bool transcoding = JobQueue::IsJobQueuedOrRunning( 11860 JOB_TRANSCODE, 11861 ctx->playingInfo->GetChanID(), 11862 ctx->playingInfo->GetScheduledStartTime()); 11863 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 11864 11865 if (islivetv) 11603 else if (actionName == "DISABLEFORCEDSUBS") 11866 11604 { 11867 osd->DialogAddButton(tr("Edit Channel"), "EDIT"); 11605 active = !m_tvm_subs_forcedon; 11606 if (!m_tvm_tracks[kTrackTypeSubtitle].empty() || 11607 !m_tvm_tracks[kTrackTypeRawText].empty()) 11608 { 11609 BUTTON(actionName, tr("Disable Forced Subtitles")); 11610 } 11868 11611 } 11869 11870 if (isrecorded || isrecording || isvideo) 11612 else if (actionName == "ENABLEFORCEDSUBS") 11871 11613 { 11872 osd->DialogAddButton(tr("Edit Recording"), "EDIT"); 11614 active = m_tvm_subs_forcedon; 11615 if (!m_tvm_tracks[kTrackTypeSubtitle].empty() || 11616 !m_tvm_tracks[kTrackTypeRawText].empty()) 11617 { 11618 BUTTON(actionName, tr("Enable Forced Subtitles")); 11619 } 11873 11620 } 11874 11875 if (isrecorded || isrecording) 11621 else if (actionName == "DISABLEEXTTEXT") 11876 11622 { 11877 osd->DialogAddButton(is_on ? tr("Turn Auto-Expire OFF") : 11878 tr("Turn Auto-Expire ON"), "TOGGLEAUTOEXPIRE"); 11623 active = m_tvm_subs_capmode != kDisplayTextSubtitle; 11624 if (m_tvm_subs_havetext) 11625 BUTTON(actionName, tr("Disable External Subtitles")); 11879 11626 } 11880 11881 if (isrecorded) 11627 else if (actionName == "ENABLEEXTTEXT") 11628 { 11629 active = m_tvm_subs_capmode == kDisplayTextSubtitle; 11630 if (m_tvm_subs_havetext) 11631 BUTTON(actionName, tr("Enable External Subtitles")); 11632 } 11633 else if (actionName == "TOGGLETTM") 11634 { 11635 if (!m_tvm_tracks[kTrackTypeTeletextMenu].empty()) 11636 BUTTON(actionName, tr("Toggle Teletext Menu")); 11637 } 11638 else if (actionName == "TOGGLESUBZOOM") 11639 { 11640 if (m_tvm_subs_enabled) 11641 BUTTON(actionName, tr("Adjust Subtitle Zoom")); 11642 } 11643 else if (actionName == "TOGGLESUBDELAY") 11882 11644 { 11883 if (transcoding) 11645 if (m_tvm_subs_enabled && 11646 (m_tvm_subs_capmode == kDisplayRawTextSubtitle || 11647 m_tvm_subs_capmode == kDisplayTextSubtitle)) 11884 11648 { 11885 osd->DialogAddButton(tr("Stop Transcoding"), "QUEUETRANSCODE");11649 BUTTON(actionName, tr("Adjust Subtitle Delay")); 11886 11650 } 11887 else 11651 } 11652 else if (actionName == "PAUSE") 11653 { 11654 active = m_tvm_ispaused; 11655 BUTTON2(actionName, tr("Play"), tr("Pause")); 11656 } 11657 else if (actionName == "TOGGLESTRETCH") 11658 { 11659 BUTTON(actionName, tr("Toggle")); 11660 } 11661 else if (actionName == "CREATEPIPVIEW") 11662 { 11663 MenuLazyInit(&m_tvm_freerecordercount); 11664 if (m_tvm_freerecordercount && 11665 player.size() <= kMaxPIPCount && !m_tvm_hasPBP && m_tvm_allowPIP) 11888 11666 { 11889 osd->DialogAddButton(tr("Begin Transcoding"), 11890 "DIALOG_MENU_TRANSCODE_0", 11891 true, selected == "TRANSCODE"); 11667 BUTTON(actionName, tr("Open Live TV PIP")); 11892 11668 } 11893 11669 } 11894 } 11895 else if (category == "TRANSCODE") 11896 { 11897 backaction = "JOBS"; 11898 currenttext = tr("Begin Transcoding"); 11899 osd->DialogAddButton(tr("Default"), "QUEUETRANSCODE"); 11900 osd->DialogAddButton(tr("Autodetect"), "QUEUETRANSCODE_AUTO"); 11901 osd->DialogAddButton(tr("High Quality"), "QUEUETRANSCODE_HIGH"); 11902 osd->DialogAddButton(tr("Medium Quality"),"QUEUETRANSCODE_MEDIUM"); 11903 osd->DialogAddButton(tr("Low Quality"), "QUEUETRANSCODE_LOW"); 11904 } 11905 } 11906 11907 void TV::FillOSDMenuPlayback(const PlayerContext *ctx, OSD *osd, 11908 QString category, const QString selected, 11909 QString ¤ttext, QString &backaction) 11910 { 11911 bool allowPIP = IsPIPSupported(ctx); 11912 bool allowPBP = IsPBPSupported(ctx); 11913 bool ispaused = false; 11914 ctx->LockDeletePlayer(__FILE__, __LINE__); 11915 if (ctx->player) 11916 ispaused = ctx->player->IsPaused(); 11917 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 11918 11919 if (category == "MAIN") 11920 { 11921 osd->DialogAddButton(tr("Playback"), "DIALOG_MENU_PLAYBACK_0", 11922 true, selected == "PLAYBACK"); 11923 } 11924 else if (category == "PLAYBACK") 11925 { 11926 backaction = "MAIN"; 11927 currenttext = tr("Playback"); 11928 11929 osd->DialogAddButton(ispaused ? tr("Play") : tr("Pause"), 11930 ACTION_PAUSE, false, false); 11931 osd->DialogAddButton(tr("Adjust Time Stretch"), 11932 "DIALOG_MENU_TIMESTRETCH_0", true, 11933 selected == "TIMESTRETCH"); 11934 if (allowPIP || allowPBP) 11670 else if (actionName == "CREATEPBPVIEW") 11935 11671 { 11936 osd->DialogAddButton(tr("Picture-in-Picture"), 11937 "DIALOG_MENU_PIP_1", true, 11938 selected == "PIP"); 11672 MenuLazyInit(&m_tvm_freerecordercount); 11673 if (m_tvm_freerecordercount && 11674 player.size() < kMaxPBPCount && !m_tvm_hasPIP && m_tvm_allowPBP) 11675 { 11676 BUTTON(actionName, tr("Open Live TV PBP")); 11677 } 11939 11678 } 11940 osd->DialogAddButton(tr("Sleep"), 11941 "DIALOG_MENU_SLEEP_0", true, 11942 selected == "SLEEP"); 11943 if (db_use_channel_groups) 11679 else if (actionName == "JUMPRECPIP") 11944 11680 { 11945 osd->DialogAddButton(tr("Channel Groups"), 11946 "DIALOG_MENU_CHANNELGROUP_0", 11947 true, selected == "CHANNELGROUP"); 11948 } 11949 if (!db_browse_always) 11950 osd->DialogAddButton(tr("Toggle Browse Mode"), "TOGGLEBROWSE"); 11951 if (inPlaylist) 11952 osd->DialogAddButton(tr("Cancel Playlist"), "CANCELPLAYLIST"); 11953 osd->DialogAddButton(tr("Playback data"), 11954 ACTION_TOGGLEOSDDEBUG, false, false); 11955 } 11956 else if (category == "TIMESTRETCH") 11957 { 11958 backaction = "PLAYBACK"; 11959 currenttext = tr("Adjust Time Stretch"); 11960 int speedX100 = (int)(round(ctx->ts_normal * 100)); 11961 osd->DialogAddButton(tr("Toggle"), "TOGGLESTRETCH"); 11962 osd->DialogAddButton(tr("Adjust"), "ADJUSTSTRETCH"); 11963 osd->DialogAddButton(tr("0.5X"), "ADJUSTSTRETCH0.5", false, speedX100 == 50); 11964 osd->DialogAddButton(tr("0.9X"), "ADJUSTSTRETCH0.9", false, speedX100 == 90); 11965 osd->DialogAddButton(tr("1.0X"), "ADJUSTSTRETCH1.0", false, speedX100 == 100); 11966 osd->DialogAddButton(tr("1.1X"), "ADJUSTSTRETCH1.1", false, speedX100 == 110); 11967 osd->DialogAddButton(tr("1.2X"), "ADJUSTSTRETCH1.2", false, speedX100 == 120); 11968 osd->DialogAddButton(tr("1.3X"), "ADJUSTSTRETCH1.3", false, speedX100 == 130); 11969 osd->DialogAddButton(tr("1.4X"), "ADJUSTSTRETCH1.4", false, speedX100 == 140); 11970 osd->DialogAddButton(tr("1.5X"), "ADJUSTSTRETCH1.5", false, speedX100 == 150); 11971 } 11972 else if (category == "SLEEP") 11973 { 11974 backaction = "PLAYBACK"; 11975 currenttext = tr("Sleep"); 11976 if (sleepTimerId) 11977 osd->DialogAddButton(tr("Sleep Off"), ACTION_TOGGLESLEEP + "ON"); 11978 osd->DialogAddButton(tr("%n minute(s)", "", 30), 11979 ACTION_TOGGLESLEEP + "30"); 11980 osd->DialogAddButton(tr("%n minute(s)", "", 60), 11981 ACTION_TOGGLESLEEP + "60"); 11982 osd->DialogAddButton(tr("%n minute(s)", "", 90), 11983 ACTION_TOGGLESLEEP + "90"); 11984 osd->DialogAddButton(tr("%n minute(s)", "", 120), 11985 ACTION_TOGGLESLEEP + "120"); 11986 } 11987 else if (category == "CHANNELGROUP") 11988 { 11989 backaction = "PLAYBACK"; 11990 currenttext = tr("Channel Groups"); 11991 osd->DialogAddButton(tr("All Channels"), "CHANGROUP_ALL_CHANNELS"); 11992 ChannelGroupList::const_iterator it; 11993 for (it = db_channel_groups.begin(); 11994 it != db_channel_groups.end(); ++it) 11681 if (player.size() <= kMaxPIPCount && 11682 !m_tvm_hasPBP && m_tvm_allowPIP) 11683 { 11684 BUTTON(actionName, tr("Open Recording PIP")); 11685 } 11686 } 11687 else if (actionName == "JUMPRECPBP") 11995 11688 { 11996 osd->DialogAddButton(it->name, 11997 QString("CHANGROUP_%1").arg(it->grpid), 11998 false, (int)(it->grpid) == channelGroupId); 11689 if (player.size() < kMaxPBPCount && 11690 !m_tvm_hasPIP && m_tvm_allowPBP) 11691 { 11692 BUTTON(actionName, tr("Open Recording PBP")); 11693 } 11999 11694 } 12000 } 12001 else if (category == "PIP" && (allowPIP || allowPBP)) 12002 { 12003 backaction = "PLAYBACK"; 12004 currenttext = tr("Picture-in-Picture"); 12005 bool hasPBP = (player.size()>1) && GetPlayer(ctx,1)->IsPBP(); 12006 bool hasPIP = (player.size()>1) && GetPlayer(ctx,1)->IsPIP(); 12007 12008 if (RemoteGetFreeRecorderCount()) 11695 else if (actionName == "NEXTPIPWINDOW") 12009 11696 { 12010 if (player.size() <= kMaxPIPCount && !hasPBP && allowPIP) 12011 osd->DialogAddButton(tr("Open Live TV PIP"), "CREATEPIPVIEW"); 12012 if (player.size() < kMaxPBPCount && !hasPIP && allowPBP) 12013 osd->DialogAddButton(tr("Open Live TV PBP"), "CREATEPBPVIEW"); 11697 if (player.size() > 1) 11698 BUTTON(actionName, tr("Change Active Window")); 12014 11699 } 12015 12016 if (player.size() <= kMaxPIPCount && !hasPBP && allowPIP) 12017 osd->DialogAddButton(tr("Open Recording PIP"), "JUMPRECPIP"); 12018 if (player.size() < kMaxPBPCount && !hasPIP && allowPBP) 12019 osd->DialogAddButton(tr("Open Recording PBP"), "JUMPRECPBP"); 12020 12021 if (player.size() > 1) 11700 else if (actionName == "TOGGLEPIPMODE") 12022 11701 { 12023 osd->DialogAddButton(tr("Change Active Window"), "NEXTPIPWINDOW"); 12024 12025 QString pipType = (ctx->IsPBP()) ? "PBP" : "PIP"; 12026 QString toggleMode = QString("TOGGLE%1MODE").arg(pipType); 12027 12028 bool isPBP = ctx->IsPBP(); 12029 const PlayerContext *mctx = GetPlayer(ctx, 0); 12030 QString pipClose = (isPBP) ? tr("Close PBP") : tr("Close PIP"); 12031 if (mctx == ctx) 11702 if (player.size() > 1) 12032 11703 { 12033 if (player.size() > 2) 12034 pipClose = (isPBP) ? tr("Close PBPs") : tr("Close PIPs"); 12035 osd->DialogAddButton(pipClose, toggleMode); 12036 12037 if (player.size() == 2) 12038 osd->DialogAddButton(tr("Swap Windows"), "SWAPPIP"); 11704 const PlayerContext *mctx = GetPlayer(ctx, 0); 11705 const PlayerContext *octx = GetPlayer(ctx, 1); 11706 if (mctx == ctx && octx->IsPIP()) 11707 BUTTON(actionName, tr("Close PIP(s)", 0, player.size() - 1)); 12039 11708 } 12040 else 11709 } 11710 else if (actionName == "TOGGLEPBPMODE") 11711 { 11712 if (player.size() > 1) 12041 11713 { 12042 osd->DialogAddButton(pipClose, toggleMode); 12043 osd->DialogAddButton(tr("Swap Windows"), "SWAPPIP"); 11714 const PlayerContext *mctx = GetPlayer(ctx, 0); 11715 const PlayerContext *octx = GetPlayer(ctx, 1); 11716 if (mctx == ctx && octx->IsPBP()) 11717 BUTTON(actionName, tr("Close PBP(s)", 0, player.size() - 1)); 12044 11718 } 12045 11719 } 11720 else if (actionName == "SWAPPIP") 11721 { 11722 const PlayerContext *mctx = GetPlayer(ctx, 0); 11723 if (mctx != ctx || player.size() == 2) 11724 BUTTON(actionName, tr("Swap Windows")); 11725 } 11726 else if (actionName == "TOGGLEPIPSTATE") 11727 { 12046 11728 uint max_cnt = min(kMaxPBPCount, kMaxPIPCount+1); 12047 11729 if (player.size() <= max_cnt && 12048 !(hasPIP && !allowPBP) && 12049 !(hasPBP && !allowPIP)) 11730 !(m_tvm_hasPIP && !m_tvm_allowPBP) && 11731 !(m_tvm_hasPBP && !m_tvm_allowPIP)) 11732 { 11733 active = !m_tvm_hasPBP; 11734 BUTTON2(actionName, tr("Switch to PBP"), tr("Switch to PIP")); 11735 } 11736 } 11737 else if (actionName == "TOGGLEBROWSE") 11738 { 11739 if (db_use_channel_groups) 11740 BUTTON(actionName, tr("Toggle Browse Mode")); 11741 } 11742 else if (actionName == "CANCELPLAYLIST") 11743 { 11744 if (inPlaylist) 11745 BUTTON(actionName, tr("Cancel Playlist")); 11746 } 11747 else if (actionName == "DEBUGOSD") 11748 { 11749 BUTTON(actionName, tr("Playback Data")); 11750 } 11751 else if (actionName == "JUMPFFWD") 11752 { 11753 if (m_tvm_jump) 11754 BUTTON(actionName, tr("Jump Ahead")); 11755 } 11756 else if (actionName == "JUMPRWND") 11757 { 11758 if (m_tvm_jump) 11759 BUTTON(actionName, tr("Jump Back")); 11760 } 11761 else if (actionName == "JUMPTODVDROOTMENU") 11762 { 11763 if (m_tvm_isbd || m_tvm_isdvd) 11764 { 11765 active = m_tvm_isdvd; 11766 BUTTON2(actionName, tr("DVD Root Menu"), tr("Top menu")); 11767 } 11768 } 11769 else if (actionName == "JUMPTOPOPUPMENU") 11770 { 11771 if (m_tvm_isbd) 11772 BUTTON(actionName, tr("Popup menu")); 11773 } 11774 else if (actionName == "JUMPTODVDTITLEMENU") 11775 { 11776 if (m_tvm_isdvd) 11777 BUTTON(actionName, tr("DVD Title Menu")); 11778 } 11779 else if (actionName == "JUMPTODVDCHAPTERMENU") 11780 { 11781 if (m_tvm_isdvd) 11782 BUTTON(actionName, tr("DVD Chapter Menu")); 11783 } 11784 else if (actionName == "PREVCHAN") 11785 { 11786 if (m_tvm_previouschan) 11787 BUTTON(actionName, tr("Previous Channel")); 11788 } 11789 else if (actionName == "GUIDE") 11790 { 11791 BUTTON(actionName, tr("Program Guide")); 11792 } 11793 else if (actionName == "FINDER") 11794 { 11795 BUTTON(actionName, tr("Program Finder")); 11796 } 11797 else if (actionName == "VIEWSCHEDULED") 11798 { 11799 BUTTON(actionName, tr("Upcoming Recordings")); 11800 } 11801 else if (actionName == "SCHEDULE") 11802 { 11803 BUTTON(actionName, tr("Edit Recording Schedule")); 11804 } 11805 else if (actionName == "DIALOG_JUMPREC_X_0") 11806 { 11807 BUTTON3(actionName, tr("Recorded Program"), "", true); 11808 QVariant v; 11809 v.setValue(c.m_node); 11810 m_tvm_jumprec_back_hack = v; 11811 } 11812 else if (actionName == "JUMPPREV") 11813 { 11814 if (lastProgram != NULL) 12050 11815 { 12051 QString switchTo = (isPBP) ? tr("Switch to PIP") : tr("Switch to PBP"); 12052 osd->DialogAddButton(switchTo, "TOGGLEPIPSTATE"); 11816 if (lastProgram->GetSubtitle().isEmpty()) 11817 BUTTON(actionName, lastProgram->GetTitle()); 11818 else 11819 BUTTON(actionName, 11820 QString("%1: %2") 11821 .arg(lastProgram->GetTitle()) 11822 .arg(lastProgram->GetSubtitle())); 11823 } 11824 } 11825 else if (actionName == "EDIT") 11826 { 11827 if (m_tvm_islivetv || m_tvm_isrecorded || 11828 m_tvm_isrecording || m_tvm_isvideo) 11829 { 11830 active = m_tvm_islivetv; 11831 BUTTON2(actionName, tr("Edit Channel"), tr("Edit Recording")); 12053 11832 } 12054 11833 } 11834 else if (actionName == "TOGGLEAUTOEXPIRE") 11835 { 11836 if (m_tvm_isrecorded || m_tvm_isrecording) 11837 { 11838 active = m_tvm_is_on; 11839 BUTTON2(actionName, 11840 tr("Turn Auto-Expire OFF"), tr("Turn Auto-Expire ON")); 11841 } 11842 } 11843 else if (actionName == "QUEUETRANSCODE") 11844 { 11845 if (m_tvm_isrecorded) 11846 { 11847 active = m_tvm_transcoding; 11848 BUTTON2(actionName, tr("Stop Transcoding"), tr("Default")); 11849 } 11850 } 11851 else if (actionName == "QUEUETRANSCODE_AUTO") 11852 { 11853 if (m_tvm_isrecorded) 11854 { 11855 active = m_tvm_transcoding; 11856 BUTTON(actionName, tr("Autodetect")); 11857 } 11858 } 11859 else if (actionName == "QUEUETRANSCODE_HIGH") 11860 { 11861 if (m_tvm_isrecorded) 11862 { 11863 active = m_tvm_transcoding; 11864 BUTTON(actionName, tr("High Quality")); 11865 } 11866 } 11867 else if (actionName == "QUEUETRANSCODE_MEDIUM") 11868 { 11869 if (m_tvm_isrecorded) 11870 { 11871 active = m_tvm_transcoding; 11872 BUTTON(actionName, tr("Medium Quality")); 11873 } 11874 } 11875 else if (actionName == "QUEUETRANSCODE_LOW") 11876 { 11877 if (m_tvm_isrecorded) 11878 { 11879 active = m_tvm_transcoding; 11880 BUTTON(actionName, tr("Low Quality")); 11881 } 11882 } 11883 else 11884 { 11885 // Allow an arbitrary action if it has a translated 11886 // description available to be used as the button text. 11887 // Look in the specified keybinding context as well as the 11888 // Global context. 11889 QString text = GetMythMainWindow()-> 11890 GetActionText(m_keyBindingContext, actionName); 11891 if (text.isEmpty()) 11892 text = GetMythMainWindow() 11893 ->GetActionText("Global", actionName); 11894 if (!text.isEmpty()) 11895 BUTTON(actionName, text); 11896 } 12055 11897 } 12056 }12057 11898 12058 void TV::FillOSDMenuSchedule(const PlayerContext *ctx, OSD *osd, 12059 QString category, const QString selected, 12060 QString ¤ttext, QString &backaction) 12061 { 12062 if (category == "MAIN") 11899 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 11900 return result; 11901 } 11902 11903 void TV::MenuLazyInit(void *field) 11904 { 11905 if (field == &m_tvm_freerecordercount) 11906 { 11907 if (m_tvm_freerecordercount < 0) 11908 m_tvm_freerecordercount = RemoteGetFreeRecorderCount(); 11909 } 11910 } 11911 11912 void TV::MenuInit(void) 11913 { 11914 m_tvmCtx = GetPlayerReadLock(-1, __FILE__, __LINE__); 11915 m_tvmOsd = GetOSDLock(m_tvmCtx); 11916 PlayerContext *ctx = m_tvmCtx; 11917 11918 m_tvm_avsync = true; 11919 m_tvm_visual = false; 11920 m_tvm_active = ""; 11921 m_tvm_upmixing = false; 11922 m_tvm_canupmix = false; 11923 11924 m_tvm_aspectoverride = kAspect_Off; 11925 m_tvm_adjustfill = kAdjustFill_Off; 11926 m_tvm_fill_autodetect = false; 11927 m_tvm_sup = kPictureAttributeSupported_None; 11928 m_tvm_studio_levels = false; 11929 m_tvm_stereoallowed = false; 11930 m_tvm_stereomode = kStereoscopicModeNone; 11931 m_tvm_scan_type = kScan_Ignore; 11932 m_tvm_scan_type_unlocked = kScan_Ignore; 11933 m_tvm_scan_type_locked = false; 11934 m_tvm_cur_mode = ""; 11935 m_tvm_doublerate = false; 11936 11937 m_tvm_speedX100 = (int)(round(ctx->ts_normal * 100)); 11938 m_tvm_state = ctx->GetState(); 11939 m_tvm_isrecording = (m_tvm_state == kState_WatchingRecording); 11940 m_tvm_isrecorded = (m_tvm_state == kState_WatchingPreRecorded); 11941 m_tvm_isrecorded = (m_tvm_state == kState_WatchingPreRecorded); 11942 m_tvm_isvideo = (m_tvm_state == kState_WatchingVideo); 11943 m_tvm_curskip = kCommSkipOff; 11944 m_tvm_ispaused = false; 11945 m_tvm_allowPIP = IsPIPSupported(ctx); 11946 m_tvm_allowPBP = IsPBPSupported(ctx); 11947 m_tvm_hasPBP = (player.size() > 1) && GetPlayer(ctx,1)->IsPBP(); 11948 m_tvm_hasPIP = (player.size() > 1) && GetPlayer(ctx,1)->IsPIP(); 11949 m_tvm_freerecordercount = -1; 11950 m_tvm_isdvd = (m_tvm_state == kState_WatchingDVD); 11951 m_tvm_isbd = (ctx->buffer && ctx->buffer->IsBD() && 11952 ctx->buffer->BD()->IsHDMVNavigation()); 11953 m_tvm_jump = (!m_tvm_num_chapters && !m_tvm_isdvd && 11954 !m_tvm_isbd && ctx->buffer->IsSeekingAllowed()); 11955 m_tvm_islivetv = StateIsLiveTV(m_tvm_state); 11956 m_tvm_previouschan = false; 11957 11958 m_tvm_num_chapters = GetNumChapters(ctx); 11959 m_tvm_current_chapter = GetCurrentChapter(ctx); 11960 m_tvm_num_angles = GetNumAngles(ctx); 11961 m_tvm_current_angle = GetCurrentAngle(ctx); 11962 m_tvm_num_titles = GetNumTitles(ctx); 11963 m_tvm_current_title = GetCurrentTitle(ctx); 11964 m_tvm_chapter_times.clear(); 11965 GetChapterTimes(ctx, m_tvm_chapter_times); 11966 11967 m_tvm_subs_capmode = 0; 11968 m_tvm_subs_havetext = false; 11969 m_tvm_subs_forcedon = true; 11970 m_tvm_subs_enabled = false; 11971 m_tvm_subs_have_subs = false; 11972 11973 for (int i = kTrackTypeUnknown ; i < kTrackTypeCount ; ++i) 11974 m_tvm_curtrack[i] = -1; 11975 11976 if (m_tvm_islivetv) 12063 11977 { 12064 osd->DialogAddButton(tr("Schedule"), 12065 "DIALOG_MENU_SCHEDULE_0", 12066 true, selected == "SCHEDULE"); 11978 QString prev_channum = ctx->GetPreviousChannel(); 11979 QString cur_channum = QString(); 11980 if (ctx->tvchain) 11981 cur_channum = ctx->tvchain->GetChannelName(-1); 11982 if (!prev_channum.isEmpty() && prev_channum != cur_channum) 11983 m_tvm_previouschan = true; 12067 11984 } 12068 else if (category == "SCHEDULE") 11985 11986 ctx->LockDeletePlayer(__FILE__, __LINE__); 11987 11988 if (ctx->player) 12069 11989 { 12070 backaction = "MAIN"; 12071 currenttext = tr("Schedule"); 12072 osd->DialogAddButton(tr("Program Guide"), ACTION_GUIDE); 12073 osd->DialogAddButton(tr("Program Finder"), ACTION_FINDER); 12074 osd->DialogAddButton(tr("Upcoming Recordings"), ACTION_VIEWSCHEDULED); 12075 osd->DialogAddButton(tr("Edit Recording Schedule"), "SCHEDULE"); 11990 for (int i = kTrackTypeUnknown ; i < kTrackTypeCount ; ++i) 11991 { 11992 m_tvm_tracks[i] = ctx->player->GetTracks(i); 11993 if (!m_tvm_tracks[i].empty()) 11994 m_tvm_curtrack[i] = ctx->player->GetTrack(i); 11995 } 11996 m_tvm_subs_have_subs = 11997 !m_tvm_tracks[kTrackTypeSubtitle].empty() || 11998 m_tvm_subs_havetext || 11999 !m_tvm_tracks[kTrackTypeCC708].empty() || 12000 !m_tvm_tracks[kTrackTypeCC608].empty() || 12001 !m_tvm_tracks[kTrackTypeTeletextCaptions].empty() || 12002 !m_tvm_tracks[kTrackTypeRawText].empty(); 12003 m_tvm_avsync = (ctx->player->GetTrackCount(kTrackTypeVideo) > 0) && 12004 !m_tvm_tracks[kTrackTypeAudio].empty(); 12005 m_tvm_visual = ctx->player->CanVisualise(); 12006 m_tvm_active = ctx->player->GetVisualiserName(); 12007 m_tvm_upmixing = ctx->player->GetAudio()->IsUpmixing(); 12008 m_tvm_canupmix = ctx->player->GetAudio()->CanUpmix(); 12009 m_tvm_aspectoverride = ctx->player->GetAspectOverride(); 12010 m_tvm_adjustfill = ctx->player->GetAdjustFill(); 12011 m_tvm_scan_type = ctx->player->GetScanType(); 12012 m_tvm_scan_type_unlocked = m_tvm_scan_type; 12013 m_tvm_scan_type_locked = ctx->player->IsScanTypeLocked(); 12014 m_tvm_doublerate = ctx->player->CanSupportDoubleRate(); 12015 m_tvm_curskip = ctx->player->GetAutoCommercialSkip(); 12016 m_tvm_ispaused = ctx->player->IsPaused(); 12017 m_tvm_subs_capmode = ctx->player->GetCaptionMode(); 12018 m_tvm_subs_enabled = ctx->player->GetCaptionsEnabled(); 12019 m_tvm_subs_havetext = ctx->player->HasTextSubtitles(); 12020 m_tvm_subs_forcedon = ctx->player->GetAllowForcedSubtitles(); 12021 ctx->player->GetVideoOutput()->GetDeinterlacers(m_tvm_deinterlacers); 12022 m_tvm_currentdeinterlacer = 12023 ctx->player->GetVideoOutput()->GetDeinterlacer(); 12024 if (m_tvm_visual) 12025 m_tvm_visualisers = ctx->player->GetVisualiserList(); 12026 VideoOutput *vo = ctx->player->GetVideoOutput(); 12027 if (vo) 12028 { 12029 m_tvm_sup = vo->GetSupportedPictureAttributes(); 12030 m_tvm_stereoallowed = vo->StereoscopicModesAllowed(); 12031 m_tvm_stereomode = vo->GetStereoscopicMode(); 12032 m_tvm_fill_autodetect = !vo->hasHWAcceleration(); 12033 m_tvm_studio_levels = 12034 vo->GetPictureAttribute(kPictureAttribute_StudioLevels) > 0; 12035 } 12036 if (!m_tvm_scan_type_locked) 12037 { 12038 if (kScan_Interlaced == m_tvm_scan_type) 12039 m_tvm_cur_mode = tr("(I)", "Interlaced (Normal)"); 12040 else if (kScan_Intr2ndField == m_tvm_scan_type) 12041 m_tvm_cur_mode = tr("(i)", "Interlaced (Reversed)"); 12042 else if (kScan_Progressive == m_tvm_scan_type) 12043 m_tvm_cur_mode = tr("(P)", "Progressive"); 12044 m_tvm_cur_mode = " " + m_tvm_cur_mode; 12045 m_tvm_scan_type_unlocked = kScan_Detect; 12046 } 12076 12047 } 12048 ctx->LockPlayingInfo(__FILE__, __LINE__); 12049 m_tvm_is_on = ctx->playingInfo->QueryAutoExpire() != kDisableAutoExpire; 12050 m_tvm_transcoding = JobQueue::IsJobQueuedOrRunning 12051 (JOB_TRANSCODE, ctx->playingInfo->GetChanID(), 12052 ctx->playingInfo->GetScheduledStartTime()); 12053 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 12054 12055 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 12056 } 12057 12058 void TV::MenuDeinit(void) 12059 { 12060 ReturnOSDLock(m_tvmCtx, m_tvmOsd); 12061 ReturnPlayerLock(m_tvmCtx); 12062 m_tvmOsd = NULL; 12063 m_tvmOsd = NULL; 12064 } 12065 12066 void TV::MenuShow(const QDomNode &node, const QDomNode &selected) 12067 { 12068 MenuInit(); 12069 if (m_tvmOsd) 12070 { 12071 m_tvmOsd->DialogShow(OSD_DLG_MENU, m_menuName); 12072 MenuBase::MenuShow(node, selected); 12073 QString text = 12074 MenuTranslate(node.toElement().attribute("text", m_menuName)); 12075 m_tvmOsd->DialogSetText(text); 12076 QDomNode parent = node.parentNode(); 12077 if (!parent.parentNode().isNull()) 12078 { 12079 QVariant v; 12080 v.setValue(node); 12081 m_tvmOsd->DialogBack("", v); 12082 } 12083 } 12084 MenuDeinit(); 12085 } 12086 12087 void TV::MenuStrings(void) const 12088 { 12089 tr("Playback Menu"); 12090 tr("Playback Compact Menu"); 12091 tr("Audio"); 12092 tr("Select Audio Track"); 12093 tr("Visualisation"); 12094 tr("Video"); 12095 tr("Change Aspect Ratio"); 12096 tr("Adjust Fill"); 12097 tr("Adjust Picture"); 12098 tr("3D"); 12099 tr("Advanced"); 12100 tr("Video Scan"); 12101 tr("Deinterlacer"); 12102 tr("Subtitles"); 12103 tr("Select Subtitle"); 12104 tr("Text Subtitles"); 12105 tr("Select ATSC CC"); 12106 tr("Select VBI CC"); 12107 tr("Select Teletext CC"); 12108 tr("Playback"); 12109 tr("Adjust Time Stretch"); 12110 tr("Picture-in-Picture"); 12111 tr("Sleep"); 12112 tr("Channel Groups"); 12113 tr("Navigate"); 12114 tr("Commercial Auto-Skip"); 12115 tr("Chapter"); 12116 tr("Angle"); 12117 tr("Title"); 12118 tr("Schedule"); 12119 tr("Source"); 12120 tr("Jump to Program"); 12121 tr("Switch Input"); 12122 tr("Switch Source"); 12123 tr("Jobs"); 12124 tr("Begin Transcoding"); 12125 } 12126 12127 void TV::ShowOSDMenu(const PlayerContext *ctx, bool isCompact) 12128 { 12129 if (!MenuIsLoaded()) 12130 { 12131 MenuLoadFromFile("menu_playback.xml", 12132 tr("Playback Menu"), 12133 metaObject()->className(), 12134 "TV Playback"); 12135 m_compactMenu.MenuLoadFromFile("menu_playback_compact.xml", 12136 tr("Playback Compact Menu"), 12137 metaObject()->className(), 12138 "TV Playback"); 12139 } 12140 if (isCompact && m_compactMenu.MenuIsLoaded()) 12141 MenuShow(m_compactMenu.MenuGetRoot(), QDomNode()); 12142 else if (MenuIsLoaded()) 12143 MenuShow(MenuGetRoot(), QDomNode()); 12077 12144 } 12078 12145 12079 12146 void TV::FillOSDMenuJumpRec(PlayerContext* ctx, const QString category, … … void TV::FillOSDMenuJumpRec(PlayerContext* ctx, const QString category, 12185 12252 if (level == 1) 12186 12253 osd->DialogBack(category, "DIALOG_" + ACTION_JUMPREC + "_X_0"); 12187 12254 else if (level == 0) 12188 osd->DialogBack(ACTION_JUMPREC, 12189 "DIALOG_MENU_" + ACTION_JUMPREC +"_0"); 12255 { 12256 if (m_tvm_jumprec_back_hack.isValid()) 12257 osd->DialogBack("", m_tvm_jumprec_back_hack); 12258 else 12259 osd->DialogBack(ACTION_JUMPREC, 12260 "DIALOG_MENU_" + ACTION_JUMPREC +"_0"); 12261 } 12190 12262 } 12191 12263 } 12192 12264 ReturnOSDLock(ctx, osd); -
mythtv/libs/libmythtv/tv_play.h
diff --git a/mythtv/libs/libmythtv/tv_play.h b/mythtv/libs/libmythtv/tv_play.h index 56556dc..43e7599 100644
a b using namespace std; 39 39 #include "channelgroup.h" 40 40 #include "mythtimer.h" 41 41 #include "osd.h" 42 #include "decoderbase.h" 42 43 43 44 class QDateTime; 45 class QDomDocument; 46 class QDomNode; 44 47 class OSD; 45 48 class RemoteEncoder; 46 49 class MythPlayer; … … class AskProgramInfo 138 141 ProgramInfo *info; 139 142 }; 140 143 144 enum MenuCategory { 145 kMenuCategoryItem, 146 kMenuCategoryItemlist, 147 kMenuCategoryMenu 148 }; 149 enum MenuShowContext { 150 kMenuShowActive, 151 kMenuShowInactive, 152 kMenuShowAlways 153 }; 154 155 class MenuItemContext 156 { 157 public: 158 // Constructor for a menu element. 159 MenuItemContext(const QDomNode &node, 160 const QString &menuName, 161 bool setCurrentActive, 162 bool doDisplay) : 163 m_node(node), 164 m_category(kMenuCategoryMenu), 165 m_menuName(menuName), 166 m_showContext(kMenuShowAlways), 167 m_setCurrentActive(setCurrentActive), 168 m_action(""), 169 m_actionText(""), 170 m_doDisplay(doDisplay) {} 171 // Constructor for an item element. 172 MenuItemContext(const QDomNode &node, 173 MenuShowContext showContext, 174 bool setCurrentActive, 175 const QString &action, 176 const QString &actionText, 177 bool doDisplay) : 178 m_node(node), 179 m_category(kMenuCategoryItem), 180 m_menuName(""), 181 m_showContext(showContext), 182 m_setCurrentActive(setCurrentActive), 183 m_action(action), 184 m_actionText(actionText), 185 m_doDisplay(doDisplay) {} 186 // Constructor for an itemlist element. 187 MenuItemContext(const QDomNode &node, 188 MenuShowContext showContext, 189 bool setCurrentActive, 190 const QString &action, 191 bool doDisplay) : 192 m_node(node), 193 m_category(kMenuCategoryItemlist), 194 m_menuName(""), 195 m_showContext(showContext), 196 m_setCurrentActive(setCurrentActive), 197 m_action(action), 198 m_actionText(""), 199 m_doDisplay(doDisplay) {} 200 const QDomNode &m_node; 201 MenuCategory m_category; 202 const QString m_menuName; 203 MenuShowContext m_showContext; 204 bool m_setCurrentActive; 205 const QString m_action; 206 const QString m_actionText; 207 bool m_doDisplay; 208 }; 209 210 class MenuBase 211 { 212 public: 213 MenuBase() : m_menuDocument(NULL), m_translationContext(""), 214 m_recursionLevel(0) {} 215 ~MenuBase(); 216 bool MenuLoadFromFile(const QString &filename, const QString &menuname, 217 const char *translationContext, 218 const QString &keyBindingContext); 219 bool MenuIsLoaded(void) const { return (m_menuDocument != NULL); } 220 QDomElement MenuGetRoot(void) const; 221 QString MenuTranslate(const QString &text) const; 222 virtual void MenuShow(const QDomNode &node, const QDomNode &selected) { 223 MenuShowHelper(node, selected, true); 224 } 225 protected: 226 virtual bool MenuShowHelper(const QDomNode &node, 227 const QDomNode &selected, 228 bool doDisplay); 229 virtual bool MenuDisplayItem(const MenuItemContext &c) { return false; } 230 virtual void MenuStrings(void) const {} 231 QDomDocument *m_menuDocument; 232 QString m_menuName; 233 const char *m_translationContext; 234 QString m_keyBindingContext; 235 private: 236 void MenuProcessIncludes(QDomElement &root); 237 int m_recursionLevel; // guard against infinite recursion 238 }; 239 141 240 /** 142 241 * \class TV 143 242 * … … class AskProgramInfo 156 255 * \qmlsignal TVPlaybackSought(qint position_seconds) 157 256 * Absolute seek has completed to position_seconds 158 257 */ 159 class MTV_PUBLIC TV : public QObject 258 class MTV_PUBLIC TV : public QObject, public MenuBase 160 259 { 161 260 friend class PlaybackBox; 162 261 friend class GuideGrid; … … class MTV_PUBLIC TV : public QObject 606 705 bool HandleOSDVideoExit(PlayerContext *ctx, QString action); 607 706 608 707 // Menu dialog 609 void ShowOSDMenu(const PlayerContext*, const QString category = "", 610 const QString selected = ""); 611 612 void FillOSDMenuAudio (const PlayerContext *ctx, OSD *osd, 613 QString category, const QString selected, 614 QString ¤ttext, QString &backaction); 615 void FillOSDMenuVideo (const PlayerContext *ctx, OSD *osd, 616 QString category, const QString selected, 617 QString ¤ttext, QString &backaction); 618 void FillOSDMenuSubtitles(const PlayerContext *ctx, OSD *osd, 619 QString category, const QString selected, 620 QString ¤ttext, QString &backaction); 621 void FillOSDMenuNavigate (const PlayerContext *ctx, OSD *osd, 622 QString category, const QString selected, 623 QString ¤ttext, QString &backaction); 624 void FillOSDMenuJobs (const PlayerContext *ctx, OSD *osd, 625 QString category, const QString selected, 626 QString ¤ttext, QString &backaction); 627 void FillOSDMenuPlayback (const PlayerContext *ctx, OSD *osd, 628 QString category, const QString selected, 629 QString ¤ttext, QString &backaction); 630 void FillOSDMenuSchedule (const PlayerContext *ctx, OSD *osd, 631 QString category, const QString selected, 632 QString ¤ttext, QString &backaction); 633 void FillOSDMenuSource (const PlayerContext *ctx, OSD *osd, 634 QString category, const QString selected, 635 QString ¤ttext, QString &backaction); 708 void ShowOSDMenu(const PlayerContext*, bool isCompact = false); 709 636 710 void FillOSDMenuJumpRec (PlayerContext* ctx, const QString category = "", 637 711 int level = 0, const QString selected = ""); 638 712 713 virtual void MenuShow(const QDomNode &node, const QDomNode &selected); 714 virtual bool MenuDisplayItem(const MenuItemContext &c); 715 virtual void MenuInit(void); 716 virtual void MenuDeinit(void); 717 virtual void MenuStrings(void) const; 718 void MenuLazyInit(void *field); 719 639 720 // LCD 640 721 void UpdateLCD(void); 641 722 void ShowLCDChannelInfo(const PlayerContext*); … … class MTV_PUBLIC TV : public QObject 857 938 TimerContextMap signalMonitorTimerId; 858 939 TimerContextMap tvchainUpdateTimerId; 859 940 941 // Playback menu state caching 942 PlayerContext *m_tvmCtx; 943 OSD *m_tvmOsd; 944 945 // Various tracks 946 // XXX This ignores kTrackTypeTextSubtitle which is greater than 947 // kTrackTypeCount, and it unnecessarily includes 948 // kTrackTypeUnknown. 949 QStringList m_tvm_tracks[kTrackTypeCount]; 950 int m_tvm_curtrack[kTrackTypeCount]; 951 952 // Audio 953 bool m_tvm_avsync; 954 bool m_tvm_visual; 955 QString m_tvm_active; 956 bool m_tvm_upmixing; 957 bool m_tvm_canupmix; 958 QStringList m_tvm_visualisers; 959 960 // Video 961 AspectOverrideMode m_tvm_aspectoverride; 962 AdjustFillMode m_tvm_adjustfill; 963 bool m_tvm_fill_autodetect; 964 uint m_tvm_sup; 965 bool m_tvm_studio_levels; 966 bool m_tvm_stereoallowed; 967 StereoscopicMode m_tvm_stereomode; 968 FrameScanType m_tvm_scan_type; 969 FrameScanType m_tvm_scan_type_unlocked; 970 bool m_tvm_scan_type_locked; 971 QString m_tvm_cur_mode; 972 QStringList m_tvm_deinterlacers; 973 QString m_tvm_currentdeinterlacer; 974 bool m_tvm_doublerate; 975 976 // Playback 977 int m_tvm_speedX100; 978 TVState m_tvm_state; 979 bool m_tvm_isrecording; 980 bool m_tvm_isrecorded; 981 bool m_tvm_isvideo; 982 CommSkipMode m_tvm_curskip; 983 bool m_tvm_ispaused; 984 bool m_tvm_allowPIP; 985 bool m_tvm_allowPBP; 986 bool m_tvm_hasPIP; 987 bool m_tvm_hasPBP; 988 int m_tvm_freerecordercount; 989 bool m_tvm_isdvd; 990 bool m_tvm_isbd; 991 bool m_tvm_jump; 992 bool m_tvm_islivetv; 993 bool m_tvm_previouschan; 994 995 // Navigate 996 int m_tvm_num_chapters; 997 int m_tvm_current_chapter; 998 QList<long long> m_tvm_chapter_times; 999 int m_tvm_num_angles; 1000 int m_tvm_current_angle; 1001 int m_tvm_num_titles; 1002 int m_tvm_current_title; 1003 1004 // Subtitles 1005 uint m_tvm_subs_capmode; 1006 bool m_tvm_subs_havetext; 1007 bool m_tvm_subs_forcedon; 1008 bool m_tvm_subs_enabled; 1009 bool m_tvm_subs_have_subs; 1010 1011 bool m_tvm_is_on; 1012 bool m_tvm_transcoding; 1013 1014 QVariant m_tvm_jumprec_back_hack; 1015 // End of playback menu state caching 1016 1017 MenuBase m_compactMenu; 1018 860 1019 public: 861 1020 // Constants 862 1021 static const int kInitFFRWSpeed; ///< 1x, default to normal speed -
mythtv/libs/libmythui/mythmainwindow.cpp
diff --git a/mythtv/libs/libmythui/mythmainwindow.cpp b/mythtv/libs/libmythui/mythmainwindow.cpp index cfa0ebc..7abc1f7 100644
a b class MythMainWindowPrivate 233 233 QMap<int, JumpData*> jumpMap; 234 234 QMap<QString, JumpData> destinationMap; 235 235 QMap<QString, MPData> mediaPluginMap; 236 QHash<QString, QHash<QString, QString> > actionText; 236 237 237 238 void (*exitmenucallback)(void); 238 239 … … void MythMainWindow::RegisterKey(const QString &context, const QString &action, 1701 1702 } 1702 1703 1703 1704 BindKey(context, action, keybind); 1705 d->actionText[context][action] = description; 1704 1706 } 1705 1707 1706 1708 QString MythMainWindow::GetKey(const QString &context, … … QString MythMainWindow::GetKey(const QString &context, 1725 1727 return query.value(0).toString(); 1726 1728 } 1727 1729 1730 QString MythMainWindow::GetActionText(const QString &context, 1731 const QString &action) const 1732 { 1733 if (d->actionText.contains(context)) 1734 { 1735 QHash<QString, QString> entry = d->actionText.value(context); 1736 if (entry.contains(action)) 1737 return entry.value(action); 1738 } 1739 return ""; 1740 } 1741 1728 1742 void MythMainWindow::ClearJump(const QString &destination) 1729 1743 { 1730 1744 /* make sure that the jump point exists (using [] would add it)*/ -
mythtv/libs/libmythui/mythmainwindow.h
diff --git a/mythtv/libs/libmythui/mythmainwindow.h b/mythtv/libs/libmythui/mythmainwindow.h index 7643af8..f56d12f 100644
a b class MUI_PUBLIC MythMainWindow : public QWidget 62 62 void RegisterKey(const QString &context, const QString &action, 63 63 const QString &description, const QString &key); 64 64 QString GetKey(const QString &context, const QString &action) const; 65 QString GetActionText(const QString &context, const QString &action) const; 65 66 66 67 void ClearJump(const QString &destination); 67 68 void BindJump(const QString &destination, const QString &key); -
new file mythtv/themes/default/menu_playback.xml
diff --git a/mythtv/themes/default/menu_playback.xml b/mythtv/themes/default/menu_playback.xml new file mode 100644 index 0000000..7dc85ad
- + 1 <?xml version="1.0"?> 2 3 <!-- All "text" attribute values need translations. The "XXXtext" 4 attributes illustrate the default value if the "text" attribute 5 is omitted. --> 6 7 <menu text="Playback Menu"> 8 <menu text="Audio"> 9 <menu text="Select Audio Track"> 10 <itemlist actiongroup="SELECTAUDIO_" current="active" /> 11 </menu> 12 <item action="TOGGLEAUDIOSYNC" XXXtext="Adjust Audio Sync" /> 13 <menu text="Visualisation"> 14 <item action="DISABLEVISUALISATION" XXXtext="None" /> 15 <itemlist actiongroup="VISUALISER_" current="active" /> 16 </menu> 17 <item action="DISABLEUPMIX" XXXtext="Disable Audio Upmixer" 18 show="inactive" /> 19 <item action="ENABLEUPMIX" XXXtext="Enable Audio Upmixer" 20 show="inactive" /> 21 </menu> 22 <menu text="Video"> 23 <menu text="Change Aspect Ratio"> 24 <itemlist actiongroup="TOGGLEASPECT" current="active" /> 25 <!-- Alternatively: 26 <item action="TOGGLEASPECT0" XXXtext="Off" current="active" /> 27 <item action="TOGGLEASPECT1" XXXtext="4:3" current="active" /> 28 <item action="TOGGLEASPECT3" XXXtext="14:9" current="active" /> 29 <item action="TOGGLEASPECT2" XXXtext="16:9" current="active" /> 30 <item action="TOGGLEASPECT4" XXXtext="2.35:1" current="active" /> 31 --> 32 </menu> 33 <menu text="Adjust Fill"> 34 <item action="AUTODETECT_FILL" XXXtext="Auto Detect" current="active" /> 35 <!-- Alternatively: 36 <item action="TOGGLEFILL0" XXXtext="Off" current="active" /> 37 <item action="TOGGLEFILL1" XXXtext="Half" current="active" /> 38 <item action="TOGGLEFILL2" XXXtext="Full" current="active" /> 39 <item action="TOGGLEFILL3" XXXtext="H.Stretch" current="active" /> 40 <item action="TOGGLEFILL4" XXXtext="V.Stretch" current="active" /> 41 <item action="TOGGLEFILL5" XXXtext="H.Fill" current="active" /> 42 <item action="TOGGLEFILL6" XXXtext="V.Fill" current="active" /> 43 --> 44 <itemlist actiongroup="TOGGLEFILL" current="active" /> 45 </menu> 46 <item action="TOGGLEMANUALZOOM" XXXtext="Manual Zoom Mode" /> 47 <menu text="Adjust Picture"> 48 <itemlist actiongroup="TOGGLEPICCONTROLS" /> 49 <!-- Alternatively: 50 <item action="TOGGLEPICCONTROLS0" XXXtext="None" /> 51 <item action="TOGGLEPICCONTROLS1" XXXtext="Brightness" /> 52 <item action="TOGGLEPICCONTROLS2" XXXtext="Contrast" /> 53 <item action="TOGGLEPICCONTROLS3" XXXtext="Color" /> 54 <item action="TOGGLEPICCONTROLS4" XXXtext="Hue" /> 55 <item action="TOGGLESTUDIOLEVELS" 56 XXXtext="Disable Studio Levels" show="active" /> 57 <item action="TOGGLESTUDIOLEVELS" 58 XXXtext="Enable Studio Levels" show="active" /> 59 <item action="TOGGLEPICCONTROLS6" XXXtext="Volume" /> 60 --> 61 <item action="TOGGLENIGHTMODE" 62 XXXtext="Disable Night Mode" show="active" /> 63 <item action="TOGGLENIGHTMODE" 64 XXXtext="Enable Night Mode" show="inactive" /> 65 </menu> 66 <menu text="3D"> 67 <itemlist actiongroup="3D" current="active" /> 68 <!-- Alternatively: 69 <item action="3DNONE" XXXtext="None" current="active" /> 70 <item action="3DSIDEBYSIDE" XXXtext="Side by Side" current="active" /> 71 <item action="3DSIDEBYSIDEDISCARD" XXXtext="Discard Side by Side" 72 current="active" /> 73 <item action="3DTOPANDBOTTOM" XXXtext="Top and Bottom" 74 current="active" /> 75 <item action="3DTOPANDBOTTOMDISCARD" XXXtext="Discard Top and Bottom" 76 current="active" /> 77 --> 78 </menu> 79 <menu text="Advanced"> 80 <menu text="Video Scan"> 81 <itemlist actiongroup="SELECTSCAN_" current="active" /> 82 <!-- Alternatively: 83 <item action="SELECTSCAN_0" 84 XXXtext="Detect" current="active" /> 85 <item action="SELECTSCAN_3" 86 XXXtext="Progressive" current="active" /> 87 <item action="SELECTSCAN_1" 88 XXXtext="Interlaced (Normal)" current="active" /> 89 <item action="SELECTSCAN_2" 90 XXXtext="Interlaced (Reversed)" current="active" /> 91 --> 92 </menu> 93 <menu text="Deinterlacer"> 94 <itemlist actiongroup="DEINTERLACER_" current="active" /> 95 </menu> 96 </menu> 97 </menu> 98 <menu text="Subtitles"> 99 <item action="DISABLESUBS" XXXtext="Disable Subtitles" show="inactive" /> 100 <item action="ENABLESUBS" XXXtext="Enable Subtitles" show="inactive" /> 101 <item action="DISABLEFORCEDSUBS" XXXtext="Disable Forced Subtitles" 102 show="inactive" /> 103 <item action="ENABLEFORCEDSUBS" XXXtext="Enable Forced Subtitles" 104 show="inactive" /> 105 <menu text="Select Subtitle"> 106 <itemlist actiongroup="SELECTSUBTITLE_" current="active" /> 107 </menu> 108 <menu text="Text Subtitles"> 109 <item action="DISABLEEXTTEXT" XXXtext="Disable External Subtitles" 110 show="inactive" /> 111 <item action="ENABLEEXTTEXT" XXXtext="Enable External Subtitles" 112 show="inactive" /> 113 <itemlist actiongroup="SELECTRAWTEXT_" current="active" /> 114 </menu> 115 <menu text="Select ATSC CC"> 116 <itemlist actiongroup="SELECTCC708_" current="active" /> 117 </menu> 118 <menu text="Select VBI CC"> 119 <itemlist actiongroup="SELECTCC608_" current="active" /> 120 </menu> 121 <menu text="Select Teletext CC"> 122 <itemlist actiongroup="SELECTTTC_" current="active" /> 123 </menu> 124 <item action="TOGGLETTM" XXXtext="Toggle Teletext Menu" /> 125 <item action="TOGGLESUBZOOM" XXXtext="Adjust Subtitle Zoom" /> 126 <item action="TOGGLESUBDELAY" XXXtext="Adjust Subtitle Delay" /> 127 </menu> 128 <menu text="Playback"> 129 <item action="PAUSE" XXXtext="Play" show="active" /> 130 <item action="PAUSE" XXXtext="Pause" show="inactive" /> 131 <menu text="Adjust Time Stretch"> 132 <item action="TOGGLESTRETCH" XXXtext="Toggle" /> 133 <itemlist actiongroup="ADJUSTSTRETCH" current="active" /> 134 <!-- Alternatively: 135 <item action="ADJUSTSTRETCH" XXXtext="Adjust" /> 136 <item action="ADJUSTSTRETCH0.5" XXXtext="0.5X" current="active" /> 137 <item action="ADJUSTSTRETCH0.9" XXXtext="0.9X" current="active" /> 138 <item action="ADJUSTSTRETCH1.0" XXXtext="1.0X" current="active" /> 139 <item action="ADJUSTSTRETCH1.1" XXXtext="1.1X" current="active" /> 140 <item action="ADJUSTSTRETCH1.2" XXXtext="1.2X" current="active" /> 141 <item action="ADJUSTSTRETCH1.3" XXXtext="1.3X" current="active" /> 142 <item action="ADJUSTSTRETCH1.4" XXXtext="1.4X" current="active" /> 143 <item action="ADJUSTSTRETCH1.5" XXXtext="1.5X" current="active" /> 144 --> 145 </menu> 146 <menu text="Picture-in-Picture"> 147 <item action="JUMPRECPIP" XXXtext="Open Recording PIP" /> 148 <item action="JUMPRECPBP" XXXtext="Open Recording PBP" /> 149 <item action="CREATEPIPVIEW" XXXtext="Open Live TV PIP" /> 150 <item action="CREATEPBPVIEW" XXXtext="Open Live TV PBP" /> 151 <item action="NEXTPIPWINDOW" XXXtext="Change Active Window" /> 152 <item action="TOGGLEPIPMODE" XXXtext="Close PIP(s)" /> 153 <item action="TOGGLEPBPMODE" XXXtext="Close PBP(s)" /> 154 <item action="SWAPPIP" XXXtext="Swap Windows" /> 155 <item action="TOGGLEPIPSTATE" XXXtext="Switch to PBP" show="active" /> 156 <item action="TOGGLEPIPSTATE" XXXtext="Switch to PIP" show="inactive" /> 157 </menu> 158 <menu text="Sleep"> 159 <itemlist actiongroup="TOGGLESLEEP" /> 160 <!-- Alternatively: 161 <item action="TOGGLESLEEPON" XXXtext="Sleep Off" /> 162 <item action="TOGGLESLEEP30" XXXtext="Sleep 30 minutes" /> 163 <item action="TOGGLESLEEP60" XXXtext="Sleep 60 minutes" /> 164 <item action="TOGGLESLEEP90" XXXtext="Sleep 90 minutes" /> 165 <item action="TOGGLESLEEP120" XXXtext="Sleep 120 minutes" /> 166 --> 167 </menu> 168 <menu text="Channel Groups"> 169 <itemlist actiongroup="CHANGROUP_" current="active" /> 170 </menu> 171 <item action="TOGGLEBROWSE" XXXtext="Toggle Browse Mode" /> 172 <item action="CANCELPLAYLIST" XXXtext="Cancel Playlist" /> 173 <item action="DEBUGOSD" XXXtext="Playback Data" /> 174 </menu> 175 <menu text="Navigate"> 176 <item action="JUMPFFWD" XXXtext="Jump Ahead" /> 177 <item action="JUMPRWND" XXXtext="Jump Back" /> 178 <menu text="Commercial Auto-Skip"> 179 <itemlist actiongroup="TOGGLECOMMSKIP" current="active" /> 180 <!-- Alternatively: 181 <item action="TOGGLECOMMSKIP0" XXXtext="Auto-Skip OFF" 182 current="active" /> 183 <item action="TOGGLECOMMSKIP2" XXXtext="Auto-Skip Notify" 184 current="active" /> 185 <item action="TOGGLECOMMSKIP1" XXXtext="Auto-Skip ON" 186 current="active" /> 187 --> 188 </menu> 189 <!-- JUMPTODVDROOTMENU has different text/meanings for BD & DVD --> 190 <item action="JUMPTODVDROOTMENU" XXXtext="DVD Root Menu" show="active" /> 191 <item action="JUMPTODVDROOTMENU" XXXtext="Top menu" show="inactive" /> 192 <item action="JUMPTOPOPUPMENU" XXXtext="Popup menu" /> 193 <item action="JUMPTODVDTITLEMENU" XXXtext="DVD Title Menu" /> 194 <item action="JUMPTODVDCHAPTERMENU" XXXtext="DVD Chapter Menu" /> 195 <item action="PREVCHAN" XXXtext="Previous Channel" /> 196 <menu text="Chapter"> 197 <itemlist actiongroup="JUMPTOCHAPTER" current="active" /> 198 </menu> 199 <menu text="Angle"> 200 <itemlist actiongroup="SWITCHTOANGLE" current="active" /> 201 </menu> 202 <menu text="Title"> 203 <itemlist actiongroup="JUMPTOTITLE" current="active" /> 204 </menu> 205 </menu> 206 <menu text="Schedule"> 207 <item action="GUIDE" XXXtext="Program Guide" /> 208 <item action="FINDER" XXXtext="Program Finder" /> 209 <item action="VIEWSCHEDULED" XXXtext="Upcoming Recordings" /> 210 <item action="SCHEDULE" XXXtext="Edit Recording Schedule" /> 211 </menu> 212 <menu text="Source"> 213 <menu text="Jump to Program"> 214 <item action="DIALOG_JUMPREC_X_0" XXXtext="Recorded Program" /> 215 <item action="JUMPPREV" /> 216 </menu> 217 <menu text="Switch Input"> 218 <itemlist actiongroup="SWITCHTOINPUT_" show="inactive" /> 219 </menu> 220 <menu text="Switch Source"> 221 <itemlist actiongroup="SWITCHTOSOURCE_" /> 222 </menu> 223 </menu> 224 <menu text="Jobs"> 225 <item action="EDIT" XXXtext="Edit Channel" show="active" /> 226 <item action="EDIT" XXXtext="Edit Recording" show="inactive" /> 227 <item action="TOGGLEAUTOEXPIRE" XXXtext="Turn Auto-Expire OFF" show="active" /> 228 <item action="TOGGLEAUTOEXPIRE" XXXtext="Turn Auto-Expire ON" show="inactive" /> 229 <item action="QUEUETRANSCODE" XXXtext="Stop Transcoding" show="active" /> 230 <menu text="Begin Transcoding"> 231 <item action="QUEUETRANSCODE" XXXtext="Default" 232 show="inactive" /> 233 <item action="QUEUETRANSCODE_AUTO" XXXtext="Autodetect" 234 show="inactive" /> 235 <item action="QUEUETRANSCODE_HIGH" XXXtext="High Quality" 236 show="inactive" /> 237 <item action="QUEUETRANSCODE_MEDIUM" XXXtext="Medium Quality" 238 show="inactive" /> 239 <item action="QUEUETRANSCODE_LOW" XXXtext="Low Quality" 240 show="inactive" /> 241 </menu> 242 </menu> 243 </menu> -
new file mythtv/themes/default/menu_playback_compact.xml
diff --git a/mythtv/themes/default/menu_playback_compact.xml b/mythtv/themes/default/menu_playback_compact.xml new file mode 100644 index 0000000..59ecad4
- + 1 <?xml version="1.0"?> 2 3 <menu text="Playback Compact Menu"> 4 <!-- Insert desired actions here. End by including the main menu 5 so that all actions are ultimately available. The actions 6 may need more descriptive text outside the context of the 7 original menu; if so, it's best to find a string from tv_play.cpp 8 that is already being translated. --> 9 <include file="menu_playback.xml" /> 10 </menu>
