Ticket #6158: PBBMVExport.4.diff

File PBBMVExport.4.diff, 19.3 KB (added by robert.mcnamara@…, 12 years ago)

Adds custom export capability

  • mythtv/programs/mythfrontend/playbackbox.cpp

     
    2020#include "mythdirs.h"
    2121#include "mythcontext.h"
    2222#include "mythdbcon.h"
     23#include "mythdb.h"
    2324#include "mythverbose.h"
    2425#include "programinfo.h"
    2526#include "scheduledrecording.h"
     
    4243#define LOC QString("PlaybackBox: ")
    4344#define LOC_ERR QString("PlaybackBox Error: ")
    4445
     46QString customExportFile = NULL;
     47QString customExportDir = NULL;
     48
    4549#define REC_CAN_BE_DELETED(rec) \
    4650    ((((rec)->programflags & FL_INUSEPLAYING) == 0) && \
    4751     ((((rec)->programflags & FL_INUSERECORDING) == 0) || \
     
    18131817    RemoteStopRecording(rec);
    18141818}
    18151819
     1820void PlaybackBox::mvexport(ProgramInfo *rec)
     1821{
     1822
     1823    // User Rating Adjustment
     1824    QString exportRating = QString::number((int)((rec->stars * 10.0) + 0.5));
     1825
     1826    // Stuff necessary to perform the copy command
     1827
     1828    QString copyFrom = rec->GetPlaybackURL(false, true);
     1829    QString baseMVDir = gContext->GetSetting("VideoStartupDir");
     1830    QString MVFileFormat;
     1831    QString MVDirFormat;
     1832    QString copyToDir;
     1833    QString copyToFile;
     1834    QString extension;
     1835
     1836    // Check the original extension
     1837
     1838    QRegExp rx(".*\\.(\\w+)$");
     1839    int pos = rx.indexIn(copyFrom);
     1840    if (pos > -1)
     1841    {
     1842        extension = rx.cap(1);
     1843    }
     1844    else
     1845    {
     1846        extension = "";
     1847    }
     1848
     1849    // If a custom export string is used, use it
     1850
     1851    if (customExportFile.isEmpty())
     1852    {
     1853        MVDirFormat = gContext->GetSetting("TVExportDirFormat",
     1854                              "Television/%TITLE%/");
     1855        MVFileFormat = gContext->GetSetting("TVExportFileFormat",
     1856                              "%TITLE% - %SUBTITLE%");
     1857    }
     1858    else
     1859    {
     1860        MVDirFormat = customExportDir;
     1861        MVFileFormat = customExportFile;
     1862    }
     1863
     1864   // Replace Variables with actual values
     1865
     1866    if (!MVDirFormat.isEmpty())
     1867    {
     1868         MVDirFormat.replace(QRegExp("%FILE%"), rec->GetRecordBasename(true));
     1869         MVDirFormat.replace(QRegExp("%TITLE%"), rec->title);
     1870         MVDirFormat.replace(QRegExp("%SUBTITLE%"), rec->subtitle);
     1871         MVDirFormat.replace(QRegExp("%DESCRIPTION%"), rec->description);
     1872         MVDirFormat.replace(QRegExp("%HOSTNAME%"), rec->hostname);
     1873         MVDirFormat.replace(QRegExp("%CATEGORY%"), rec->category);
     1874         MVDirFormat.replace(QRegExp("%RECGROUP%"), rec->recgroup);
     1875         MVDirFormat.replace(QRegExp("%PLAYGROUP%"), rec->playgroup);
     1876         MVDirFormat.replace(QRegExp("%CHANID%"), rec->chanid);
     1877         MVDirFormat.replace(QRegExp("%STARTTIME%"),
     1878                         rec->recstartts.toString("yyyyMMddhhmmss"));
     1879         MVDirFormat.replace(QRegExp("%ENDTIME%"),
     1880                         rec->recendts.toString("yyyyMMddhhmmss"));
     1881         MVDirFormat.replace(QRegExp("%STARTTIMEISO%"),
     1882                         rec->recstartts.toString(Qt::ISODate));
     1883         MVDirFormat.replace(QRegExp("%ENDTIMEISO%"),
     1884                         rec->recendts.toString(Qt::ISODate));
     1885         MVDirFormat.replace(QRegExp("%PROGSTART%"),
     1886                         rec->startts.toString("yyyyMMddhhmmss"));
     1887         MVDirFormat.replace(QRegExp("%PROGEND%"),
     1888                         rec->endts.toString("yyyyMMddhhmmss"));
     1889         MVDirFormat.replace(QRegExp("%PROGSTARTISO%"),
     1890                         rec->startts.toString(Qt::ISODate));
     1891         MVDirFormat.replace(QRegExp("%PROGENDISO%"),
     1892                         rec->endts.toString(Qt::ISODate));
     1893    }
     1894    if (!MVFileFormat.isEmpty())
     1895    {
     1896         MVFileFormat.replace(QRegExp("%FILE%"), rec->GetRecordBasename(true));
     1897         MVFileFormat.replace(QRegExp("%TITLE%"), rec->title);
     1898         MVFileFormat.replace(QRegExp("%SUBTITLE%"), rec->subtitle);
     1899         MVFileFormat.replace(QRegExp("%DESCRIPTION%"), rec->description);
     1900         MVFileFormat.replace(QRegExp("%HOSTNAME%"), rec->hostname);
     1901         MVFileFormat.replace(QRegExp("%CATEGORY%"), rec->category);
     1902         MVFileFormat.replace(QRegExp("%RECGROUP%"), rec->recgroup);
     1903         MVFileFormat.replace(QRegExp("%PLAYGROUP%"), rec->playgroup);
     1904         MVFileFormat.replace(QRegExp("%CHANID%"), rec->chanid);
     1905         MVFileFormat.replace(QRegExp("%STARTTIME%"),
     1906                         rec->recstartts.toString("yyyyMMddhhmmss"));
     1907         MVFileFormat.replace(QRegExp("%ENDTIME%"),
     1908                         rec->recendts.toString("yyyyMMddhhmmss"));
     1909         MVFileFormat.replace(QRegExp("%STARTTIMEISO%"),
     1910                         rec->recstartts.toString(Qt::ISODate));
     1911         MVFileFormat.replace(QRegExp("%ENDTIMEISO%"),
     1912                         rec->recendts.toString(Qt::ISODate));
     1913         MVFileFormat.replace(QRegExp("%PROGSTART%"),
     1914                         rec->startts.toString("yyyyMMddhhmmss"));
     1915         MVFileFormat.replace(QRegExp("%PROGEND%"),
     1916                         rec->endts.toString("yyyyMMddhhmmss"));
     1917         MVFileFormat.replace(QRegExp("%PROGSTARTISO%"),
     1918                         rec->startts.toString(Qt::ISODate));
     1919         MVFileFormat.replace(QRegExp("%PROGENDISO%"),
     1920                         rec->endts.toString(Qt::ISODate));
     1921    }
     1922
     1923    copyToDir = QString("%1/%2/").arg(baseMVDir).arg(MVDirFormat);
     1924    copyToFile = QString("%1/%2.%3").arg(copyToDir)
     1925                         .arg(MVFileFormat).arg(extension);
     1926
     1927
     1928    // File and Directory Definitions
     1929
     1930    QFile fromFile(copyFrom);
     1931    QDir toDir(copyToDir);
     1932    QFile toFile(copyToFile);
     1933
     1934    if (!toDir.exists())
     1935    {
     1936        // Attempt to create path to export point.
     1937        toDir.mkpath(copyToDir);
     1938        toDir.mkdir(copyToDir);
     1939        if (!toDir.exists())
     1940        {
     1941            VERBOSE(VB_IMPORTANT, QString("Unable to create directory %1! "
     1942                                          "Please ensure the preceding path "
     1943                                          "exists and is writeable.").arg(copyToDir));   
     1944            return;
     1945        }
     1946    }
     1947
     1948    long long int bytesCopied = copy(toFile,fromFile);
     1949
     1950    if (bytesCopied != -1)
     1951    {
     1952        // Add File into videometadata
     1953
     1954        MSqlQuery query(MSqlQuery::InitCon());
     1955
     1956        query.prepare("INSERT INTO videometadata (title,plot,year,category,"
     1957                          "userrating,length,filename,showlevel,inetref, "
     1958                          "browse) VALUES (:TITLE, :PLOT, :YEAR, :CATEGORY, "
     1959                          ":USERRATING, :LENGTH, :FILENAME, :SHOWLEVEL, "
     1960                          ":INETREF, :BROWSE)");
     1961
     1962        query.bindValue(":TITLE", MVFileFormat);
     1963        query.bindValue(":PLOT", rec->description);
     1964        query.bindValue(":YEAR", rec->originalAirDate.toString("yyyy"));
     1965        query.bindValue(":CATEGORY", rec->category);
     1966        query.bindValue(":USERRATING", exportRating);
     1967        query.bindValue(":LENGTH", rec->lenMins);
     1968        query.bindValue(":FILENAME", copyToFile);
     1969        query.bindValue(":SHOWLEVEL", 1);
     1970        query.bindValue(":INETREF", 0);
     1971        query.bindValue(":BROWSE", 1);
     1972
     1973        if (!query.exec() || !query.isActive())
     1974        {
     1975            MythDB::DBError("video metadata update", query);
     1976            return;
     1977        }
     1978
     1979        // Move recordedmarkup for file into videometadata
     1980
     1981        MSqlQuery markup(MSqlQuery::InitCon());
     1982
     1983        markup.prepare("INSERT INTO filemarkup (filename,mark,offset,type) "
     1984                      "SELECT :FILENAME, mark, data, type from "
     1985                      "recordedmarkup where chanid=:CHANID and starttime=:STARTTIME");
     1986
     1987        markup.bindValue(":FILENAME", copyToFile);
     1988        markup.bindValue(":CHANID", rec->chanid);
     1989        markup.bindValue(":STARTTIME", rec->recstartts);
     1990
     1991        if (!markup.exec() || !markup.isActive())
     1992        {
     1993            MythDB::DBError("video metadata update", markup);
     1994            return;
     1995        }
     1996
     1997        // Copy and set preview image as coverfile
     1998
     1999        QString imagefile = NULL;
     2000        imagefile = getPreviewImage(rec);
     2001        QString MVScreenshotDir = gContext->GetSetting("VideoScreenshotDir");
     2002        QString MVimagefile = QString("%1/%2.png").arg(MVScreenshotDir).arg(MVFileFormat);
     2003
     2004        VERBOSE(VB_IMPORTANT, QString("Copying %1 to %2").arg(imagefile).arg(MVimagefile));
     2005
     2006        QFile fromPoster(imagefile);
     2007        QFile toPoster(MVimagefile);
     2008
     2009        long long int posterBytesCopied = copy(toPoster,fromPoster);
     2010
     2011        if (posterBytesCopied != -1)
     2012        {
     2013            MSqlQuery poster(MSqlQuery::InitCon());
     2014
     2015            poster.prepare("UPDATE videometadata set screenshot=:COVERFILE "
     2016                              "where filename=:FILENAME");
     2017
     2018            poster.bindValue(":COVERFILE", MVimagefile);
     2019            poster.bindValue(":FILENAME", copyToFile);
     2020
     2021            if (!poster.exec() || !poster.isActive())
     2022            {
     2023                MythDB::DBError("video metadata update", poster);
     2024                 return;
     2025            }
     2026        }
     2027        else
     2028        {
     2029            VERBOSE(VB_IMPORTANT, QString("Copy succeeded, but image copy failed.").arg(posterBytesCopied));
     2030            return;
     2031        }
     2032        VERBOSE(VB_IMPORTANT, QString("Copy succeeded, %1 bytes copied.").arg(bytesCopied));
     2033    }
     2034    else
     2035    {
     2036        VERBOSE(VB_IMPORTANT, QString("Copy unsuccessful, check all permissions."));
     2037    }
     2038
     2039customExportDir.clear();
     2040customExportFile.clear();
     2041
     2042}
     2043
    18162044bool PlaybackBox::doRemove(ProgramInfo *rec, bool forgetHistory,
    18172045                           bool forceMetadataDelete)
    18182046{
     
    18672095        showActionPopup(pginfo);
    18682096}
    18692097
     2098void PlaybackBox::showExportPopup(ProgramInfo *program)
     2099{
     2100    if (m_popupMenu)
     2101        return;
     2102
     2103    QString label = tr("Are you sure you want to export:");
     2104
     2105    m_expItem = CurrentItem();
     2106    popupString(m_expItem, label);
     2107
     2108    m_popupMenu = new MythDialogBox(label, m_popupStack, "pbbmainmenupopup");
     2109
     2110    connect(m_popupMenu, SIGNAL(Exiting()), SLOT(popupClosed()));
     2111
     2112    if (m_popupMenu->Create())
     2113        m_popupStack->AddScreen(m_popupMenu);
     2114    else
     2115    {
     2116        delete m_popupMenu;
     2117        m_popupMenu = NULL;
     2118    }
     2119
     2120    m_popupMenu->SetReturnEvent(this, "slotmenu");
     2121
     2122    m_freeSpaceNeedsUpdate = true;
     2123    QString tmpmessage;
     2124    const char *tmpslot = NULL;
     2125
     2126    if (program->IsSameProgram(*program))
     2127        {
     2128        tmpmessage = tr("Yes, Export to MythVideo");
     2129        tmpslot = SLOT(doMVExport());
     2130        m_popupMenu->AddButton(tmpmessage, tmpslot);
     2131
     2132        tmpmessage = tr("Export with custom name/location");
     2133        tmpslot = SLOT(showCustomExportEditor());
     2134        m_popupMenu->AddButton(tmpmessage, tmpslot);
     2135
     2136        tmpmessage = tr("No, I don't want to Export");
     2137        tmpslot = SLOT(noExport());
     2138        m_popupMenu->AddButton(tmpmessage, tmpslot);
     2139        }
     2140}
     2141
     2142
    18702143void PlaybackBox::showDeletePopup(ProgramInfo *program, deletePopupType types)
    18712144{
    18722145    if (m_popupMenu)
     
    25182791                           true);
    25192792    m_popupMenu->AddButton(tr("Job Options"), SLOT(showJobPopup()), true);
    25202793
     2794    QString MVlocation = FindPluginName("mythvideo");
     2795    if (QFile(MVlocation).exists())
     2796        m_popupMenu->AddButton(tr("Export to MythVideo"), SLOT(askMVExport()));
     2797
    25212798    if (!(m_player && m_player->IsSameProgram(0, pginfo)))
    25222799    {
    25232800        if (pginfo->recgroup == "Deleted")
     
    26142891    stop(pginfo);
    26152892}
    26162893
     2894void PlaybackBox::doMVExport()
     2895{
     2896    ProgramInfo *pginfo = CurrentItem();
     2897    mvexport(pginfo);
     2898}
     2899
    26172900void PlaybackBox::showProgramDetails()
    26182901{
    26192902   ProgramInfo *pginfo = CurrentItem();
     
    27523035    }
    27533036}
    27543037
     3038void PlaybackBox::askMVExport(ProgramInfo *pginfo)
     3039{
     3040    if (!pginfo)
     3041        pginfo = CurrentItem();
     3042    showExportPopup(pginfo);
     3043}
     3044
    27553045void PlaybackBox::askDelete(ProgramInfo *pginfo)
    27563046{
    27573047    if (!pginfo)
     
    39834273        m_recordingList->RemoveItem(item);
    39844274}
    39854275
     4276void PlaybackBox::showCustomExportEditor()
     4277{
     4278
     4279    MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
     4280
     4281    CustomExportEdit *editExport = new CustomExportEdit(mainStack);
     4282
     4283    if (editExport->Create())
     4284    {
     4285        connect(editExport, SIGNAL(result(const QString &, const QString &)),
     4286                SLOT(startCustomExport(const QString &, const QString &)));
     4287        mainStack->AddScreen(editExport);
     4288    }
     4289    else
     4290        delete editExport;
     4291}
     4292
     4293void PlaybackBox::startCustomExport(const QString &newFile,
     4294                                    const QString &newDir)
     4295{
     4296    MythUIButtonListItem *item = m_recordingList->GetItemCurrent();
     4297
     4298    if (!item)
     4299        return;
     4300
     4301    ProgramInfo *pginfo = CurrentItem();
     4302
     4303    if (!pginfo)
     4304        return;
     4305
     4306    customExportFile = newFile;
     4307    customExportDir = newDir;
     4308
     4309    mvexport(pginfo);
     4310}
     4311
    39864312void PlaybackBox::setRecGroup(QString newRecGroup)
    39874313{
    39884314    ProgramInfo *tmpItem = CurrentItem();
     
    43534679    Close();
    43544680}
    43554681
     4682////////////////////////////////////////////////////////
     4683
     4684CustomExportEdit::CustomExportEdit(MythScreenStack *lparent)
     4685                : MythScreenType(lparent, "customexportedit")
     4686{
     4687    m_dirEdit = m_fileEdit = NULL;
     4688}
     4689
     4690bool CustomExportEdit::Create()
     4691{
     4692    if (!LoadWindowFromXML("recordings-ui.xml", "customexport", this))
     4693        return false;
     4694       
     4695    m_dirEdit = dynamic_cast<MythUITextEdit*>(GetChild("dir"));
     4696    m_fileEdit = dynamic_cast<MythUITextEdit*>(GetChild("file"));
     4697    MythUIButton *okButton = dynamic_cast<MythUIButton*>(GetChild("ok"));
     4698 
     4699    if (!m_dirEdit || !m_fileEdit || !okButton)
     4700    {
     4701        VERBOSE(VB_IMPORTANT, "Window 'customexport' is missing required "
     4702                              "elements.");
     4703        return false;
     4704    }
     4705   
     4706    m_dirEdit->SetText(gContext->GetSetting("TVExportDirFormat"));
     4707    m_fileEdit->SetText(gContext->GetSetting("TVExportFileFormat"));
     4708
     4709    connect(okButton, SIGNAL(Clicked()), SLOT(ReturnExport()));
     4710     
     4711    if (!BuildFocusList())
     4712        VERBOSE(VB_IMPORTANT, "Failed to build a focuslist.");
     4713 
     4714    return true;
     4715}
     4716
     4717void CustomExportEdit::ReturnExport()
     4718{
     4719    QString newExportDir = m_dirEdit->GetText();
     4720    QString newExportFile = m_fileEdit->GetText();
     4721
     4722    emit result(newExportFile, newExportDir);
     4723    Close();
     4724}
     4725
    43564726//////////////////////////////////////////
    43574727
    43584728HelpPopup::HelpPopup(MythScreenStack *lparent)
  • mythtv/programs/mythfrontend/playbackbox.h

     
    142142    void showRecGroupChanger();
    143143    void showPlayGroupChanger();
    144144    void showMetadataEditor();
     145    void showCustomExportEditor();
    145146    void showGroupFilter();
    146147    void showRecGroupPasswordChanger();
    147148    void showPlayFromPopup();
     
    170171
    171172    void askStop();
    172173    void doStop();
     174    void askMVExport(ProgramInfo *pginfo = NULL);
     175    void doMVExport();
    173176
    174177    void doEditScheduled();
    175178    void doAllowRerecord();
     
    200203    void setPlayGroup(QString newPlayGroup);
    201204
    202205    void saveRecMetadata(const QString &newTitle, const QString &newSubtitle);
     206    void startCustomExport(const QString &newFile, const QString &newDir);
    203207
    204208    void SetRecGroupPassword(const QString &newPasswd);
    205209
     
    260264
    261265    bool play(ProgramInfo *rec, bool inPlaylist = false);
    262266    void stop(ProgramInfo *);
     267    void mvexport(ProgramInfo *);
    263268    void remove(ProgramInfo *);
    264269    void showActions(ProgramInfo *);
    265270    ProgramInfo *CurrentItem(void);
     
    279284
    280285    bool doRemove(ProgramInfo *, bool forgetHistory, bool forceMetadataDelete);
    281286    void showDeletePopup(ProgramInfo *, deletePopupType);
     287    void showExportPopup(ProgramInfo *);
    282288    void showActionPopup(ProgramInfo *program);
    283289    void showFileNotFoundActionPopup(ProgramInfo *program);
    284290    void popupString(ProgramInfo *program, QString &message);
     
    376382    // Other state
    377383    /// Program currently selected for deletion
    378384    ProgramInfo *m_delItem;
     385    /// Program currently selected for export
     386    ProgramInfo *m_expItem;
    379387    /// Program currently selected during an update
    380388    ProgramInfo *m_currentItem;
    381389    /// Group currently selected
     
    516524    ProgramInfo *m_progInfo;
    517525};
    518526
     527class CustomExportEdit : public MythScreenType
     528{
     529    Q_OBJECT
     530
     531  public:
     532    CustomExportEdit(MythScreenStack *lparent);
     533
     534    bool Create(void);
     535
     536  signals:
     537    void result(const QString &, const QString &);
     538
     539  protected slots:   
     540    void ReturnExport(void);
     541 
     542  private:
     543    MythUITextEdit     *m_dirEdit;
     544    MythUITextEdit     *m_fileEdit;
     545   
     546};
     547
    519548class HelpPopup : public MythScreenType
    520549{
    521550    Q_OBJECT
  • mythplugins/mythvideo/mythvideo/globalsettings.cpp

     
    236246    return gc;
    237247}
    238248
     249HostLineEdit *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
     261HostLineEdit *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
    239272HostLineEdit *VideoArtworkDirectory()
    240273{
    241274    HostLineEdit *gc = new HostLineEdit("VideoArtworkDir");
     
    683748    page1->addChild(VideoStartupDirectory());
    684749    page1->addChild(VideoArtworkDirectory());
    685750    page1->addChild(VideoDefaultView());
     751    page1->addChild(TVExportDirectoryFormat()); 
     752    page1->addChild(TVExportFileFormat()); 
    686753
    687754    VConfigPage page2(pages, false);
    688755    page2->addChild(VideoListUnknownFiletypes());
  • mythplugins/mythvideo/mythvideo/globals.cpp

     
    2528const QString JUMP_VIDEO_TREE = "Video Listings";
    2629const QString JUMP_VIDEO_GALLERY = "Video Gallery";
    2730const QString JUMP_VIDEO_DEFAULT = "MythVideo";
     31const QString DEFAULT_TVEXPORTDIRFORMAT = "Television/%TITLE%";
     32const QString DEFAULT_TVEXPORTFILEFORMAT = "%TITLE% - %SUBTITLE%";
    2833
    2934#ifdef Q_WS_MACX
    3035const QString DEFAULT_VIDEOSTARTUP_DIR = QDir::homePath() + "/Movies";
  • mythplugins/mythvideo/mythvideo/globals.h

     
    2528extern const QString JUMP_VIDEO_DEFAULT;
    2629
    2730extern const QString DEFAULT_VIDEOSTARTUP_DIR;
     31extern const QString DEFAULT_TVEXPORTDIRFORMAT;
     32extern const QString DEFAULT_TVEXPORTFILEFORMAT;
    2833
    2934#endif // GLOBALS_H_