Ticket #6158: PBBMVExport.5.diff
File PBBMVExport.5.diff, 20.4 KB (added by , 17 years ago) |
---|
-
mythtv/programs/mythfrontend/playbackbox.cpp
20 20 #include "mythdirs.h" 21 21 #include "mythcontext.h" 22 22 #include "mythdbcon.h" 23 #include "mythdb.h" 23 24 #include "mythverbose.h" 24 25 #include "programinfo.h" 25 26 #include "scheduledrecording.h" … … 44 45 #define LOC QString("PlaybackBox: ") 45 46 #define LOC_ERR QString("PlaybackBox Error: ") 46 47 48 QString customExportFile = NULL; 49 QString customExportDir = NULL; 50 47 51 #define REC_CAN_BE_DELETED(rec) \ 48 52 ((((rec)->programflags & FL_INUSEPLAYING) == 0) && \ 49 53 ((((rec)->programflags & FL_INUSERECORDING) == 0) || \ … … 1815 1819 RemoteStopRecording(rec); 1816 1820 } 1817 1821 1822 void PlaybackBox::mvexport(ProgramInfo *rec) 1823 { 1824 1825 // User Rating Adjustment 1826 QString exportRating = QString::number((int)((rec->stars * 10.0) + 0.5)); 1827 1828 // Stuff necessary to perform the copy command 1829 1830 QString copyFrom = rec->GetPlaybackURL(false, true); 1831 QString baseMVDir = gContext->GetSetting("VideoStartupDir"); 1832 QString MVFileFormat; 1833 QString MVDirFormat; 1834 QString copyToDir; 1835 QString copyToFile; 1836 QString extension; 1837 1838 // Check the original extension 1839 1840 QRegExp rx(".*\\.(\\w+)$"); 1841 int pos = rx.indexIn(copyFrom); 1842 if (pos > -1) 1843 { 1844 extension = rx.cap(1); 1845 } 1846 else 1847 { 1848 extension = ""; 1849 } 1850 1851 // If a custom export string is used, use it. 1852 // Also replace %VARIABLES% with actual values. 1853 1854 if (customExportFile.isEmpty()) 1855 { 1856 QString defaultDir = gContext->GetSetting("TVExportDirFormat", 1857 "Television/%TITLE%/"); 1858 QString defaultFile = gContext->GetSetting("TVExportFileFormat", 1859 "%TITLE% - %SUBTITLE%"); 1860 MVDirFormat = replaceExportVariables(rec, defaultDir); 1861 MVFileFormat = replaceExportVariables(rec, defaultFile); 1862 } 1863 else 1864 { 1865 MVDirFormat = replaceExportVariables(rec, customExportDir); 1866 MVFileFormat = replaceExportVariables(rec, customExportFile); 1867 } 1868 1869 copyToDir = QString("%1/%2/").arg(baseMVDir).arg(MVDirFormat); 1870 copyToFile = QString("%1/%2.%3").arg(copyToDir) 1871 .arg(MVFileFormat).arg(extension); 1872 1873 1874 // File and Directory Definitions 1875 1876 QFile fromFile(copyFrom); 1877 QDir toDir(copyToDir); 1878 QFile toFile(copyToFile); 1879 1880 if (!toDir.exists()) 1881 { 1882 // Attempt to create path to export point. 1883 toDir.mkpath(copyToDir); 1884 toDir.mkdir(copyToDir); 1885 if (!toDir.exists()) 1886 { 1887 VERBOSE(VB_IMPORTANT, QString("Unable to create directory %1! " 1888 "Please ensure the preceding path " 1889 "exists and is writeable.").arg(copyToDir)); 1890 return; 1891 } 1892 } 1893 1894 // Perform the actual copy. 1895 1896 long long int bytesCopied = copy(toFile,fromFile); 1897 1898 if (bytesCopied != -1) 1899 { 1900 // Add File into videometadata 1901 1902 MSqlQuery query(MSqlQuery::InitCon()); 1903 1904 query.prepare("INSERT INTO videometadata (title,plot,year,category," 1905 "userrating,length,filename,showlevel,inetref, " 1906 "browse) VALUES (:TITLE, :PLOT, :YEAR, :CATEGORY, " 1907 ":USERRATING, :LENGTH, :FILENAME, :SHOWLEVEL, " 1908 ":INETREF, :BROWSE)"); 1909 1910 query.bindValue(":TITLE", MVFileFormat); 1911 query.bindValue(":PLOT", rec->description); 1912 query.bindValue(":YEAR", rec->originalAirDate.toString("yyyy")); 1913 query.bindValue(":CATEGORY", rec->category); 1914 query.bindValue(":USERRATING", exportRating); 1915 query.bindValue(":LENGTH", rec->lenMins); 1916 query.bindValue(":FILENAME", copyToFile); 1917 query.bindValue(":SHOWLEVEL", 1); 1918 query.bindValue(":INETREF", 0); 1919 query.bindValue(":BROWSE", 1); 1920 1921 if (!query.exec() || !query.isActive()) 1922 { 1923 MythDB::DBError("video metadata update", query); 1924 return; 1925 } 1926 1927 // Move recordedmarkup for file into videometadata 1928 1929 MSqlQuery markup(MSqlQuery::InitCon()); 1930 1931 markup.prepare("INSERT INTO filemarkup (filename,mark,offset,type) " 1932 "SELECT :FILENAME, mark, data, type from " 1933 "recordedmarkup where chanid=:CHANID and starttime=:STARTTIME"); 1934 1935 markup.bindValue(":FILENAME", copyToFile); 1936 markup.bindValue(":CHANID", rec->chanid); 1937 markup.bindValue(":STARTTIME", rec->recstartts); 1938 1939 if (!markup.exec() || !markup.isActive()) 1940 { 1941 MythDB::DBError("video metadata update", markup); 1942 return; 1943 } 1944 1945 // Copy and set preview image as screenshot 1946 // If Banners, cover files, or fanart exist with 1947 // seriesID as the name, use them automatically. 1948 1949 QString screenshotFile = getPreviewImage(rec); 1950 QString MVScreenshotDir = gContext->GetSetting("VideoScreenshotDir"); 1951 QString MVScreenshotFile = QString("%1/%2.png").arg(MVScreenshotDir).arg(MVFileFormat); 1952 1953 QString MVBannerDir = gContext->GetSetting("VideoBannerDir"); 1954 QString bannerFile = testImageFiles(MVBannerDir, rec->seriesid); 1955 if (!bannerFile.isNull()) 1956 VERBOSE(VB_IMPORTANT, QString("Found Banner File Match: %1").arg(bannerFile)); 1957 1958 QString MVFanartDir = gContext->GetSetting("VideoFanartDir"); 1959 QString fanartFile = testImageFiles(MVFanartDir, rec->seriesid); 1960 if (!fanartFile.isNull()) 1961 VERBOSE(VB_IMPORTANT, QString("Found Fanart File Match: %1").arg(fanartFile)); 1962 1963 QString MVCoverDir = gContext->GetSetting("VideoArtworkDir"); 1964 QString coverFile = testImageFiles(MVCoverDir, rec->seriesid); 1965 if (!coverFile.isNull()) 1966 VERBOSE(VB_IMPORTANT, QString("Found Cover File Match: %1").arg(coverFile)); 1967 1968 VERBOSE(VB_IMPORTANT, QString("Copying %1 to %2").arg(screenshotFile).arg(MVScreenshotFile)); 1969 1970 QFile fromScreenshot(screenshotFile); 1971 QFile toScreenshot(MVScreenshotFile); 1972 1973 long long int screenshotBytesCopied = copy(toScreenshot,fromScreenshot); 1974 1975 if (screenshotBytesCopied != -1 || !bannerFile.isNull() || !fanartFile.isNull() || 1976 !coverFile.isNull()) 1977 { 1978 MSqlQuery images(MSqlQuery::InitCon()); 1979 1980 images.prepare("UPDATE videometadata set screenshot=:SCREENSHOTFILE, " 1981 "banner=:BANNERFILE, fanart=:FANARTFILE, coverfile=:COVERFILE " 1982 "where filename=:FILENAME"); 1983 1984 images.bindValue(":SCREENSHOTFILE", MVScreenshotFile); 1985 images.bindValue(":BANNERFILE", bannerFile); 1986 images.bindValue(":FANARTFILE", fanartFile); 1987 images.bindValue(":COVERFILE", coverFile); 1988 images.bindValue(":FILENAME", copyToFile); 1989 1990 if (!images.exec() || !images.isActive()) 1991 { 1992 MythDB::DBError("video metadata update", images); 1993 return; 1994 } 1995 } 1996 else 1997 { 1998 VERBOSE(VB_IMPORTANT, QString("Copy succeeded, but no images " 1999 "were copied of found.").arg(screenshotBytesCopied)); 2000 return; 2001 } 2002 VERBOSE(VB_IMPORTANT, QString("Copy succeeded, %1 bytes copied.").arg(bytesCopied)); 2003 } 2004 else 2005 { 2006 VERBOSE(VB_IMPORTANT, QString("Copy unsuccessful, check all permissions.")); 2007 } 2008 2009 customExportDir.clear(); 2010 customExportFile.clear(); 2011 2012 } 2013 2014 QString PlaybackBox::testImageFiles(QString &testDirectory, QString &seriesID) 2015 { 2016 QString testFilename = QString("%1/%2").arg(testDirectory).arg(seriesID); 2017 QString foundFile = NULL; 2018 2019 QStringList test_files; 2020 test_files.append(testFilename + ".png"); 2021 test_files.append(testFilename + ".jpg"); 2022 test_files.append(testFilename + ".gif"); 2023 for (QStringList::const_iterator tfp = test_files.begin(); 2024 tfp != test_files.end(); ++tfp) 2025 { 2026 if (QFile::exists(*tfp)) 2027 { 2028 foundFile = *tfp; 2029 break; 2030 } 2031 } 2032 return foundFile; 2033 } 2034 2035 QString PlaybackBox::replaceExportVariables(ProgramInfo *rec, QString &repString) 2036 { 2037 if (!repString.isEmpty()) 2038 { 2039 repString.replace(QRegExp("%FILE%"), rec->GetRecordBasename(true)); 2040 repString.replace(QRegExp("%TITLE%"), rec->title); 2041 repString.replace(QRegExp("%SUBTITLE%"), rec->subtitle); 2042 repString.replace(QRegExp("%DESCRIPTION%"), rec->description); 2043 repString.replace(QRegExp("%HOSTNAME%"), rec->hostname); 2044 repString.replace(QRegExp("%CATEGORY%"), rec->category); 2045 repString.replace(QRegExp("%RECGROUP%"), rec->recgroup); 2046 repString.replace(QRegExp("%PLAYGROUP%"), rec->playgroup); 2047 repString.replace(QRegExp("%ORIGAIRYEAR%"), 2048 rec->originalAirDate.toString("yyyy")); 2049 repString.replace(QRegExp("%ORIGAIRDATE%"), 2050 rec->originalAirDate.toString("yyyyMMdd")); 2051 repString.replace(QRegExp("%CALLSIGN%"), rec->chansign); 2052 repString.replace(QRegExp("%CHANNAME%"), rec->channame); 2053 repString.replace(QRegExp("%CHANID%"), rec->chanid); 2054 repString.replace(QRegExp("%STARTTIME%"), 2055 rec->recstartts.toString("yyyyMMddhhmmss")); 2056 repString.replace(QRegExp("%ENDTIME%"), 2057 rec->recendts.toString("yyyyMMddhhmmss")); 2058 repString.replace(QRegExp("%STARTTIMEISO%"), 2059 rec->recstartts.toString(Qt::ISODate)); 2060 repString.replace(QRegExp("%ENDTIMEISO%"), 2061 rec->recendts.toString(Qt::ISODate)); 2062 repString.replace(QRegExp("%PROGSTART%"), 2063 rec->startts.toString("yyyyMMddhhmmss")); 2064 repString.replace(QRegExp("%PROGEND%"), 2065 rec->endts.toString("yyyyMMddhhmmss")); 2066 repString.replace(QRegExp("%PROGSTARTISO%"), 2067 rec->startts.toString(Qt::ISODate)); 2068 repString.replace(QRegExp("%PROGENDISO%"), 2069 rec->endts.toString(Qt::ISODate)); 2070 } 2071 return repString; 2072 } 2073 1818 2074 bool PlaybackBox::doRemove(ProgramInfo *rec, bool forgetHistory, 1819 2075 bool forceMetadataDelete) 1820 2076 { … … 1869 2125 showActionPopup(pginfo); 1870 2126 } 1871 2127 2128 void PlaybackBox::showExportPopup(ProgramInfo *program) 2129 { 2130 if (m_popupMenu) 2131 return; 2132 2133 QString label = tr("Are you sure you want to export:"); 2134 2135 m_expItem = CurrentItem(); 2136 popupString(m_expItem, label); 2137 2138 m_popupMenu = new MythDialogBox(label, m_popupStack, "pbbmainmenupopup"); 2139 2140 connect(m_popupMenu, SIGNAL(Exiting()), SLOT(popupClosed())); 2141 2142 if (m_popupMenu->Create()) 2143 m_popupStack->AddScreen(m_popupMenu); 2144 else 2145 { 2146 delete m_popupMenu; 2147 m_popupMenu = NULL; 2148 } 2149 2150 m_popupMenu->SetReturnEvent(this, "slotmenu"); 2151 2152 m_freeSpaceNeedsUpdate = true; 2153 QString tmpmessage; 2154 const char *tmpslot = NULL; 2155 2156 if (program->IsSameProgram(*program)) 2157 { 2158 tmpmessage = tr("Yes, Export to MythVideo"); 2159 tmpslot = SLOT(doMVExport()); 2160 m_popupMenu->AddButton(tmpmessage, tmpslot); 2161 2162 tmpmessage = tr("Export with custom name/location"); 2163 tmpslot = SLOT(showCustomExportEditor()); 2164 m_popupMenu->AddButton(tmpmessage, tmpslot); 2165 2166 tmpmessage = tr("No, I don't want to Export"); 2167 tmpslot = SLOT(noExport()); 2168 m_popupMenu->AddButton(tmpmessage, tmpslot); 2169 } 2170 } 2171 2172 1872 2173 void PlaybackBox::showDeletePopup(ProgramInfo *program, deletePopupType types) 1873 2174 { 1874 2175 if (m_popupMenu) … … 2271 2572 else 2272 2573 m_popupMenu->AddButton(tr("Preserve this episode"), 2273 2574 SLOT(togglePreserveEpisode())); 2575 2576 QString MVlocation = FindPluginName("mythvideo"); 2577 if (QFile(MVlocation).exists()) 2578 m_popupMenu->AddButton(tr("Export to MythVideo"), SLOT(askMVExport())); 2274 2579 } 2275 2580 } 2276 2581 … … 2616 2921 stop(pginfo); 2617 2922 } 2618 2923 2924 void PlaybackBox::doMVExport() 2925 { 2926 ProgramInfo *pginfo = CurrentItem(); 2927 mvexport(pginfo); 2928 } 2929 2619 2930 void PlaybackBox::showProgramDetails() 2620 2931 { 2621 2932 ProgramInfo *pginfo = CurrentItem(); … … 2754 3065 } 2755 3066 } 2756 3067 3068 void PlaybackBox::askMVExport(ProgramInfo *pginfo) 3069 { 3070 if (!pginfo) 3071 pginfo = CurrentItem(); 3072 showExportPopup(pginfo); 3073 } 3074 2757 3075 void PlaybackBox::askDelete(ProgramInfo *pginfo) 2758 3076 { 2759 3077 if (!pginfo) … … 3985 4303 m_recordingList->RemoveItem(item); 3986 4304 } 3987 4305 4306 void PlaybackBox::showCustomExportEditor() 4307 { 4308 4309 MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); 4310 4311 CustomExportEdit *editExport = new CustomExportEdit(mainStack); 4312 4313 if (editExport->Create()) 4314 { 4315 connect(editExport, SIGNAL(result(const QString &, const QString &)), 4316 SLOT(startCustomExport(const QString &, const QString &))); 4317 mainStack->AddScreen(editExport); 4318 } 4319 else 4320 delete editExport; 4321 } 4322 4323 void PlaybackBox::startCustomExport(const QString &newFile, 4324 const QString &newDir) 4325 { 4326 MythUIButtonListItem *item = m_recordingList->GetItemCurrent(); 4327 4328 if (!item) 4329 return; 4330 4331 ProgramInfo *pginfo = CurrentItem(); 4332 4333 if (!pginfo) 4334 return; 4335 4336 customExportFile = newFile; 4337 customExportDir = newDir; 4338 4339 mvexport(pginfo); 4340 } 4341 3988 4342 void PlaybackBox::setRecGroup(QString newRecGroup) 3989 4343 { 3990 4344 ProgramInfo *tmpItem = CurrentItem(); … … 4355 4709 Close(); 4356 4710 } 4357 4711 4712 //////////////////////////////////////////////////////// 4713 4714 CustomExportEdit::CustomExportEdit(MythScreenStack *lparent) 4715 : MythScreenType(lparent, "customexportedit") 4716 { 4717 m_dirEdit = m_fileEdit = NULL; 4718 } 4719 4720 bool CustomExportEdit::Create() 4721 { 4722 if (!LoadWindowFromXML("recordings-ui.xml", "customexport", this)) 4723 return false; 4724 4725 m_dirEdit = dynamic_cast<MythUITextEdit*>(GetChild("dir")); 4726 m_fileEdit = dynamic_cast<MythUITextEdit*>(GetChild("file")); 4727 MythUIButton *okButton = dynamic_cast<MythUIButton*>(GetChild("ok")); 4728 4729 if (!m_dirEdit || !m_fileEdit || !okButton) 4730 { 4731 VERBOSE(VB_IMPORTANT, "Window 'customexport' is missing required " 4732 "elements."); 4733 return false; 4734 } 4735 4736 m_dirEdit->SetText(gContext->GetSetting("TVExportDirFormat")); 4737 m_fileEdit->SetText(gContext->GetSetting("TVExportFileFormat")); 4738 4739 connect(okButton, SIGNAL(Clicked()), SLOT(ReturnExport())); 4740 4741 if (!BuildFocusList()) 4742 VERBOSE(VB_IMPORTANT, "Failed to build a focuslist."); 4743 4744 return true; 4745 } 4746 4747 void CustomExportEdit::ReturnExport() 4748 { 4749 QString newExportDir = m_dirEdit->GetText(); 4750 QString newExportFile = m_fileEdit->GetText(); 4751 4752 emit result(newExportFile, newExportDir); 4753 Close(); 4754 } 4755 4358 4756 ////////////////////////////////////////// 4359 4757 4360 4758 HelpPopup::HelpPopup(MythScreenStack *lparent) -
mythtv/programs/mythfrontend/playbackbox.h
142 142 void showRecGroupChanger(); 143 143 void showPlayGroupChanger(); 144 144 void showMetadataEditor(); 145 void showCustomExportEditor(); 145 146 void showGroupFilter(); 146 147 void showRecGroupPasswordChanger(); 147 148 void showPlayFromPopup(); … … 170 171 171 172 void askStop(); 172 173 void doStop(); 174 void askMVExport(ProgramInfo *pginfo = NULL); 175 void doMVExport(); 173 176 174 177 void doEditScheduled(); 175 178 void doAllowRerecord(); … … 200 203 void setPlayGroup(QString newPlayGroup); 201 204 202 205 void saveRecMetadata(const QString &newTitle, const QString &newSubtitle); 206 void startCustomExport(const QString &newFile, const QString &newDir); 203 207 204 208 void SetRecGroupPassword(const QString &newPasswd); 205 209 … … 260 264 261 265 bool play(ProgramInfo *rec, bool inPlaylist = false); 262 266 void stop(ProgramInfo *); 267 void mvexport(ProgramInfo *); 268 QString testImageFiles(QString &testDirectory, QString &seriesID); 269 QString replaceExportVariables(ProgramInfo *rec, QString &repString); 263 270 void remove(ProgramInfo *); 264 271 void showActions(ProgramInfo *); 265 272 ProgramInfo *CurrentItem(void); … … 279 286 280 287 bool doRemove(ProgramInfo *, bool forgetHistory, bool forceMetadataDelete); 281 288 void showDeletePopup(ProgramInfo *, deletePopupType); 289 void showExportPopup(ProgramInfo *); 282 290 void showActionPopup(ProgramInfo *program); 283 291 void showFileNotFoundActionPopup(ProgramInfo *program); 284 292 void popupString(ProgramInfo *program, QString &message); … … 376 384 // Other state 377 385 /// Program currently selected for deletion 378 386 ProgramInfo *m_delItem; 387 /// Program currently selected for export 388 ProgramInfo *m_expItem; 379 389 /// Program currently selected during an update 380 390 ProgramInfo *m_currentItem; 381 391 /// Group currently selected … … 516 526 ProgramInfo *m_progInfo; 517 527 }; 518 528 529 class CustomExportEdit : public MythScreenType 530 { 531 Q_OBJECT 532 533 public: 534 CustomExportEdit(MythScreenStack *lparent); 535 536 bool Create(void); 537 538 signals: 539 void result(const QString &, const QString &); 540 541 protected slots: 542 void ReturnExport(void); 543 544 private: 545 MythUITextEdit *m_dirEdit; 546 MythUITextEdit *m_fileEdit; 547 548 }; 549 519 550 class HelpPopup : public MythScreenType 520 551 { 521 552 Q_OBJECT -
mythplugins/mythvideo/mythvideo/globalsettings.cpp
236 246 return gc; 237 247 } 238 248 249 HostLineEdit *TVExportDirectoryFormat() 250 { 251 HostLineEdit *gc = new HostLineEdit("TVExportDirFormat"); 252 gc->setLabel(QObject::tr("TV Export Directory Format")); 253 gc->setValue(DEFAULT_TVEXPORTDIRFORMAT); 254 gc->setHelpText(QObject::tr("Directory format for recording export " 255 "to MythVideo, using user job style variables. Directory " 256 "is off of base MythVideo directory. Example: " 257 "Television/%CATEGORY%/%TITLE%")); 258 return gc; 259 } 260 261 HostLineEdit *TVExportFileFormat() 262 { 263 HostLineEdit *gc = new HostLineEdit("TVExportFileFormat"); 264 gc->setLabel(QObject::tr("TV Export File Format")); 265 gc->setValue(DEFAULT_TVEXPORTFILEFORMAT); 266 gc->setHelpText(QObject::tr("File format for recording export " 267 "to MythVideo, using user job style variables. Example: " 268 "%TITLE% - %SUBTITLE% (%STARTTIMEISO%)")); 269 return gc; 270 } 271 239 272 HostLineEdit *VideoArtworkDirectory() 240 273 { 241 274 HostLineEdit *gc = new HostLineEdit("VideoArtworkDir"); … … 709 777 vman->addChild(SearchListingsCommand()); 710 778 vman->addChild(GetPostersCommand()); 711 779 vman->addChild(GetDataCommand()); 780 vman->setLabel(QObject::tr("Video Export")); 781 vman->addChild(TVExportDirectoryFormat()); 782 vman->addChild(TVExportFileFormat()); 712 783 713 784 VConfigPage page4(pages, false); 714 785 page4->addChild(vman); -
mythplugins/mythvideo/mythvideo/globals.cpp
25 28 const QString JUMP_VIDEO_TREE = "Video Listings"; 26 29 const QString JUMP_VIDEO_GALLERY = "Video Gallery"; 27 30 const QString JUMP_VIDEO_DEFAULT = "MythVideo"; 31 const QString DEFAULT_TVEXPORTDIRFORMAT = "Television/%TITLE%"; 32 const QString DEFAULT_TVEXPORTFILEFORMAT = "%TITLE% - %SUBTITLE%"; 28 33 29 34 #ifdef Q_WS_MACX 30 35 const QString DEFAULT_VIDEOSTARTUP_DIR = QDir::homePath() + "/Movies"; -
mythplugins/mythvideo/mythvideo/globals.h
25 28 extern const QString JUMP_VIDEO_DEFAULT; 26 29 27 30 extern const QString DEFAULT_VIDEOSTARTUP_DIR; 31 extern const QString DEFAULT_TVEXPORTDIRFORMAT; 32 extern const QString DEFAULT_TVEXPORTFILEFORMAT; 28 33 29 34 #endif // GLOBALS_H_