Index: scheduler.cpp
===================================================================
--- scheduler.cpp	(revision 18801)
+++ scheduler.cpp	(working copy)
@@ -4,6 +4,7 @@
 #include <qregexp.h>
 #include <qstring.h>
 #include <qdatetime.h>
+#include <qfile.h>
 
 #include <iostream>
 #include <algorithm>
@@ -3514,9 +3515,11 @@
 
     // This code could probably be expanded to check the actual bitrate the
     // recording will record at for analog broadcasts that are encoded locally.
+    // maxSizeKB is 1/3 larger than required as this is what the auto expire
+    // uses
     EncoderLink *nexttv = (*m_tvList)[pginfo->cardid];
     long long maxByterate = nexttv->GetMaxBitrate() / 8;
-    long long maxSizeKB = maxByterate *
+    long long maxSizeKB = (maxByterate + maxByterate/3) *
                           pginfo->recstartts.secsTo(pginfo->recendts) / 1024;
 
     // Loop though looking for a directory to put the file in.  The first time
@@ -3524,35 +3527,73 @@
     // can't find a directory that way we loop through and pick the first good
     // one from the list no matter how much free space it has.  We assume that
     // something will have to be expired for us to finish the recording.
-    for (unsigned int pass = 1; pass <= 2; pass++)
+    // pass 1: try to fit onto an existing file system with enought free space
+    // pass 2: fit onto the file system with the lowest priority files to be expired
+    //         this is used only with multiple file systems 
+    //         Estimates are made by simulating each expiry until one of
+    //         the file  systems has enough sapce to fit the new file.
+    // pass 3: fit onto the first file system that will take it with lowest
+    //         priority files on this file system expired
+    for (unsigned int pass = 1; pass <= 3; pass++)
     {
         bool foundDir = false;
-        for (fslistit = fsInfoList.begin();
-            fslistit != fsInfoList.end(); fslistit++)
+
+        if (pass == 2 && expirer && fsInfoList.size()>1)
         {
-            long long desiredSpaceKB = 0;
-            FileSystemInfo *fs = *fslistit;
-            if (expirer)
-                desiredSpaceKB = expirer->GetDesiredSpace(fs->fsID);
+            // setup a container of remaing space for all the file systems
+            QMap <int , long long> remainingSpaceKB;
+            for (fslistit = fsInfoList.begin();
+                fslistit != fsInfoList.end(); fslistit++)
+            {
+                     remainingSpaceKB[(*fslistit)->fsID] = (*fslistit)->freeSpaceKB;
+            }
 
-            if ((fs->hostname == pginfo->hostname) &&
-                (dirlist.contains(fs->directory)) &&
-                ((pass == 2) ||
-                 (fs->freeSpaceKB > (desiredSpaceKB + maxSizeKB))))
+            // get list of expirable programs
+            pginfolist_t expiring;
+            expirer->GetAllExpiring(expiring);
+
+            for(pginfolist_t::iterator it=expiring.begin(); 
+                it != expiring.end(); it++)
             {
-                pginfo->pathname = fs->directory;
-                fsID = fs->fsID;
 
-                if (pass == 1)
-                    VERBOSE(VB_FILE, QString("'%1' will record in '%2' which "
-                            "has %3 MiB free. This recording could use a max "
-                            "of %4 MiB and the AutoExpirer wants to keep %5 "
-                            "MiB free.")
-                            .arg(pginfo->title).arg(pginfo->pathname)
-                            .arg(fs->freeSpaceKB / 1024).arg(maxSizeKB / 1024)
-                            .arg(desiredSpaceKB / 1024));
-                else
-                    VERBOSE(VB_FILE, QString("'%1' will record in '%2' "
+                // find the filesystem its on
+                FileSystemInfo *fs=NULL;
+                for (fslistit = fsInfoList.begin();
+                    fslistit != fsInfoList.end(); fslistit++)
+                {
+                    QString filename = (*fslistit)->directory + "/" + (*it)->pathname;
+                    QFile checkFile(filename);
+
+                    if (checkFile.exists())
+                    {
+                        fs = *fslistit;
+                        break;
+                    }
+
+                }   
+
+                if (fs == NULL)
+                {
+                    VERBOSE(VB_IMPORTANT, QString("Unable to match '%1'"
+                            " to any file system. "
+                            " Ignoring it.")
+                            .arg((*it)->pathname));
+                    continue;
+                }
+                    
+
+                // add this files size to the remaing free space
+                remainingSpaceKB[fs->fsID] += (*it)->filesize / 1024;
+                
+                // check if we have enough space for new file
+                long long desiredSpaceKB = expirer->GetDesiredSpace(fs->fsID);
+
+                if (remainingSpaceKB[fs->fsID] > (desiredSpaceKB + maxSizeKB))
+                {
+                    pginfo->pathname = fs->directory;
+                    fsID = fs->fsID;
+
+                    VERBOSE(VB_FILE, QString("pass 2: '%1' will record in '%2' "
                             "although there is only %3 MiB free and the "
                             "AutoExpirer wants at least %4 MiB.  Something "
                             "will have to be deleted or expired in order for "
@@ -3561,11 +3602,63 @@
                             .arg(fs->freeSpaceKB / 1024)
                             .arg(desiredSpaceKB / 1024));
 
-                foundDir = true;
-                break;
+                    foundDir = true;
+                    break;
+                }
             }
+ 
+            // clean up this list - can't call CleanExpireList as it's private
+            ProgramInfo *pginfo = NULL;
+            while (expiring.size() > 0)
+            {
+                pginfo = expiring.back();
+                expiring.pop_back();
+                delete pginfo;
+            }
+
         }
+        else //  passes 1 & 3
+        {
+            for (fslistit = fsInfoList.begin();
+                fslistit != fsInfoList.end(); fslistit++)
+            {
+                long long desiredSpaceKB = 0;
+                FileSystemInfo *fs = *fslistit;
+                if (expirer)
+                    desiredSpaceKB = expirer->GetDesiredSpace(fs->fsID);
 
+                if ((fs->hostname == pginfo->hostname) &&
+                    (dirlist.contains(fs->directory)) &&
+                    ((pass == 3) ||
+                     (fs->freeSpaceKB > (desiredSpaceKB + maxSizeKB))))
+                {
+                    pginfo->pathname = fs->directory;
+                    fsID = fs->fsID;
+
+                    if (pass == 1)
+                        VERBOSE(VB_FILE, QString("pass 1: '%1' will record in '%2' which "
+                                "has %3 MB free. This recording could use a max "
+                                "of %4 MB and the AutoExpirer wants to keep %5 "
+                                "MiB free.")
+                                .arg(pginfo->title).arg(pginfo->pathname)
+                                .arg(fs->freeSpaceKB / 1024).arg(maxSizeKB / 1024)
+                                .arg(desiredSpaceKB / 1024));
+                    else
+                        VERBOSE(VB_FILE, QString("pass 3: '%1' will record in '%2' "
+                                "although there is only %3 MB free and the "
+                                "AutoExpirer wants at least %4 MB.  Something "
+                                "will have to be deleted or expired in order for "
+                                "this recording to complete successfully.")
+                                .arg(pginfo->title).arg(pginfo->pathname)
+                                .arg(fs->freeSpaceKB / 1024)
+                                .arg(desiredSpaceKB / 1024));
+
+                    foundDir = true;
+                    break;
+                }
+            }
+        }
+
         if (foundDir)
             break;
     }
