Ticket #7603: 7603-pbb-misc-v1.patch
| File 7603-pbb-misc-v1.patch, 58.2 KB (added by , 17 years ago) |
|---|
-
programs/mythfrontend/playbackbox.cpp
364 364 // Main Recording List support 365 365 m_progsInDB(0), 366 366 // Other state 367 m_ currentItem(NULL), m_op_on_playlist(false),367 m_op_on_playlist(false), 368 368 m_programInfoCache(this), m_playingSomething(false), 369 369 // Selection state variables 370 370 m_needUpdate(false), … … 409 409 gContext->SaveSetting("DisplayGroupDefaultViewMask", (int)m_viewMask); 410 410 } 411 411 412 // If user wants to start in watchlist and watchlist is displayed, then413 // make it the current group414 if (m_watchListStart && (m_viewMask & VIEW_WATCHLIST))415 m_currentGroup = m_watchGroupLabel;416 417 412 // This setting is deprecated in favour of viewmask, this just ensures the 418 413 // that it is converted over when upgrading from earlier versions 419 414 if (gContext->GetNumSetting("LiveTVInAllPrograms",0) && … … 472 467 m_coverartTimer->disconnect(this); 473 468 m_coverartTimer = NULL; 474 469 } 475 476 delete m_currentItem;477 470 } 478 471 479 472 bool PlaybackBox::Create() … … 698 691 void PlaybackBox::UpdateUIListItem( 699 692 MythUIButtonListItem *item, bool is_sel, bool force_preview_reload) 700 693 { 701 // TODO Make sure playlist DisplayState is respected..702 703 694 if (!item) 704 695 return; 705 696 … … 744 735 if (oldimgfile.isEmpty() || force_preview_reload) 745 736 m_helper.GetPreviewImage(*pginfo); 746 737 738 bool in_playlist = m_playList.contains(pginfo->MakeUniqueKey()); 739 item->DisplayState((in_playlist) ? "yes" : "no", "playlist"); 740 747 741 if ((GetFocusWidget() == m_recordingList) && is_sel) 748 742 { 749 743 InfoMap infoMap; … … 1001 995 } 1002 996 } 1003 997 1004 void PlaybackBox:: updateGroupList()998 void PlaybackBox::UpdateUIGroupList(const QStringList &groupPreferences) 1005 999 { 1006 1000 m_groupList->Reset(); 1007 1001 1008 1002 if (!m_titleList.isEmpty()) 1009 1003 { 1010 MythUIButtonListItem *item = NULL; 1011 1012 QString groupname; 1013 1014 bool foundGroup = false; 1004 int best_pref = 10000, sel_idx = 0; 1015 1005 QStringList::iterator it; 1016 1006 for (it = m_titleList.begin(); it != m_titleList.end(); ++it) 1017 1007 { 1018 groupname = (*it).simplified();1008 QString groupname = (*it).simplified(); 1019 1009 1010 MythUIButtonListItem *item = 1011 new MythUIButtonListItem( 1012 m_groupList, "", qVariantFromValue(groupname.toLower())); 1013 1020 1014 // The first item added to the list will trigger an update of the 1021 1015 // associated Recording List, m_needsUpdate should be false unless 1022 1016 // this is the currently selected group 1023 if (groupname.toLower() == m_currentGroup) 1017 int pref = groupPreferences.indexOf(groupname.toLower()); 1018 if ((pref >= 0) && (pref < best_pref)) 1024 1019 { 1025 m_needUpdate = true;1026 foundGroup = true;1020 best_pref = pref; 1021 sel_idx = m_groupList->GetItemPos(item); 1027 1022 } 1028 1023 1029 item = new MythUIButtonListItem(m_groupList, "",1030 qVariantFromValue(groupname.toLower()));1031 1032 if (m_needUpdate)1033 m_groupList->SetItemCurrent(item);1034 1035 1024 if (groupname.isEmpty()) 1036 1025 groupname = m_groupDisplayName; 1037 1026 … … 1042 1031 item->SetText(QString::number(count), "reccount"); 1043 1032 } 1044 1033 1045 if (!foundGroup) 1046 { 1047 m_needUpdate = true; 1048 m_groupList->SetItemCurrent(0); 1049 } 1034 m_needUpdate = true; 1035 m_groupList->SetItemCurrent(sel_idx); 1050 1036 } 1051 1037 } 1052 1038 … … 1168 1154 if ((*it)->subtitleType & sit.key()) 1169 1155 item->DisplayState(sit.value(), "subtitletypes"); 1170 1156 } 1171 1172 if (m_currentItem &&1173 (m_currentItem->chanid == (*it)->chanid) &&1174 (m_currentItem->recstartts == (*it)->recstartts))1175 {1176 m_recordingList->SetItemCurrent(item);1177 }1178 1157 } 1179 1158 1180 1159 if (m_noRecordingsText) … … 1194 1173 1195 1174 bool PlaybackBox::UpdateUILists(void) 1196 1175 { 1197 // TODO Make sure playlist DisplayState is respected..1198 1199 1176 m_isFilling = true; 1200 1177 1201 if (m_currentItem) 1178 // Save selection, including next few items & groups 1179 QStringList groupSelPref; 1180 QStringList itemSelPref; 1181 MythUIButtonListItem *prefSelGroup = m_groupList->GetItemCurrent(); 1182 if (prefSelGroup) 1202 1183 { 1203 delete m_currentItem; 1204 m_currentItem = NULL; 1184 groupSelPref.push_back(prefSelGroup->GetData().toString()); 1185 for (int i = m_groupList->GetCurrentPos(); 1186 i < m_groupList->GetCount(); i++) 1187 { 1188 prefSelGroup = m_groupList->GetItemAt(i); 1189 if (prefSelGroup) 1190 groupSelPref.push_back(prefSelGroup->GetData().toString()); 1191 } 1192 1193 int curPos = m_recordingList->GetCurrentPos(); 1194 for (int i = curPos; i < m_recordingList->GetCount(); i++) 1195 { 1196 MythUIButtonListItem *item = m_recordingList->GetItemAt(i); 1197 ProgramInfo *pginfo = qVariantValue<ProgramInfo*>(item->GetData()); 1198 itemSelPref.push_back(groupSelPref.front()); 1199 itemSelPref.push_back(pginfo->MakeUniqueKey()); 1200 } 1201 if (curPos >= m_recordingList->GetCount()) 1202 curPos = -1; 1203 for (int i = curPos; i >= 0; i--) 1204 { 1205 MythUIButtonListItem *item = m_recordingList->GetItemAt(i); 1206 ProgramInfo *pginfo = qVariantValue<ProgramInfo*>(item->GetData()); 1207 itemSelPref.push_back(groupSelPref.front()); 1208 itemSelPref.push_back(pginfo->MakeUniqueKey()); 1209 } 1205 1210 } 1211 else 1212 { 1213 // If user wants to start in watchlist and watchlist is displayed, then 1214 // make it the current group 1215 if (m_watchListStart && (m_viewMask & VIEW_WATCHLIST)) 1216 groupSelPref.push_back(m_watchGroupLabel); 1217 } 1206 1218 1207 ProgramInfo *tmp = CurrentItem(); 1208 if (tmp) 1209 m_currentItem = new ProgramInfo(*tmp); 1210 1219 // Cache available status for later restoration 1211 1220 QMap<QString, AvailableStatusType> asCache; 1212 1221 QString asKey; 1213 1222 … … 1670 1679 } 1671 1680 } 1672 1681 1673 updateGroupList();1682 UpdateUIGroupList(groupSelPref); 1674 1683 UpdateUsageUI(); 1675 1684 1676 if (m_currentItem) 1685 QStringList::const_iterator it = m_playList.begin(); 1686 for (; it != m_playList.end(); ++it) 1677 1687 { 1678 delete m_currentItem; 1679 m_currentItem = NULL; 1688 ProgramInfo *pginfo = FindProgramInUILists(*it); 1689 if (!pginfo) 1690 continue; 1691 MythUIButtonListItem *item = 1692 m_recordingList->GetItemByData(qVariantFromValue(pginfo)); 1693 if (item) 1694 item->DisplayState("yes", "playlist"); 1680 1695 } 1681 1696 1697 // If possible reselect the item selected before, 1698 // otherwise select the nearest available item. 1699 prefSelGroup = m_groupList->GetItemCurrent(); 1700 if (prefSelGroup && 1701 groupSelPref.contains(prefSelGroup->GetData().toString()) && 1702 itemSelPref.contains(prefSelGroup->GetData().toString())) 1703 { 1704 // the group is selected above in UpdateUIGroupList() 1705 QString groupname = prefSelGroup->GetData().toString(); 1706 VERBOSE(VB_IMPORTANT, QString("Selected Group: '%1'") 1707 .arg(groupname)); 1708 for (uint i = 0; i+1 < (uint)itemSelPref.size(); i+=2) 1709 { 1710 VERBOSE(VB_IMPORTANT, QString("Checking '%1':%2") 1711 .arg(itemSelPref[i]).arg(itemSelPref[i+1])); 1712 1713 if (itemSelPref[i] != groupname) 1714 continue; 1715 1716 const QString key = itemSelPref[i+1]; 1717 for (uint j = 0; j < (uint)m_recordingList->GetCount(); j++) 1718 { 1719 MythUIButtonListItem *item = m_recordingList->GetItemAt(j); 1720 ProgramInfo *pginfo = 1721 qVariantValue<ProgramInfo*>(item->GetData()); 1722 if (i==0 && pginfo) 1723 { 1724 VERBOSE(VB_IMPORTANT, QString(" against %1") 1725 .arg(pginfo->MakeUniqueKey())); 1726 } 1727 if (pginfo && (pginfo->MakeUniqueKey() == key)) 1728 { 1729 VERBOSE(VB_IMPORTANT, "Reselect success"); 1730 m_recordingList->SetItemCurrent(j); 1731 i = itemSelPref.size(); 1732 break; 1733 } 1734 } 1735 } 1736 } 1737 else 1738 { 1739 VERBOSE(VB_IMPORTANT, QString("prefSelGroup: 0x%1 in list of %2") 1740 .arg((uint64_t)prefSelGroup).arg(m_groupList->GetCount())); 1741 } 1742 1743 VERBOSE(VB_IMPORTANT, "UpdateUILists() -- end"); 1744 1682 1745 m_isFilling = false; 1683 1746 1684 1747 return true; … … 1686 1749 1687 1750 void PlaybackBox::playSelectedPlaylist(bool random) 1688 1751 { 1689 ProgramInfo *tmpItem; 1690 QStringList::Iterator it = m_playList.begin(); 1691 QStringList randomList = m_playList; 1692 bool playNext = true; 1693 int i = 0; 1694 1695 while (randomList.size() && playNext) 1752 if (random) 1696 1753 { 1697 if (random) 1698 i = (int)(1.0 * randomList.size() * rand() / (RAND_MAX + 1.0)); 1754 m_playListPlay.clear(); 1755 QStringList tmp = m_playList; 1756 while (!tmp.empty()) 1757 { 1758 uint i = rand() % tmp.size(); 1759 m_playListPlay.push_back(tmp[i]); 1760 tmp.removeAll(tmp[i]); 1761 } 1762 } 1763 else 1764 { 1765 m_playListPlay = m_playList; 1766 } 1699 1767 1700 it = randomList.begin() + i; 1701 1702 tmpItem = FindProgramInUILists(*it); 1703 1704 if ((tmpItem->availableStatus == asAvailable) || 1705 (tmpItem->availableStatus == asNotYetAvailable)) 1706 playNext = play(tmpItem, true); 1707 1708 randomList.erase(it); 1709 } 1768 QCoreApplication::postEvent( 1769 this, new MythEvent("PLAY_PLAYLIST")); 1710 1770 } 1711 1771 1712 1772 void PlaybackBox::playSelected(MythUIButtonListItem *item) … … 1728 1788 return; 1729 1789 } 1730 1790 1731 if ((pginfo->availableStatus == asAvailable) || 1732 (pginfo->availableStatus == asNotYetAvailable)) 1733 play(pginfo); 1734 else 1735 showAvailablePopup(pginfo); 1736 1791 Play(*pginfo, false); 1737 1792 } 1738 1793 1739 1794 void PlaybackBox::StopSelected(void) … … 1767 1822 push_onto_del(m_delList, *pginfo); 1768 1823 ShowDeletePopup(kDeleteRecording); 1769 1824 } 1770 else1771 showAvailablePopup(pginfo);1772 1825 } 1773 1826 1774 1827 void PlaybackBox::upcoming() 1775 1828 { 1776 ProgramInfo *pginfo = CurrentItem(); 1777 1778 if (!pginfo) 1779 return; 1780 1781 if (pginfo->availableStatus != asAvailable) 1782 { 1783 showAvailablePopup(pginfo); 1784 return; 1785 } 1786 1787 ShowUpcoming(pginfo); 1829 ProgramInfo *pginfo = CurrentItem(); 1830 if (pginfo) 1831 ShowUpcoming(pginfo); 1788 1832 } 1789 1833 1790 1834 ProgramInfo *PlaybackBox::CurrentItem(void) … … 1807 1851 void PlaybackBox::customEdit() 1808 1852 { 1809 1853 ProgramInfo *pginfo = CurrentItem(); 1810 1811 if (!pginfo) 1812 return; 1813 1814 if (pginfo->availableStatus != asAvailable) 1815 { 1816 showAvailablePopup(pginfo); 1817 return; 1818 } 1819 1820 EditCustom(pginfo); 1854 if (pginfo) 1855 EditCustom(pginfo); 1821 1856 } 1822 1857 1823 1858 void PlaybackBox::details() 1824 1859 { 1825 1860 ProgramInfo *pginfo = CurrentItem(); 1826 1827 if (!pginfo) 1828 return; 1829 1830 if (pginfo->availableStatus != asAvailable) 1831 showAvailablePopup(pginfo); 1832 else 1861 if (pginfo) 1833 1862 ShowDetails(pginfo); 1834 1863 } 1835 1864 … … 1895 1924 m_popupMenu->AddButton(tr("Add this Group to Playlist"), 1896 1925 SLOT(togglePlayListTitle())); 1897 1926 } 1898 else if (pginfo && pginfo->availableStatus == asAvailable)1927 else if (pginfo) 1899 1928 { 1900 1929 m_popupMenu->AddButton(tr("Add this recording to Playlist"), 1901 1930 SLOT(togglePlayListItem())); … … 1905 1934 m_popupMenu->AddButton(tr("Help (Status Icons)"), SLOT(showIconHelp())); 1906 1935 } 1907 1936 1908 void PlaybackBox::showActionsSelected()1937 bool PlaybackBox::Play(const ProgramInfo &rec, bool inPlaylist) 1909 1938 { 1910 if (GetFocusWidget() == m_groupList)1911 return;1912 1913 ProgramInfo *pginfo = CurrentItem();1914 1915 if (!pginfo)1916 return;1917 1918 if ((pginfo->availableStatus != asAvailable) &&1919 (pginfo->availableStatus != asFileNotFound))1920 showAvailablePopup(pginfo);1921 else1922 showActions(pginfo);1923 }1924 1925 bool PlaybackBox::play(ProgramInfo *rec, bool inPlaylist)1926 {1927 1939 bool playCompleted = false; 1928 1940 1929 if (!rec)1930 return false;1931 1932 1941 if (m_player) 1933 1942 return true; 1934 1943 1935 // TODO do this in another thread 1936 rec->pathname = rec->GetPlaybackURL(true); 1937 1938 if (rec->availableStatus == asNotYetAvailable) 1939 rec->availableStatus = asAvailable; 1940 1941 // TODO do this in another thread 1942 if (!rec->IsFileReadable()) 1944 if ((asAvailable != rec.availableStatus) || (0 == rec.filesize) || 1945 (rec.GetRecordBasename() == rec.pathname)) 1943 1946 { 1944 VERBOSE(VB_IMPORTANT, QString("PlaybackBox::play(): Error, %1 file " 1945 "not found").arg(rec->pathname)); 1946 1947 if (rec->recstatus == rsRecording) 1948 rec->availableStatus = asNotYetAvailable; 1949 else 1950 rec->availableStatus = asFileNotFound; 1951 1952 showAvailablePopup(rec); 1953 1947 m_helper.CheckAvailability( 1948 rec, (inPlaylist) ? kCheckForPlaylistAction : kCheckForPlayAction); 1954 1949 return false; 1955 1950 } 1956 1951 1957 if ((rec->filesize == 0) && (rec->GetFilesize() == 0)) 1958 { 1959 VERBOSE(VB_IMPORTANT, 1960 QString("PlaybackBox::play(): Error, %1 is zero-bytes in size") 1961 .arg(rec->pathname)); 1952 ProgramInfo *tvrec = new ProgramInfo(rec); 1962 1953 1963 if (rec->recstatus == rsRecording)1964 rec->availableStatus = asNotYetAvailable;1965 else1966 rec->availableStatus = asZeroByte;1967 1968 showAvailablePopup(rec);1969 1970 return false;1971 }1972 1973 ProgramInfo *tvrec = new ProgramInfo(*rec);1974 1975 1954 m_playingSomething = true; 1976 1955 1977 playCompleted = TV::StartTV(tvrec, false, inPlaylist, m_underNetworkControl); 1956 playCompleted = TV::StartTV( 1957 tvrec, false, inPlaylist, m_underNetworkControl); 1978 1958 1979 1959 m_playingSomething = false; 1980 1960 1981 1961 delete tvrec; 1982 1962 1983 UpdateUILists(); 1963 if (inPlaylist && !m_playListPlay.empty()) 1964 { 1965 QCoreApplication::postEvent( 1966 this, new MythEvent("PLAY_PLAYLIST")); 1967 } 1984 1968 1985 1969 return playCompleted; 1986 1970 } … … 2006 1990 ((delItem->availableStatus == asPendingDelete) || 2007 1991 (!REC_CAN_BE_DELETED(delItem)))) 2008 1992 { 2009 showAvailablePopup(delItem);2010 1993 return; 2011 1994 } 2012 1995 … … 2016 1999 if (!forceMetadataDelete) 2017 2000 delItem->UpdateLastDelete(true); 2018 2001 2002 delItem->availableStatus = asPendingDelete; 2019 2003 m_helper.DeleteRecording( 2020 2004 delItem->chanid.toUInt(), delItem->recstartts, forceMetadataDelete); 2021 2005 … … 2214 2198 return QString(); 2215 2199 } 2216 2200 2217 void PlaybackBox::showActions(ProgramInfo *pginfo)2218 {2219 if (!pginfo)2220 return;2221 2222 // TODO do this in another thread (IsFileReadable remote check)2223 if (!pginfo->IsFileReadable())2224 {2225 VERBOSE(VB_IMPORTANT, QString("PlaybackBox::showActions(): Error, %1 "2226 "file not found").arg(pginfo->pathname));2227 2228 pginfo->availableStatus = asFileNotFound;2229 showFileNotFoundActionPopup(pginfo);2230 }2231 else if (pginfo->availableStatus != asAvailable)2232 showAvailablePopup(pginfo);2233 else2234 showActionPopup(pginfo);2235 }2236 2237 2201 void PlaybackBox::doPIPPlay(void) 2238 2202 { 2239 2203 doPIPPlay(kPIPonTV); … … 2291 2255 2292 2256 uint other_delete_cnt = (m_delList.size() / 3) - 1; 2293 2257 2294 popupString(delItem, label);2258 label += CreateProgramInfoString(*delItem); 2295 2259 2296 2260 m_popupMenu = new MythDialogBox(label, m_popupStack, "pbbmainmenupopup"); 2297 2261 … … 2371 2335 } 2372 2336 } 2373 2337 2374 void PlaybackBox:: showAvailablePopup(ProgramInfo *rec)2338 void PlaybackBox::ShowAvailabilityPopup(const ProgramInfo &pginfo) 2375 2339 { 2376 if (!rec) 2377 return; 2378 2379 QString msg = rec->title; 2380 if (!rec->subtitle.isEmpty()) 2381 msg += " \"" + rec->subtitle + "\""; 2340 QString msg = pginfo.title; 2341 if (!pginfo.subtitle.isEmpty()) 2342 msg += " \"" + pginfo.subtitle + "\""; 2382 2343 msg += "\n"; 2383 2344 2384 switch ( rec->availableStatus)2345 switch (pginfo.availableStatus) 2385 2346 { 2386 2347 case asAvailable: 2387 if (rec->programflags & (FL_INUSERECORDING | FL_INUSEPLAYING))2388 {2389 QString byWho;2390 rec->IsInUse(byWho);2348 if (pginfo.programflags & (FL_INUSERECORDING | FL_INUSEPLAYING)) 2349 { 2350 QString byWho; 2351 pginfo.IsInUse(byWho); 2391 2352 2392 ShowOkPopup(tr("Recording Available\n") + msg +2393 tr("This recording is currently in "2394 "use by:") + "\n" + byWho);2395 }2396 else2397 {2398 ShowOkPopup(tr("Recording Available\n") + msg +2399 tr("This recording is currently "2400 "Available"));2401 }2402 break;2353 ShowOkPopup(tr("Recording Available\n") + msg + 2354 tr("This recording is currently in " 2355 "use by:") + "\n" + byWho); 2356 } 2357 else 2358 { 2359 ShowOkPopup(tr("Recording Available\n") + msg + 2360 tr("This recording is currently " 2361 "Available")); 2362 } 2363 break; 2403 2364 case asPendingDelete: 2404 ShowOkPopup(tr("Recording Unavailable\n") + msg +2405 tr("This recording is currently being "2406 "deleted and is unavailable"));2407 break;2365 ShowOkPopup(tr("Recording Unavailable\n") + msg + 2366 tr("This recording is currently being " 2367 "deleted and is unavailable")); 2368 break; 2408 2369 case asFileNotFound: 2409 ShowOkPopup(tr("Recording Unavailable\n") + msg +2410 tr("The file for this recording can "2411 "not be found"));2412 break;2370 ShowOkPopup(tr("Recording Unavailable\n") + msg + 2371 tr("The file for this recording can " 2372 "not be found")); 2373 break; 2413 2374 case asZeroByte: 2414 ShowOkPopup(tr("Recording Unavailable\n") + msg +2415 tr("The file for this recording is "2416 "empty."));2417 break;2375 ShowOkPopup(tr("Recording Unavailable\n") + msg + 2376 tr("The file for this recording is " 2377 "empty.")); 2378 break; 2418 2379 case asNotYetAvailable: 2419 ShowOkPopup(tr("Recording Unavailable\n") + msg +2420 tr("This recording is not yet "2421 "available."));2380 ShowOkPopup(tr("Recording Unavailable\n") + msg + 2381 tr("This recording is not yet " 2382 "available.")); 2422 2383 } 2423 2384 } 2424 2385 2425 2386 void PlaybackBox::showPlaylistPopup() 2426 2387 { 2427 if ( m_popupMenu)2388 if (!CreatePopupMenuPlaylist()) 2428 2389 return; 2429 2390 2430 if (!(m_popupMenu = createPlaylistPopupMenu()))2431 return;2432 2433 2391 m_popupMenu->AddButton(tr("Play"), SLOT(doPlayList())); 2434 2392 m_popupMenu->AddButton(tr("Shuffle Play"), SLOT(doPlayListRandom())); 2435 2393 m_popupMenu->AddButton(tr("Clear Playlist"), SLOT(doClearPlaylist())); … … 2458 2416 2459 2417 void PlaybackBox::showPlaylistStoragePopup() 2460 2418 { 2461 if ( m_popupMenu)2419 if (!CreatePopupMenuPlaylist()) 2462 2420 return; 2463 2421 2464 if (!(m_popupMenu = createPlaylistPopupMenu()))2465 return;2466 2467 2422 m_popupMenu->AddButton(tr("Change Recording Group"), 2468 2423 SLOT(ShowRecGroupChangerUsePlaylist())); 2469 2424 m_popupMenu->AddButton(tr("Change Playback Group"), … … 2474 2429 SLOT(doPlaylistExpireSetOn())); 2475 2430 } 2476 2431 2477 void PlaybackBox::showPlaylistJobPopup( )2432 void PlaybackBox::showPlaylistJobPopup(void) 2478 2433 { 2479 if ( m_popupMenu)2434 if (!CreatePopupMenuPlaylist()) 2480 2435 return; 2481 2436 2482 if (!(m_popupMenu = createPlaylistPopupMenu()))2483 return;2484 2485 2437 QString jobTitle; 2486 2438 QString command; 2487 2439 QStringList::Iterator it; … … 2589 2541 } 2590 2542 } 2591 2543 2592 MythDialogBox *PlaybackBox::createPopupMenu(const QString &label)2544 bool PlaybackBox::CreatePopupMenu(const QString &label) 2593 2545 { 2594 2546 if (m_popupMenu) 2595 return NULL;2547 return false; 2596 2548 2597 2549 m_popupMenu = new MythDialogBox(label, m_popupStack, "pbbmainmenupopup"); 2598 2550 2599 2551 if (!m_popupMenu) 2600 return NULL;2552 return false; 2601 2553 2602 2554 connect(m_popupMenu, SIGNAL(Exiting()), SLOT(popupClosed())); 2603 2555 … … 2610 2562 { 2611 2563 delete m_popupMenu; 2612 2564 m_popupMenu = NULL; 2613 return NULL;2565 return false; 2614 2566 } 2615 2567 2616 2568 return m_popupMenu; 2617 2569 } 2618 2570 2619 MythDialogBox *PlaybackBox::createProgramPopupMenu(const QString &title, 2620 ProgramInfo *pginfo) 2571 bool PlaybackBox::CreatePopupMenuPlaylist(void) 2621 2572 { 2622 if (m_popupMenu) 2623 return NULL; 2624 2625 QString label = title; 2626 if (pginfo) 2627 { 2628 popupString(pginfo, label); 2629 } 2630 else 2631 { 2632 ProgramInfo *pginfo = CurrentItem(); 2633 popupString(pginfo, label); 2634 } 2635 2636 return createPopupMenu(label); 2573 return CreatePopupMenu( 2574 tr("There is %n item(s) in the playlist. Actions affect " 2575 "all items in the playlist", "", m_playList.size())); 2637 2576 } 2638 2577 2639 MythDialogBox *PlaybackBox::createPlaylistPopupMenu()2640 {2641 if (m_popupMenu)2642 return NULL;2643 2644 QString label = tr("There is %n item(s) in the playlist. Actions affect "2645 "all items in the playlist", "", m_playList.size());2646 2647 return createPopupMenu(label);2648 }2649 2650 2578 void PlaybackBox::showPlayFromPopup() 2651 2579 { 2652 if (m_popupMenu) 2580 ProgramInfo *pginfo = CurrentItem(); 2581 if (!pginfo || !CreatePopupMenu(tr("Play Options"), *pginfo)) 2653 2582 return; 2654 2583 2655 if (!(m_popupMenu = createProgramPopupMenu(tr("Play Options"))))2656 return;2657 2658 2584 m_popupMenu->AddButton(tr("Play from bookmark"), SLOT(playSelected())); 2659 2585 m_popupMenu->AddButton(tr("Play from beginning"), SLOT(doPlayFromBeg())); 2660 2586 } 2661 2587 2662 2588 void PlaybackBox::showStoragePopup() 2663 2589 { 2664 if (m_popupMenu) 2590 ProgramInfo *pginfo = CurrentItem(); 2591 if (!pginfo || !CreatePopupMenu(tr("Storage Options"), *pginfo)) 2665 2592 return; 2666 2593 2667 if (!(m_popupMenu = createProgramPopupMenu(tr("Storage Options"))))2668 return;2669 2670 2594 m_popupMenu->AddButton(tr("Change Recording Group"), 2671 2595 SLOT(ShowRecGroupChanger())); 2672 2596 2673 2597 m_popupMenu->AddButton(tr("Change Playback Group"), 2674 2598 SLOT(ShowPlayGroupChanger())); 2675 2599 2676 ProgramInfo *pginfo = CurrentItem();2677 2600 if (pginfo) 2678 2601 { 2679 2602 if (pginfo->programflags & FL_AUTOEXP) … … 2694 2617 2695 2618 void PlaybackBox::showRecordingPopup() 2696 2619 { 2697 if (m_popupMenu) 2620 ProgramInfo *pginfo = CurrentItem(); 2621 if (!pginfo || !CreatePopupMenu(tr("Scheduling Options"), *pginfo)) 2698 2622 return; 2699 2623 2700 if (!(m_popupMenu = createProgramPopupMenu(tr("Scheduling Options"))))2701 return;2702 2703 2624 m_popupMenu->AddButton(tr("Edit Recording Schedule"), 2704 2625 SLOT(doEditScheduled())); 2705 2626 … … 2715 2636 2716 2637 void PlaybackBox::showJobPopup() 2717 2638 { 2718 if (m_popupMenu)2719 return;2720 2721 if (!(m_popupMenu = createProgramPopupMenu(tr("Job Options"))))2722 return;2723 2724 2639 ProgramInfo *pginfo = CurrentItem(); 2725 if (!pginfo )2640 if (!pginfo || !CreatePopupMenu(tr("Job Options"), *pginfo)) 2726 2641 return; 2727 2642 2728 2643 QString jobTitle; … … 2803 2718 2804 2719 void PlaybackBox::showTranscodingProfiles() 2805 2720 { 2806 if ( m_popupMenu)2721 if (!CreatePopupMenu(tr("Transcoding profiles"))) 2807 2722 return; 2808 2723 2809 if (!(m_popupMenu = createPopupMenu(tr("Transcoding profiles"))))2810 return;2811 2812 2724 m_popupMenu->AddButton(tr("Default"), SLOT(doBeginTranscoding())); 2813 2725 m_popupMenu->AddButton(tr("Autodetect"), 2814 2726 SLOT(changeProfileAndTranscodeAuto())); … … 2832 2744 doBeginTranscoding(); 2833 2745 } 2834 2746 2835 void PlaybackBox:: showActionPopup(ProgramInfo *pginfo)2747 void PlaybackBox::ShowActionPopup(const ProgramInfo &pginfo) 2836 2748 { 2837 if (m_popupMenu || !pginfo) 2749 QString label = 2750 (asFileNotFound == pginfo.availableStatus) ? 2751 tr("Recording file can not be found") : 2752 (asZeroByte == pginfo.availableStatus) ? 2753 tr("Recording file contains no data") : 2754 tr("Recording Options"); 2755 2756 if (!CreatePopupMenu(label, pginfo)) 2838 2757 return; 2839 2758 2840 QString label = tr("Recording Options"); 2841 if (!(m_popupMenu = createProgramPopupMenu(label, pginfo))) 2759 if ((asFileNotFound == pginfo.availableStatus) || 2760 (asZeroByte == pginfo.availableStatus)) 2761 { 2762 m_popupMenu->AddButton( 2763 tr("Show Program Details"), SLOT(showProgramDetails())); 2764 m_popupMenu->AddButton( 2765 tr("Delete"), SLOT(askDelete())); 2766 2767 if (m_playList.filter(pginfo.MakeUniqueKey()).size()) 2768 { 2769 m_popupMenu->AddButton( 2770 tr("Remove from Playlist"), SLOT(togglePlayListItem())); 2771 } 2772 else 2773 { 2774 m_popupMenu->AddButton( 2775 tr("Add to Playlist"), SLOT(togglePlayListItem())); 2776 } 2777 2842 2778 return; 2779 } 2843 2780 2844 2781 bool sameProgram = false; 2845 2782 2846 2783 if (m_player) 2847 sameProgram = m_player->IsSameProgram(0, pginfo);2784 sameProgram = m_player->IsSameProgram(0, &pginfo); 2848 2785 2849 2786 TVState tvstate = kState_None; 2850 2787 if (m_player) … … 2858 2795 } 2859 2796 else 2860 2797 { 2861 if (pginfo ->programflags & FL_BOOKMARK)2798 if (pginfo.programflags & FL_BOOKMARK) 2862 2799 m_popupMenu->AddButton(tr("Play from..."), 2863 2800 SLOT(showPlayFromPopup()), true); 2864 2801 else 2865 2802 m_popupMenu->AddButton(tr("Play"), SLOT(playSelected())); 2866 2803 2867 if (m_playList.filter(pginfo ->MakeUniqueKey()).size())2804 if (m_playList.filter(pginfo.MakeUniqueKey()).size()) 2868 2805 m_popupMenu->AddButton(tr("Remove from Playlist"), 2869 2806 SLOT(togglePlayListItem())); 2870 2807 else … … 2872 2809 SLOT(togglePlayListItem())); 2873 2810 } 2874 2811 2875 if (pginfo ->recstatus == rsRecording &&2812 if (pginfo.recstatus == rsRecording && 2876 2813 (!(sameProgram && 2877 2814 (tvstate == kState_WatchingLiveTV || 2878 2815 tvstate == kState_WatchingRecording)))) … … 2880 2817 m_popupMenu->AddButton(tr("Stop Recording"), SLOT(askStop())); 2881 2818 } 2882 2819 2883 if (pginfo ->programflags & FL_WATCHED)2820 if (pginfo.programflags & FL_WATCHED) 2884 2821 m_popupMenu->AddButton(tr("Mark as Unwatched"), SLOT(toggleWatched())); 2885 2822 else 2886 2823 m_popupMenu->AddButton(tr("Mark as Watched"), SLOT(toggleWatched())); … … 2893 2830 2894 2831 if (!sameProgram) 2895 2832 { 2896 if (pginfo ->recgroup == "Deleted")2833 if (pginfo.recgroup == "Deleted") 2897 2834 { 2898 push_onto_del(m_delList, *pginfo);2835 push_onto_del(m_delList, pginfo); 2899 2836 m_popupMenu->AddButton( 2900 2837 tr("Undelete"), SLOT(Undelete())); 2901 2838 m_popupMenu->AddButton( … … 2908 2845 } 2909 2846 } 2910 2847 2911 void PlaybackBox::showFileNotFoundActionPopup(ProgramInfo *pginfo) 2848 QString PlaybackBox::CreateProgramInfoString(const ProgramInfo &pginfo) const 2912 2849 { 2913 if (m_popupMenu || !pginfo)2914 return;2850 QDateTime recstartts = pginfo.recstartts; 2851 QDateTime recendts = pginfo.recendts; 2915 2852 2916 QString label = tr("Recording file can not be found");2917 if (!(m_popupMenu = createProgramPopupMenu(label, pginfo)))2918 return;2919 2920 m_popupMenu->AddButton(tr("Show Program Details"),2921 SLOT(showProgramDetails()));2922 m_popupMenu->AddButton(tr("Delete"), SLOT(askDelete()));2923 }2924 2925 void PlaybackBox::popupString(ProgramInfo *program, QString &message)2926 {2927 if (!program)2928 return;2929 2930 QDateTime recstartts = program->recstartts;2931 QDateTime recendts = program->recendts;2932 2933 2853 QString timedate = QString("%1, %2 - %3") 2934 .arg(recstartts.date().toString(m_formatLongDate))2935 .arg(recstartts.time().toString(m_formatTime))2936 .arg(recendts.time().toString(m_formatTime));2854 .arg(recstartts.date().toString(m_formatLongDate)) 2855 .arg(recstartts.time().toString(m_formatTime)) 2856 .arg(recendts.time().toString(m_formatTime)); 2937 2857 2938 QString title = p rogram->title;2858 QString title = pginfo.title; 2939 2859 2940 2860 QString extra; 2941 2861 2942 if (!p rogram->subtitle.isEmpty())2862 if (!pginfo.subtitle.isEmpty()) 2943 2863 { 2944 extra = program->subtitle; 2945 extra = (title.length() + extra.length() + 2 <= message.length()) ? 2946 QString(" -- ") + extra : QString('\n') + extra; 2947 2948 int maxll = max(max(message.length(),title.length()), 20); 2864 extra = QString('\n') + pginfo.subtitle; 2865 int maxll = max(title.length(), 20); 2949 2866 if (extra.length() > maxll) 2950 2867 extra = extra.left(maxll - 3) + "..."; 2951 2868 } 2952 2869 2953 message = QString("%1\n%2%3\n%4") 2954 .arg(message).arg(title).arg(extra).arg(timedate); 2870 return QString("\n%1%2\n%3").arg(title).arg(extra).arg(timedate); 2955 2871 } 2956 2872 2957 2873 void PlaybackBox::doClearPlaylist(void) … … 2965 2881 continue; 2966 2882 2967 2883 MythUIButtonListItem *item = 2968 m_recordingList->GetItemByData(qVariantFromValue(tmpItem));2884 m_recordingList->GetItemByData(qVariantFromValue(tmpItem)); 2969 2885 2970 2886 if (item) 2971 2887 item->DisplayState("no", "playlist"); … … 2976 2892 void PlaybackBox::doPlayFromBeg(void) 2977 2893 { 2978 2894 ProgramInfo *pginfo = CurrentItem(); 2979 pginfo->setIgnoreBookmark(true); 2980 playSelected(m_recordingList->GetItemCurrent()); 2895 if (pginfo) 2896 { 2897 pginfo->setIgnoreBookmark(true); 2898 playSelected(m_recordingList->GetItemCurrent()); 2899 } 2981 2900 } 2982 2901 2983 2902 void PlaybackBox::doPlayList(void) … … 3003 2922 3004 2923 void PlaybackBox::showProgramDetails() 3005 2924 { 3006 ProgramInfo *pginfo = CurrentItem(); 3007 2925 ProgramInfo *pginfo = CurrentItem(); 3008 2926 if (pginfo) 3009 2927 ShowDetails(pginfo); 3010 2928 } 3011 2929 3012 2930 void PlaybackBox::doEditScheduled() 3013 2931 { 3014 ProgramInfo *pginfo = CurrentItem(); 3015 3016 if (!pginfo) 3017 return; 3018 3019 if (pginfo->availableStatus != asAvailable) 3020 showAvailablePopup(pginfo); 3021 else 2932 ProgramInfo *pginfo = CurrentItem(); 2933 if (pginfo) 3022 2934 EditScheduled(pginfo); 3023 2935 } 3024 2936 … … 3144 3056 QStringList list; 3145 3057 for (it = m_playList.begin(); it != m_playList.end(); ++it) 3146 3058 { 3147 constProgramInfo *tmpItem = FindProgramInUILists(*it);3059 ProgramInfo *tmpItem = FindProgramInUILists(*it); 3148 3060 if (tmpItem && (REC_CAN_BE_DELETED(tmpItem))) 3149 3061 { 3062 tmpItem->availableStatus = asPendingDelete; 3150 3063 list.push_back(tmpItem->chanid); 3151 3064 list.push_back(tmpItem->recstartts.toString(Qt::ISODate)); 3152 3065 list.push_back(forceDeleteStr); … … 3159 3072 } 3160 3073 m_playList.clear(); 3161 3074 3162 m_helper.DeleteRecordings(list); 3075 if (!list.empty()) 3076 m_helper.DeleteRecordings(list); 3163 3077 3164 3078 doClearPlaylist(); 3165 3079 } … … 3255 3169 return NULL; 3256 3170 } 3257 3171 3258 void PlaybackBox::UpdateProgramInfo(const ProgramInfo &pginfo)3259 {3260 // LiveTV ProgramInfo's are not in the aggregated list3261 ProgramList::iterator _it[2] = {3262 m_progLists[tr("LiveTV").toLower()].begin(), m_progLists[""].begin() };3263 ProgramList::iterator _end[2] = {3264 m_progLists[tr("LiveTV").toLower()].end(), m_progLists[""].end() };3265 3266 // We do not update the pathname as it may be localized3267 // in the remote ProgramInfo.3268 3269 for (uint i = 0; i < 2; i++)3270 {3271 ProgramList::iterator it = _it[i], end = _end[i];3272 for (; it != end; ++it)3273 {3274 if (pginfo.chanid == (*it)->chanid &&3275 pginfo.recstartts == (*it)->recstartts)3276 {3277 QString pathname = (**it).pathname;3278 **it = pginfo;3279 (**it).pathname = pathname;3280 break;3281 }3282 }3283 }3284 3285 // now do the cache..3286 m_programInfoCache.Update(pginfo);3287 }3288 3289 void PlaybackBox::UpdateProgramInfo(3290 uint chanid, const QDateTime &recstartts, uint64_t filesize)3291 {3292 // LiveTV ProgramInfo's are not in the aggregated list3293 ProgramList::iterator _it[2] = {3294 m_progLists[tr("LiveTV").toLower()].begin(), m_progLists[""].begin() };3295 ProgramList::iterator _end[2] = {3296 m_progLists[tr("LiveTV").toLower()].end(), m_progLists[""].end() };3297 3298 for (uint i = 0; i < 2; i++)3299 {3300 ProgramList::iterator it = _it[i], end = _end[i];3301 for (; it != end; ++it)3302 {3303 if (chanid == (*it)->chanid.toUInt() &&3304 recstartts == (*it)->recstartts)3305 {3306 (*it)->filesize = filesize;3307 if (filesize)3308 (*it)->availableStatus = asAvailable;3309 break;3310 }3311 }3312 }3313 3314 // now do the cache..3315 m_programInfoCache.UpdateFileSize(chanid, recstartts, filesize);3316 }3317 3318 3172 void PlaybackBox::toggleWatched(void) 3319 3173 { 3320 3174 MythUIButtonListItem *item = m_recordingList->GetItemCurrent(); … … 3452 3306 if (!pginfo) 3453 3307 return; 3454 3308 3455 if (pginfo->availableStatus != asAvailable)3456 {3457 showAvailablePopup(pginfo);3458 return;3459 }3460 3461 3309 togglePlayListItem(pginfo); 3462 3310 3463 3311 if (GetFocusWidget() == m_recordingList) … … 3469 3317 if (!pginfo) 3470 3318 return; 3471 3319 3472 if (pginfo->availableStatus != asAvailable)3473 {3474 showAvailablePopup(pginfo);3475 return;3476 }3477 3478 3320 QString key = pginfo->MakeUniqueKey(); 3479 3321 3480 3322 MythUIButtonListItem *item = … … 3683 3525 else if (action == "PLAYBACK") 3684 3526 playSelected(m_recordingList->GetItemCurrent()); 3685 3527 else if (action == "INFO") 3686 showActionsSelected(); 3528 { 3529 if (GetFocusWidget() != m_groupList) 3530 { 3531 ProgramInfo *pginfo = CurrentItem(); 3532 if (pginfo) 3533 { 3534 m_helper.CheckAvailability( 3535 *pginfo, kCheckForMenuAction); 3536 3537 if ((asPendingDelete == pginfo->availableStatus) || 3538 (asPendingDelete == pginfo->availableStatus)) 3539 { 3540 ShowAvailabilityPopup(*pginfo); 3541 } 3542 else 3543 { 3544 ShowActionPopup(*pginfo); 3545 } 3546 } 3547 } 3548 } 3687 3549 else if (action == "DETAILS") 3688 3550 details(); 3689 3551 else if (action == "CUSTOMEDIT") … … 3820 3682 return; 3821 3683 3822 3684 m_delList = me->ExtraDataList(); 3685 for (uint i = 0; i+2 < (uint)m_delList.size(); i+=3) 3686 { 3687 const ProgramInfo *pginfo = 3688 FindProgramInUILists( 3689 m_delList[i+0].toUInt(), 3690 QDateTime::fromString(m_delList[i+1], Qt::ISODate)); 3691 if (pginfo) 3692 m_helper.CheckAvailability(*pginfo, kCheckForCache); 3693 } 3694 3823 3695 bool forceDelete = m_delList[2].toUInt(); 3824 3696 if (!forceDelete) 3825 3697 ShowDeletePopup(kForceDeleteRecording); … … 3830 3702 { 3831 3703 HandlePreviewEvent(me->ExtraData(0), me->ExtraData(1)); 3832 3704 } 3705 else if (message == "AVAILABILITY" && me->ExtraDataCount() == 8) 3706 { 3707 const uint kMaxUIWaitTime = 100; // ms 3708 QStringList list = me->ExtraDataList(); 3709 QString key = list[0]; 3710 CheckAvailabilityType cat = 3711 (CheckAvailabilityType) list[1].toInt(); 3712 AvailableStatusType availableStatus = 3713 (AvailableStatusType) list[2].toInt(); 3714 uint64_t fs = list[3].toULongLong(); 3715 QTime tm; 3716 tm.setHMS(list[4].toUInt(), list[5].toUInt(), 3717 list[6].toUInt(), list[7].toUInt()); 3718 QTime now = QTime::currentTime(); 3719 int time_elapsed = tm.msecsTo(now); 3720 if (time_elapsed < 0) 3721 time_elapsed += 24 * 60 * 60 * 1000; 3722 3723 AvailableStatusType old_avail = availableStatus; 3724 ProgramInfo *pginfo = FindProgramInUILists(key); 3725 if (pginfo) 3726 { 3727 pginfo->filesize = max(pginfo->filesize, fs); 3728 old_avail = pginfo->availableStatus; 3729 pginfo->availableStatus = availableStatus; 3730 } 3731 3732 if ((uint)time_elapsed >= kMaxUIWaitTime) 3733 m_playListPlay.clear(); 3734 3735 bool playnext = ((kCheckForPlaylistAction == cat) && 3736 !m_playListPlay.empty()); 3737 3738 3739 if (((kCheckForPlayAction == cat) || 3740 (kCheckForPlaylistAction == cat)) && 3741 ((uint)time_elapsed < kMaxUIWaitTime)) 3742 { 3743 if (asAvailable != availableStatus) 3744 { 3745 if (kCheckForPlayAction == cat) 3746 ShowAvailabilityPopup(*pginfo); 3747 } 3748 else if (pginfo) 3749 { 3750 playnext = false; 3751 Play(*pginfo, kCheckForPlaylistAction == cat); 3752 } 3753 } 3754 3755 if (playnext) 3756 { 3757 // failed to play this item, instead 3758 // play the next item on the list.. 3759 QCoreApplication::postEvent( 3760 this, new MythEvent("PLAY_PLAYLIST")); 3761 } 3762 3763 if (old_avail != availableStatus) 3764 UpdateUIListItem(pginfo); 3765 } 3766 else if ((message == "PLAY_PLAYLIST") && !m_playListPlay.empty()) 3767 { 3768 QString key = m_playListPlay.front(); 3769 m_playListPlay.pop_front(); 3770 3771 if (!m_playListPlay.empty()) 3772 { 3773 const ProgramInfo *pginfo = 3774 FindProgramInUILists(m_playListPlay.front()); 3775 if (pginfo) 3776 m_helper.CheckAvailability(*pginfo, kCheckForCache); 3777 } 3778 3779 ProgramInfo *pginfo = FindProgramInUILists(key); 3780 if (pginfo) 3781 Play(*pginfo, true); 3782 } 3833 3783 } 3834 3784 else 3835 3785 ScheduleCommon::customEvent(event); … … 3838 3788 void PlaybackBox::HandleRecordingRemoveEvent( 3839 3789 uint chanid, const QDateTime &recstartts) 3840 3790 { 3841 ProgramInfo *pginfo = FindProgramInUILists(chanid, recstartts); 3842 if (pginfo && ((pginfo->availableStatus != asPendingDelete) || 3843 (m_currentGroup == m_watchGroupLabel))) 3791 if (!m_programInfoCache.Remove(chanid, recstartts)) 3844 3792 { 3845 m_recordingList->RemoveItem( 3846 m_recordingList->GetItemByData(qVariantFromValue(pginfo))); 3847 if (m_recordingList->GetCount() == 0) 3848 m_groupList->RemoveItem(m_groupList->GetItemCurrent()); 3793 VERBOSE(VB_IMPORTANT, LOC_WARN + 3794 QString("Failed to remove %1:%2, reloading list") 3795 .arg(chanid).arg(recstartts.toString(Qt::ISODate))); 3796 m_programInfoCache.ScheduleLoad(); 3797 return; 3849 3798 } 3850 3799 3851 if (!m_programInfoCache.Remove(chanid, recstartts)) 3852 m_programInfoCache.ScheduleLoad(); 3853 else 3854 ScheduleUpdateUIList(); 3800 { 3801 ProgramInfo *tmp = CurrentItem(); 3802 if (tmp) 3803 { 3804 VERBOSE(VB_IMPORTANT, QString("1 CurrentItem: %1:%2, %3") 3805 .arg(tmp->title).arg(tmp->subtitle) 3806 .arg(tmp->availableStatus)); 3807 } 3808 } 3855 3809 3810 MythUIButtonListItem *sel_item = m_groupList->GetItemCurrent(); 3811 QString groupname; 3812 if (sel_item) 3813 groupname = sel_item->GetData().toString(); 3814 3815 ProgramMap::iterator git = m_progLists.begin(); 3816 while (git != m_progLists.end()) 3817 { 3818 ProgramList::iterator pit = (*git).begin(); 3819 while (pit != (*git).end()) 3820 { 3821 if ((*pit)->recstartts == recstartts && 3822 (*pit)->chanid.toUInt() == chanid) 3823 { 3824 if (!git.key().isEmpty() && git.key() == groupname) 3825 { 3826 MythUIButtonListItem *item_by_data = 3827 m_recordingList->GetItemByData( 3828 qVariantFromValue(*pit)); 3829 MythUIButtonListItem *item_cur = 3830 m_recordingList->GetItemCurrent(); 3831 3832 if (item_cur && (item_by_data == item_cur)) 3833 { 3834 VERBOSE(VB_IMPORTANT, "Attempting to select next"); 3835 MythUIButtonListItem *item_next = 3836 m_recordingList->GetItemNext(item_cur); 3837 if (item_next) 3838 { 3839 VERBOSE(VB_IMPORTANT, "Selecting next"); 3840 m_recordingList->SetItemCurrent(item_next); 3841 } 3842 } 3843 3844 m_recordingList->RemoveItem(item_by_data); 3845 } 3846 pit = (*git).erase(pit); 3847 } 3848 else 3849 { 3850 pit++; 3851 } 3852 } 3853 3854 if ((*git).empty()) 3855 { 3856 VERBOSE(VB_IMPORTANT, QString("Group '%1' empty").arg(git.key())); 3857 if (!groupname.isEmpty() && (git.key() == groupname)) 3858 { 3859 VERBOSE(VB_IMPORTANT, "Attempting to select next group"); 3860 MythUIButtonListItem *next_item = 3861 m_groupList->GetItemNext(sel_item); 3862 if (next_item) 3863 { 3864 VERBOSE(VB_IMPORTANT, "Selecting next group"); 3865 m_groupList->SetItemCurrent(next_item); 3866 } 3867 3868 m_groupList->RemoveItem(sel_item); 3869 3870 sel_item = next_item; 3871 groupname = ""; 3872 if (sel_item) 3873 groupname = sel_item->GetData().toString(); 3874 } 3875 git = m_progLists.erase(git); 3876 } 3877 else 3878 git++; 3879 } 3880 3881 { 3882 ProgramInfo *tmp = CurrentItem(); 3883 if (tmp) 3884 { 3885 VERBOSE(VB_IMPORTANT, QString("1 Selected Item: %1:%2, %3") 3886 .arg(tmp->title).arg(tmp->subtitle) 3887 .arg(tmp->availableStatus)); 3888 } 3889 } 3890 3856 3891 m_helper.ForceFreeSpaceUpdate(); 3857 3892 } 3858 3893 … … 3864 3899 3865 3900 void PlaybackBox::HandleUpdateProgramInfoEvent(const ProgramInfo &evinfo) 3866 3901 { 3867 ProgramInfo *dst = FindProgramInUILists(evinfo); 3868 QString old_recgroup; 3869 if (dst) 3870 old_recgroup = dst->recgroup; 3902 QString old_recgroup = m_programInfoCache.GetRecGroup( 3903 evinfo.chanid.toUInt(), evinfo.recstartts); 3871 3904 3872 UpdateProgramInfo(evinfo);3905 m_programInfoCache.Update(evinfo); 3873 3906 3874 // If the program is not in the the recording lists, then it 3875 // is either a program that was just removed from the "LiveTV" 3876 // recording list and should possibly be displayed now, or it 3877 // is still in the "LiveTV" recording group and we're not 3878 // displaying programs in that group. Handle appropriately.. 3879 if (!dst) 3907 // If the recording group has changed, reload lists from the recently 3908 // updated cache; if not, only update UI for the updated item 3909 if (evinfo.recgroup == old_recgroup) 3880 3910 { 3881 if (evinfo.recgroup != "LiveTV") 3882 ScheduleUpdateUIList(); 3911 ProgramInfo *dst = FindProgramInUILists(evinfo); 3912 if (dst) 3913 UpdateUIListItem(dst); 3883 3914 return; 3884 3915 } 3885 3916 3886 // If the recording group has changed, reload lists from the recently 3887 // updated cache; if not, only update UI for the updated item 3888 if (dst->recgroup != old_recgroup) 3889 ScheduleUpdateUIList(); 3890 else 3891 UpdateUIListItem(dst); 3917 ScheduleUpdateUIList(); 3892 3918 } 3893 3919 3894 3920 void PlaybackBox::HandleUpdateProgramInfoFileSizeEvent( 3895 3921 uint chanid, const QDateTime &recstartts, uint64_t filesize) 3896 3922 { 3897 UpdateProgramInfo(chanid, recstartts, filesize);3923 m_programInfoCache.UpdateFileSize(chanid, recstartts, filesize); 3898 3924 3899 3925 ProgramInfo *dst = FindProgramInUILists(chanid, recstartts); 3900 3926 if (dst) … … 4135 4161 void PlaybackBox::ShowRecGroupChanger(bool use_playlist) 4136 4162 { 4137 4163 m_op_on_playlist = use_playlist; 4164 4165 ProgramInfo *pginfo = NULL; 4166 if (use_playlist) 4167 { 4168 if (!m_playList.empty()) 4169 pginfo = FindProgramInUILists(m_playList[0]); 4170 } 4171 else 4172 pginfo = CurrentItem(); 4173 4174 if (!pginfo) 4175 return; 4176 4138 4177 MSqlQuery query(MSqlQuery::InitCon()); 4139 4178 query.prepare( 4140 4179 "SELECT recgroup, COUNT(title) FROM recorded " 4141 4180 "WHERE deletepending = 0 GROUP BY recgroup ORDER BY recgroup"); 4142 4181 4143 QStringList groupNames; 4144 QStringList displayNames; 4145 QString selected; 4182 QStringList displayNames(tr("Add New")); 4183 QStringList groupNames("addnewgroup"); 4146 4184 4147 groupNames.append("addnewgroup");4148 displayNames.append(tr("Add New"));4185 if (!query.exec()) 4186 return; 4149 4187 4150 if (query.exec())4188 while (query.next()) 4151 4189 { 4152 QString itemStr; 4153 QString dispGroup; 4154 while (query.next()) 4155 { 4156 dispGroup = query.value(0).toString(); 4190 QString dispGroup = query.value(0).toString(); 4191 groupNames.push_back(dispGroup); 4157 4192 4158 groupNames.append(dispGroup); 4193 if (dispGroup == "Default") 4194 dispGroup = tr("Default"); 4195 else if (dispGroup == "LiveTV") 4196 dispGroup = tr("LiveTV"); 4197 else if (dispGroup == "Deleted") 4198 dispGroup = tr("Deleted"); 4159 4199 4160 if (dispGroup == "Default") 4161 dispGroup = tr("Default"); 4162 else if (dispGroup == "LiveTV") 4163 dispGroup = tr("LiveTV"); 4164 else if (dispGroup == "Deleted") 4165 dispGroup = tr("Deleted"); 4200 QString itemStr = tr("item(s)", "", query.value(1).toInt()); 4166 4201 4167 itemStr = tr("item(s)", "", query.value(1).toInt()); 4168 4169 displayNames.append(QString("%1 [%2 %3]").arg(dispGroup) 4170 .arg(query.value(1).toInt()).arg(itemStr)); 4171 } 4202 displayNames.push_back( 4203 QString("%1 [%2 %3]") 4204 .arg(dispGroup).arg(query.value(1).toInt()).arg(itemStr)); 4172 4205 } 4173 4206 4174 ProgramInfo *pginfo = CurrentItem();4175 selected = pginfo->recgroup;4207 QString label = tr("Select Recording Group") + 4208 CreateProgramInfoString(*pginfo); 4176 4209 4177 QString label = tr("Select Recording Group"); 4210 GroupSelector *rgChanger = new GroupSelector( 4211 m_popupStack, label, displayNames, groupNames, pginfo->recgroup); 4178 4212 4179 popupString(pginfo, label);4180 4181 GroupSelector *rgChanger = new GroupSelector(m_popupStack, label,4182 displayNames, groupNames,4183 selected);4184 4185 4213 if (rgChanger->Create()) 4186 4214 { 4187 4215 connect(rgChanger, SIGNAL(result(QString)), SLOT(setRecGroup(QString))); … … 4195 4223 void PlaybackBox::ShowPlayGroupChanger(bool use_playlist) 4196 4224 { 4197 4225 m_op_on_playlist = use_playlist; 4198 QStringList groupNames;4199 QStringList displayNames;4200 QString selected;4201 4226 4202 displayNames.append(tr("Default")); 4203 groupNames.append("Default"); 4204 4205 QStringListIterator it(PlayGroup::GetNames()); 4206 while (it.hasNext()) 4227 ProgramInfo *pginfo = NULL; 4228 if (use_playlist) 4207 4229 { 4208 QString group = it.next(); 4209 displayNames.append(group); 4210 groupNames.append(group); 4230 if (!m_playList.empty()) 4231 pginfo = FindProgramInUILists(m_playList[0]); 4211 4232 } 4233 else 4234 pginfo = CurrentItem(); 4212 4235 4213 ProgramInfo *pginfo = CurrentItem();4214 selected = pginfo->playgroup;4236 if (!pginfo) 4237 return; 4215 4238 4216 QString label = tr("Select Playback Group"); 4239 QStringList groupNames(tr("Default")); 4240 QStringList displayNames("Default"); 4217 4241 4218 popupString(pginfo, label); 4242 QStringList list = PlayGroup::GetNames(); 4243 QStringList::const_iterator it = list.begin(); 4244 for (; it != list.end(); ++it) 4245 { 4246 displayNames.push_back(*it); 4247 groupNames.push_back(*it); 4248 } 4219 4249 4250 QString label = tr("Select Playback Group") + 4251 CreateProgramInfoString(*pginfo); 4252 4220 4253 GroupSelector *pgChanger = new GroupSelector(m_popupStack, label, 4221 4254 displayNames, groupNames, 4222 selected);4255 pginfo->playgroup); 4223 4256 4224 4257 if (pgChanger->Create()) 4225 4258 { … … 4362 4395 RecordingInfo ri(*p); 4363 4396 ri.ApplyRecordRecGroupChange(newRecGroup); 4364 4397 *p = ri; 4398 UpdateUILists(); 4365 4399 } 4366 4400 4367 4401 void PlaybackBox::setPlayGroup(QString newPlayGroup) -
programs/mythfrontend/playbackboxhelper.h
35 35 typedef QMap<QString,PreviewGenState> PreviewMap; 36 36 typedef QMap<QString,QDateTime> FileTimeStampMap; 37 37 38 typedef enum CheckAvailabilityType { 39 kCheckForCache, 40 kCheckForMenuAction, 41 kCheckForPlayAction, 42 kCheckForPlaylistAction, 43 } CheckAvailabilityType; 44 38 45 class PlaybackBoxHelper : public QThread 39 46 { 40 47 friend class PBHEventHandler; … … 51 58 uint chanid, const QDateTime &recstartts, bool forceDelete); 52 59 void DeleteRecordings(const QStringList&); 53 60 void UndeleteRecording(uint chanid, const QDateTime &recstartts); 61 void CheckAvailability(const ProgramInfo&, 62 CheckAvailabilityType cat = kCheckForCache); 54 63 void GetPreviewImage(const ProgramInfo&); 55 64 56 65 virtual void run(void); // QThread -
programs/mythfrontend/playbackboxhelper.cpp
131 131 } 132 132 } 133 133 } 134 else if (me->Message() == "CHECK_AVAILABILITY") 135 { 136 CheckAvailabilityType cat = kCheckForCache; 137 QTime tm; 138 if (me->ExtraDataCount() >= 5) 139 { 140 cat = (CheckAvailabilityType) me->ExtraData(0).toUInt(); 141 tm.setHMS( 142 me->ExtraData(1).toUInt(), 143 me->ExtraData(2).toUInt(), 144 me->ExtraData(3).toUInt(), 145 me->ExtraData(4).toUInt()); 146 } 147 ProgramInfo evinfo; 148 if (!evinfo.FromStringList(me->ExtraDataList(), 5)) 149 return true; 150 151 AvailableStatusType availableStatus = asAvailable; 152 // Note IsFileReadable() implicitly calls GetPlaybackURL 153 // when necessary, we rely on this. 154 if (!evinfo.IsFileReadable()) 155 { 156 VERBOSE(VB_IMPORTANT, LOC_ERR + 157 QString("CHECK_AVAILABILITY '%1' " 158 "file not found") 159 .arg(evinfo.pathname)); 160 availableStatus = asFileNotFound; 161 } 162 else if (0 == evinfo.filesize) 163 { 164 evinfo.filesize = evinfo.GetFilesize(); 165 if (0 == evinfo.filesize) 166 { 167 availableStatus = (evinfo.recstatus == rsRecording) ? 168 asNotYetAvailable : asZeroByte; 169 } 170 } 171 172 QStringList list; 173 list.push_back(evinfo.MakeUniqueKey()); 174 list.push_back(QString::number((int)cat)); 175 list.push_back(QString::number((int)availableStatus)); 176 list.push_back(QString::number(evinfo.filesize)); 177 list.push_back(QString::number(tm.hour())); 178 list.push_back(QString::number(tm.minute())); 179 list.push_back(QString::number(tm.second())); 180 list.push_back(QString::number(tm.msec())); 181 MythEvent *e = new MythEvent("AVAILABILITY", list); 182 QCoreApplication::postEvent(m_pbh.m_listener, e); 183 } 134 184 } 135 185 136 186 return QObject::event(e); … … 258 308 return m_freeSpaceUsedMB; 259 309 } 260 310 311 void PlaybackBoxHelper::CheckAvailability( 312 const ProgramInfo &pginfo, CheckAvailabilityType cat) 313 { 314 QTime tm = QTime::currentTime(); 315 QStringList list(QString::number((int)cat)); 316 list.push_back(QString::number(tm.hour())); 317 list.push_back(QString::number(tm.minute())); 318 list.push_back(QString::number(tm.second())); 319 list.push_back(QString::number(tm.msec())); 320 pginfo.ToStringList(list); 321 MythEvent *e = new MythEvent("CHECK_AVAILABILITY", list); 322 QCoreApplication::postEvent(m_eventHandler, e); 323 } 324 261 325 void PlaybackBoxHelper::GetPreviewImage(const ProgramInfo &pginfo) 262 326 { 263 327 QStringList extra; -
programs/mythfrontend/programinfocache.h
38 38 bool Update(const ProgramInfo&); 39 39 bool UpdateFileSize(uint chanid, const QDateTime &recstartts, 40 40 uint64_t filesize); 41 QString GetRecGroup(uint chanid, const QDateTime &recstartts) const; 41 42 void GetOrdered(vector<ProgramInfo*> &list, bool newest_first = false); 42 43 /// \note This must only be called from the UI thread. 43 44 bool empty(void) const { return m_cache.empty(); } -
programs/mythfrontend/programinfocache.cpp
185 185 return it != m_cache.end(); 186 186 } 187 187 188 /** \brief Returns the ProgramInfo::recgroup or an empty string if not found. 189 * \note This must only be called from the UI thread. 190 */ 191 QString ProgramInfoCache::GetRecGroup( 192 uint chanid, const QDateTime &recstartts) const 193 { 194 QMutexLocker locker(&m_lock); 195 196 Cache::const_iterator it = m_cache.find(PICKey(chanid,recstartts)); 197 198 QString recgroup; 199 if (it != m_cache.end()) 200 recgroup = it->second->recgroup; 201 202 return recgroup; 203 } 204 188 205 /** \brief Adds a ProgramInfo to the cache. 189 206 * \note This must only be called from the UI thread. 190 207 */ -
programs/mythfrontend/playbackbox.h
142 142 void upcoming(); 143 143 void details(); 144 144 void StopSelected(void); 145 void showActionsSelected();146 145 void showMetadataEditor(); 147 146 void showGroupFilter(); 148 147 void showRecGroupPasswordChanger(); 149 MythDialogBox *createPopupMenu(const QString &title);150 MythDialogBox *createProgramPopupMenu(const QString &title,151 ProgramInfo *pginfo = NULL);152 MythDialogBox *createPlaylistPopupMenu();153 148 void showPlayFromPopup(); 154 149 void showRecordingPopup(); 155 150 void showJobPopup(); … … 263 258 264 259 private: 265 260 bool UpdateUILists(void); 261 void UpdateUIGroupList(const QStringList &groupPreferences); 262 266 263 void UpdateProgressBar(void); 267 264 268 265 QString cutDown(const QString &, QFont *, int); 269 266 270 bool play(ProgramInfo *rec, bool inPlaylist = false); 271 void showActions(ProgramInfo *); 267 bool Play(const ProgramInfo &rec, bool inPlaylist); 272 268 ProgramInfo *CurrentItem(void); 273 269 274 270 void togglePlayListItem(ProgramInfo *pginfo); … … 286 282 void RemoveProgram(uint chanid, const QDateTime &recstartts, 287 283 bool forgetHistory, bool forceMetadataDelete); 288 284 void ShowDeletePopup(DeletePopupType); 289 void showActionPopup(ProgramInfo *program); 290 void showFileNotFoundActionPopup(ProgramInfo *program); 291 void popupString(ProgramInfo *program, QString &message); 285 void ShowAvailabilityPopup(const ProgramInfo&); 286 void ShowActionPopup(const ProgramInfo&); 292 287 293 void showAvailablePopup(ProgramInfo *rec);294 295 288 QString getRecGroupPassword(const QString &recGroup); 296 289 void fillRecGroupPasswordCache(void); 297 290 … … 302 295 303 296 bool IsUsageUIVisible(void) const; 304 297 305 void updateGroupList();306 298 void updateIcons(const ProgramInfo *pginfo = NULL); 307 299 void UpdateUsageUI(void); 308 300 void updateGroupInfo(const QString &groupname, const QString &grouplabel); 309 void UpdateProgramInfo(const ProgramInfo &pginfo);310 void UpdateProgramInfo(311 uint chanid, const QDateTime &recstartts, uint64_t filesize);312 301 313 302 void UpdateUIListItem( 314 303 ProgramInfo *ProgramInfo_pointer_from_FindProgramInUILists); … … 326 315 327 316 void ShowMenu(void); 328 317 318 bool CreatePopupMenu(const QString &title); 319 bool CreatePopupMenu(const QString &title, const ProgramInfo &pginfo) 320 { return CreatePopupMenu(title + CreateProgramInfoString(pginfo)); } 321 bool CreatePopupMenuPlaylist(void); 322 323 QString CreateProgramInfoString(const ProgramInfo &program) const; 324 325 private: 329 326 MythUIButtonList *m_groupList; 330 327 MythUIButtonList *m_recordingList; 331 328 … … 405 402 // Other state 406 403 /// Program[s] currently selected for deletion 407 404 QStringList m_delList; 408 /// Program currently selected during an update409 ProgramInfo *m_currentItem;410 405 /// Group currently selected 411 406 QString m_currentGroup; 412 407 413 408 // Play List support 414 409 QStringList m_playList; ///< list of selected items "play list" 415 410 bool m_op_on_playlist; 411 QStringList m_playListPlay; ///< list of items being played. 416 412 417 413 ProgramInfoCache m_programInfoCache; 418 414
