[mythtv] [PATCH] Watch Recordings and MaxEpisodes refinements

Kevin Kuphal kuphal at dls.net
Sun Nov 28 16:40:04 UTC 2004


This patch includes the following changes and replaces my previous patch:

* Modifies max episode expiration to work off recordid instead of title 
to avoid two schedules for the same title with different max episode 
settings from expiring each other.  I reverted my query changes as they 
had an undesired effect of not allowing more than one episode to be 
expired at a time.  Instead I simply enhanced the existing queries to 
support this fix.

* Add support for preserving an episode which excludes it from 
considering for max episode expiration.  This does not change any 
auto-expiring behavior as it is not intended to be a "permanent delete 
protection" option as that is something else entirely.

* Added Play from Beginning support on Watch Recordings to bypass bookmarks

* Reorganizes Watch Recordings INFO menu into categories to fit all the 
new buttons
- Play now will offer two sub choices when a bookmark is present for 
Play from Beginning and Play from Bookmark.   If no bookmark is 
present,  the existing Play button is presented.
- If an recording uses max episodes, a storage option button is 
presented with choices for toggling preserving the episode and 
auto-expiration.  If not, the auto-expiration button is presented on the 
main menu.
- A recording options button now presents the Change Recording Group and 
Edit Recording Schedule buttons
- A job options button now presents the Transcoding and Commercial 
Detection buttons
- The delete button remains on the main menu

Thanks,
Kevin

-------------- next part --------------
Index: mythtv/libs/libmythtv/dbcheck.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/dbcheck.cpp,v
retrieving revision 1.67
diff -n -u -r1.67 dbcheck.cpp
--- mythtv/libs/libmythtv/dbcheck.cpp	13 Oct 2004 01:49:55 -0000	1.67
+++ mythtv/libs/libmythtv/dbcheck.cpp	28 Nov 2004 16:27:26 -0000
@@ -8,7 +8,7 @@
 
 #include "mythcontext.h"
 
-const QString currentDatabaseVersion = "1057";
+const QString currentDatabaseVersion = "1058";
 
 void UpdateDBVersionNumber(const QString &newnumber)
 {
@@ -1051,6 +1051,14 @@
 };
         performActualUpdate(updates, "1058", dbver);
     }
+    if (dbver == "1058")
+    {
+        const QString updates[] = {
+"ALTER TABLE recorded ADD COLUMN preserve TINYINT(1) NOT NULL DEFAULT 0;",
+""
+};
+        performActualUpdate(updates, "1059", dbver);
+    }
 }
 
 void InitializeDatabase(void)
Index: mythtv/libs/libmythtv/programinfo.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/programinfo.cpp,v
retrieving revision 1.165
diff -n -u -r1.165 programinfo.cpp
--- mythtv/libs/libmythtv/programinfo.cpp	20 Oct 2004 07:25:37 -0000	1.165
+++ mythtv/libs/libmythtv/programinfo.cpp	28 Nov 2004 16:27:27 -0000
@@ -66,6 +66,7 @@
 
     seriesid = "";
     programid = "";
+    ignoreBookmark = false;
 
     record = NULL;
 }   
@@ -141,9 +142,10 @@
 
     originalAirDate = other.originalAirDate;
     stars = other.stars;
+    ignoreBookmark = other.ignoreBookmark;
     
     record = NULL;
-
+  
     return *this;
 }
 
@@ -1084,6 +1086,9 @@
 
     long long pos = 0;
 
+    if (ignoreBookmark)
+        return pos;
+
     QString starts = recstartts.toString("yyyyMMddhhmm");
     starts += "00";
 
@@ -1210,6 +1215,22 @@
     return result;
 }
 
+void ProgramInfo::SetPreserveEpisode(bool preserveEpisode, QSqlDatabase *db)
+{
+    MythContext::KickDatabase(db);
+
+    QString starts = recstartts.toString("yyyyMMddhhmm");
+    starts += "00";
+
+    QString querystr = QString("UPDATE recorded SET preserve = %1 "
+                               "WHERE chanid = '%2' AND "
+                               "starttime = '%3';").arg(preserveEpisode)
+                                                   .arg(chanid).arg(starts);
+    QSqlQuery query = db->exec(querystr);
+    if (!query.isActive())
+        MythContext::DBError("PreserveEpisode update", querystr);
+}
+
 void ProgramInfo::SetAutoExpire(bool autoExpire, QSqlDatabase *db)
 {
     MythContext::KickDatabase(db);
@@ -1249,6 +1270,49 @@
     return(result);
 }
 
+bool ProgramInfo::GetPreserveEpisodeFromRecorded(QSqlDatabase *db)
+{
+    MythContext::KickDatabase(db);
+
+    QString starts = recstartts.toString("yyyyMMddhhmm");
+    starts += "00";
+
+    QString querystr = QString("SELECT preserve FROM recorded WHERE "
+                               "chanid = '%1' AND starttime = '%2';")
+                              .arg(chanid).arg(starts);
+
+    bool result = false;
+    QSqlQuery query = db->exec(querystr);
+    if (query.isActive() && query.numRowsAffected() > 0)
+    {
+        query.next();
+
+        result = query.value(0).toInt();
+    }
+
+    return(result);
+}
+
+bool ProgramInfo::UsesMaxEpisodes(QSqlDatabase *db)
+{
+    MythContext::KickDatabase(db);
+
+    QString querystr = QString("SELECT maxepisodes FROM record WHERE "
+                               "recordid = %1;")
+                              .arg(recordid);
+
+    bool result = false;
+    QSqlQuery query = db->exec(querystr);
+    if (query.isActive() && query.numRowsAffected() > 0)
+    {
+        query.next();
+
+        result = query.value(0).toInt();
+    }
+
+    return(result);
+}
+
 void ProgramInfo::GetCutList(QMap<long long, int> &delMap, QSqlDatabase *db)
 {
 //    GetMarkupMap(delMap, db, MARK_CUT_START);
Index: mythtv/libs/libmythtv/programinfo.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/programinfo.h,v
retrieving revision 1.89
diff -n -u -r1.89 programinfo.h
--- mythtv/libs/libmythtv/programinfo.h	8 Oct 2004 04:23:36 -0000	1.89
+++ mythtv/libs/libmythtv/programinfo.h	28 Nov 2004 16:27:27 -0000
@@ -155,7 +155,11 @@
     void SetCommFlagged(int flag, QSqlDatabase *db);
     bool IsCommProcessing(QSqlDatabase *db);
     void SetAutoExpire(bool autoExpire, QSqlDatabase *db);
+    void SetPreserveEpisode(bool preserveEpisode, QSqlDatabase *db);
     bool GetAutoExpireFromRecorded(QSqlDatabase *db);
+    bool GetPreserveEpisodeFromRecorded(QSqlDatabase *db);
+
+    bool UsesMaxEpisodes(QSqlDatabase *db);
 
     int GetAutoRunJobs(QSqlDatabase *db);
 
@@ -188,6 +192,7 @@
                              QSqlDatabase *db);
 
     void DeleteHistory(QSqlDatabase *db);
+    void setIgnoreBookmark(bool ignore) { ignoreBookmark = ignore; }
     QString RecTypeChar(void);
     QString RecTypeText(void);
     QString RecStatusChar(void);
@@ -276,8 +281,8 @@
     QString seriesid;
     QString programid;
 
-
 private:
+    bool ignoreBookmark;
     void handleRecording(QSqlDatabase *db);
     void handleNotRecording(QSqlDatabase *db);
 
Index: mythtv/programs/mythbackend/autoexpire.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythbackend/autoexpire.cpp,v
retrieving revision 1.16
diff -n -u -r1.16 autoexpire.cpp
--- mythtv/programs/mythbackend/autoexpire.cpp	5 Oct 2004 02:51:46 -0000	1.16
+++ mythtv/programs/mythbackend/autoexpire.cpp	28 Nov 2004 16:27:27 -0000
@@ -142,32 +142,34 @@
     QMap<QString, int>::Iterator maxIter;
 
     QString fileprefix = gContext->GetFilePrefix();
-    QString querystr = "SELECT title, maxepisodes "
+    QString querystr = "SELECT recordid, maxepisodes, title "
                        "FROM record WHERE maxepisodes > 0 "
-                       "ORDER BY title ASC, maxepisodes DESC";
+                       "ORDER BY recordid ASC, maxepisodes DESC";
 
     QSqlQuery query = db->exec(querystr);
 
     if (query.isActive() && query.numRowsAffected() > 0)
     {
+        VERBOSE(VB_GENERAL, QString("Found %1 record profiles using max episode expiration")
+                                    .arg(query.numRowsAffected()));
         while (query.next()) {
+            VERBOSE(VB_GENERAL, QString(" - %1").arg(query.value(2).toString()));
             maxEpisodes[query.value(0).toString()] = query.value(1).toInt();
         }
     }
 
     for(maxIter = maxEpisodes.begin(); maxIter != maxEpisodes.end(); maxIter++)
     {
-        QString sqltitle(maxIter.key());
-        sqltitle.replace(QRegExp("\'"), "\\'");
-        sqltitle.replace(QRegExp("\""), "\\\"");
-
-        querystr = QString( "SELECT chanid, starttime FROM recorded "
-                            "WHERE title = \"%1\" "
+        querystr = QString( "SELECT chanid, starttime, title FROM recorded "
+                            "WHERE recordid = %1 AND preserve = 0 "
                             "ORDER BY starttime DESC;")
-                            .arg(sqltitle);
+                            .arg(maxIter.key());
 
         query = db->exec(querystr);
 
+        VERBOSE(VB_GENERAL, QString("Found %1 episodes in recording profile %2 using max expiration")
+                                    .arg(query.numRowsAffected())
+                                    .arg(maxIter.key()));
         if (query.isActive() && query.numRowsAffected() > 0)
         {
             int found = 0;
@@ -178,7 +180,7 @@
                 {
                     QString msg = QString("Expiring \"%1\" from %2, "
                                           "too many episodes.")
-                                          .arg(maxIter.key())
+                                          .arg(query.value(2).toString())
                                           .arg(query.value(1).toString());
                     VERBOSE(VB_GENERAL, msg);
                     gContext->LogEntry("autoexpire", LP_NOTICE, "Expired program", msg);
Index: mythtv/programs/mythfrontend/playbackbox.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythfrontend/playbackbox.cpp,v
retrieving revision 1.174
diff -n -u -r1.174 playbackbox.cpp
--- mythtv/programs/mythfrontend/playbackbox.cpp	15 Oct 2004 03:06:40 -0000	1.174
+++ mythtv/programs/mythfrontend/playbackbox.cpp	28 Nov 2004 16:27:28 -0000
@@ -1589,43 +1589,120 @@
     expectingPopup = true;
 }
 
-void PlaybackBox::showActionPopup(ProgramInfo *program)
+void PlaybackBox::showPlayFromPopup()
 {
+    if (expectingPopup)
+        cancelPopup();
+
     backup.begin(this);
     grayOut(&backup);
     backup.end();
 
     popup = new MythPopupBox(gContext->GetMainWindow(), graphicPopup,
                              popupForeground, popupBackground,
-                             popupHighlight, "action popup");
+                             popupHighlight, "playfrom popup");
 
-    initPopup(popup, program, "", "");
+    initPopup(popup, delitem, "", "");
 
-    QSqlDatabase *db = QSqlDatabase::database();
+    QButton *playButton = popup->addButton(tr("Play from beginning"), this, SLOT(doPlayFromBeg()));
+    popup->addButton(tr("Play from bookmark"), this, SLOT(doPlay()));
+    
+    popup->ShowPopup(this, SLOT(doCancel()));
+    playButton->setFocus();
+    
+    expectingPopup = true;
+}
+
+void PlaybackBox::showStoragePopup()
+{
+    if (expectingPopup)
+        cancelPopup();
 
-    QButton *playButton = popup->addButton(tr("Play"), this, SLOT(doPlay()));
+    backup.begin(this);
+    grayOut(&backup);
+    backup.end();
 
+    popup = new MythPopupBox(gContext->GetMainWindow(), graphicPopup,
+                             popupForeground, popupBackground,
+                             popupHighlight, "storage popup");
 
-    if (RemoteGetRecordingStatus(program, overrectime, underrectime) > 0)
-        popup->addButton(tr("Stop Recording"), this, SLOT(askStop()));
+    initPopup(popup, delitem, "", tr("A preserved episode is ignored in calculations for deleting episodes above the limit.  Auto-expiration is used to remove eligable programs when disk space is low."));
+
+    QSqlDatabase *db = QSqlDatabase::database();
+
+    QButton *storageButton;
 
     if (delitem && delitem->GetAutoExpireFromRecorded(db))
-        popup->addButton(tr("Don't Auto Expire"), this, SLOT(noAutoExpire()));
+        storageButton = popup->addButton(tr("Don't Auto Expire"), this, SLOT(noAutoExpire()));
     else
-        popup->addButton(tr("Auto Expire"), this, SLOT(doAutoExpire()));
+        storageButton = popup->addButton(tr("Auto Expire"), this, SLOT(doAutoExpire()));
+
+    if (delitem && delitem->UsesMaxEpisodes(db))
+    {
+        if (delitem && delitem->GetPreserveEpisodeFromRecorded(db))
+            popup->addButton(tr("Do not preserve this episode"), this, SLOT(noPreserveEpisode()));
+        else
+            popup->addButton(tr("Preserve this episode"), this, SLOT(doPreserveEpisode()));
+    }
+
+    popup->ShowPopup(this, SLOT(doCancel()));
+    storageButton->setFocus();
+    
+    expectingPopup = true;
+}
+
+void PlaybackBox::showRecordingPopup()
+{
+    if (expectingPopup)
+        cancelPopup();
+
+    backup.begin(this);
+    grayOut(&backup);
+    backup.end();
+
+    popup = new MythPopupBox(gContext->GetMainWindow(), graphicPopup,
+                             popupForeground, popupBackground,
+                             popupHighlight, "recording popup");
 
-    popup->addButton(tr("Change Recording Group"), this,
+    initPopup(popup, delitem, "", "");
+
+    QButton *changeButton = popup->addButton(tr("Change Recording Group"), this,
                      SLOT(showRecGroupChanger()));
 
     popup->addButton(tr("Edit Recording Schedule"), this,
                      SLOT(doEditScheduled()));
+    
+    popup->ShowPopup(this, SLOT(doCancel()));
+    changeButton->setFocus();
+    
+    expectingPopup = true;
+}
+
+void PlaybackBox::showJobPopup()
+{
+    if (expectingPopup)
+        cancelPopup();
+
+    backup.begin(this);
+    grayOut(&backup);
+    backup.end();
+
+    popup = new MythPopupBox(gContext->GetMainWindow(), graphicPopup,
+                             popupForeground, popupBackground,
+                             popupHighlight, "job popup");
+
+    initPopup(popup, delitem, "", "");
+
+    QSqlDatabase *db = QSqlDatabase::database();
+
+    QButton *jobButton;
 
     if (JobQueue::IsJobRunning(db, JOB_TRANSCODE, curitem->chanid,
                                                   curitem->startts))
-        popup->addButton(tr("Stop Transcoding"), this,
+        jobButton = popup->addButton(tr("Stop Transcoding"), this,
                          SLOT(doBeginTranscoding()));
     else
-        popup->addButton(tr("Begin Transcoding"), this,
+        jobButton = popup->addButton(tr("Begin Transcoding"), this,
                          SLOT(doBeginTranscoding()));
 
     if (curitem->IsCommProcessing(db))
@@ -1635,6 +1712,50 @@
         popup->addButton(tr("Begin Commercial Flagging"), this,
                          SLOT(doBeginFlagging()));
 
+    popup->ShowPopup(this, SLOT(doCancel()));
+    jobButton->setFocus();
+    
+    expectingPopup = true;
+}
+
+void PlaybackBox::showActionPopup(ProgramInfo *program)
+{
+    backup.begin(this);
+    grayOut(&backup);
+    backup.end();
+
+    popup = new MythPopupBox(gContext->GetMainWindow(), graphicPopup,
+                             popupForeground, popupBackground,
+                             popupHighlight, "action popup");
+
+    initPopup(popup, program, "", "");
+
+    QSqlDatabase *db = QSqlDatabase::database();
+    QButton *playButton;
+
+    if (curitem->programflags & FL_BOOKMARK)
+        playButton = popup->addButton(tr("Play from..."), this, SLOT(showPlayFromPopup()));
+    else
+        playButton = popup->addButton(tr("Play"), this, SLOT(doPlay()));
+
+    if (RemoteGetRecordingStatus(program, overrectime, underrectime) > 0)
+        popup->addButton(tr("Stop Recording"), this, SLOT(askStop()));
+    
+    // Remove this check and the auto expire buttons if a third button is added to the StoragePopup screen
+    // Otherwise for non-max-episode schedules, the popup will only show one button
+    if (delitem && delitem->UsesMaxEpisodes(db))
+    {
+        popup->addButton(tr("Storage Options"), this, SLOT(showStoragePopup()));
+    } else {
+        if (delitem && delitem->GetAutoExpireFromRecorded(db))
+            popup->addButton(tr("Don't Auto Expire"), this, SLOT(noAutoExpire()));
+        else
+            popup->addButton(tr("Auto Expire"), this, SLOT(doAutoExpire()));
+    }
+
+    popup->addButton(tr("Recording Options"), this, SLOT(showRecordingPopup()));
+    popup->addButton(tr("Job Options"), this, SLOT(showJobPopup()));
+
     popup->addButton(tr("Delete"), this, SLOT(askDelete()));
 
     popup->ShowPopup(this, SLOT(doCancel()));
@@ -1704,6 +1825,34 @@
     play(delitem);
 }
 
+void PlaybackBox::doPlayFromBeg(void)
+{
+    delitem->setIgnoreBookmark(true);
+    doPlay();
+}
+
+void PlaybackBox::doPreserveEpisode(void)
+{
+    if (!expectingPopup)
+        return;
+
+    cancelPopup();
+
+    QSqlDatabase *db = QSqlDatabase::database();
+    delitem->SetPreserveEpisode(true, db);
+}
+
+void PlaybackBox::noPreserveEpisode(void)
+{
+    if (!expectingPopup)
+        return;
+
+    cancelPopup();
+
+    QSqlDatabase *db = QSqlDatabase::database();
+    delitem->SetPreserveEpisode(false, db);
+}
+
 void PlaybackBox::askStop(void)
 {
     if (!expectingPopup)
Index: mythtv/programs/mythfrontend/playbackbox.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythfrontend/playbackbox.h,v
retrieving revision 1.58
diff -n -u -r1.58 playbackbox.h
--- mythtv/programs/mythfrontend/playbackbox.h	17 Sep 2004 21:57:47 -0000	1.58
+++ mythtv/programs/mythfrontend/playbackbox.h	28 Nov 2004 16:27:28 -0000
@@ -53,8 +53,13 @@
     void showRecGroupChanger();
     void showRecGroupChooser();
     void showRecGroupPasswordChanger();
+    void showPlayFromPopup();
+    void showRecordingPopup();
+    void showJobPopup();
+    void showStoragePopup();
 
     void doPlay();
+    void doPlayFromBeg();
 
     void askStop();
     void doStop();
@@ -69,6 +74,8 @@
 
     void doAutoExpire();
     void noAutoExpire();
+    void doPreserveEpisode();
+    void noPreserveEpisode();
 
     void doCancel();
 


More information about the mythtv-dev mailing list