MythTV  0.26-pre
checksetup.cpp
Go to the documentation of this file.
00001 // checksetup.cpp
00002 //
00003 // Some functions to do simple sanity checks on the MythTV setup.
00004 // CheckSetup() is currently meant for the mythtv-setup program,
00005 // but the other functions could probably be called from anywhere.
00006 // They all return true if any problems are found, and add to a
00007 // caller-supplied QString a message describing the problem.
00008 
00009 #include <QDir>
00010 
00011 #include "mythdb.h"
00012 #include "mythcorecontext.h"
00013 #include "mythmiscutil.h"
00014 #include "checksetup.h"
00015 
00017 
00018 static bool checkPath(QString path, QStringList &probs)
00019 {
00020     QDir dir(path);
00021     if (!dir.exists())
00022     {
00023         probs.push_back(QObject::tr("Path \"%1\" doesn't exist.").arg(path));
00024         return true;
00025     }
00026 
00027     QFile test(path.append("/.test"));
00028     if (test.open(QIODevice::WriteOnly))
00029         test.remove();
00030     else
00031     {
00032         probs.push_back(QObject::tr("Unable to create file \"%1\" - directory "
00033                         "is not writable?").arg(path));
00034         return true;
00035     }
00036 
00037     return false;
00038 }
00039 
00042 
00043 bool checkStoragePaths(QStringList &probs)
00044 {
00045     bool problemFound = false;
00046 
00047     QString recordFilePrefix =
00048             gCoreContext->GetSetting("RecordFilePrefix", "EMPTY");
00049 
00050     MSqlQuery query(MSqlQuery::InitCon());
00051 
00052     query.prepare("SELECT count(groupname) FROM storagegroup;");
00053     if (!query.exec() || !query.isActive() || query.size() < 1)
00054     {
00055         MythDB::DBError("checkStoragePaths", query);
00056         return false;
00057     }
00058 
00059     query.next();
00060     if (query.value(0).toInt() == 0)
00061     {
00062         QString trMesg =
00063                 QObject::tr("No Storage Group directories are defined.  You "
00064                             "must add at least one directory to the Default "
00065                             "Storage Group where new recordings will be "
00066                             "stored.");
00067         probs.push_back(trMesg);
00068         LOG(VB_GENERAL, LOG_ERR, trMesg);
00069         return true;
00070     }
00071 
00072     query.prepare("SELECT groupname, dirname "
00073                   "FROM storagegroup "
00074                   "WHERE hostname = :HOSTNAME;");
00075     query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
00076     if (!query.exec() || !query.isActive())
00077     {
00078         MythDB::DBError("checkStoragePaths", query);
00079         return false;
00080     }
00081     else if (query.size() < 1)
00082     {
00083         if (gCoreContext->IsMasterHost())
00084         {
00085             // Master backend must have a defined Default SG
00086             QString trMesg =
00087                     QObject::tr("No Storage Group directories are defined.  "
00088                                 "You must add at least one directory to the "
00089                                 "Default Storage Group where new recordings "
00090                                 "will be stored.");
00091             probs.push_back(trMesg);
00092             LOG(VB_GENERAL, LOG_ERR, trMesg);
00093             return true;
00094         }
00095         else
00096             return false;
00097     }
00098 
00099     QDir checkDir("");
00100     QString dirname;
00101     while (query.next())
00102     {
00103         /* The storagegroup.dirname column uses utf8_bin collation, so Qt
00104          * uses QString::fromAscii() for toString(). Explicitly convert the
00105          * value using QString::fromUtf8() to prevent corruption. */
00106         dirname = QString::fromUtf8(query.value(1)
00107                                     .toByteArray().constData());
00108         QStringList tokens = dirname.split(",");
00109         int curToken = 0;
00110         while (curToken < tokens.size())
00111         {
00112             checkDir.setPath(tokens[curToken]);
00113             if (checkPath(tokens[curToken], probs))
00114             {
00115                 problemFound = true;
00116             }
00117             curToken++;
00118         }
00119     }
00120 
00121     return problemFound;
00122 }
00123 
00124 bool checkImageStoragePaths(QStringList &probs)
00125 {
00126     bool problemFound = false;
00127 
00128     MSqlQuery query(MSqlQuery::InitCon());
00129 
00130     query.prepare("SELECT groupname "
00131                   "FROM storagegroup "
00132                   "WHERE hostname = :HOSTNAME;");
00133     query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
00134     if (!query.exec() || !query.isActive())
00135     {
00136         MythDB::DBError("checkImageStoragePaths", query);
00137         return false;
00138     }
00139     else if (query.size() < 1)
00140     {
00141         return false;
00142     }
00143 
00144     QStringList groups;
00145     while (query.next())
00146     {
00147         groups += query.value(0).toString();
00148     }
00149 
00150     if (groups.contains("Videos"))
00151     {
00152         if (groups.contains("Fanart") &&
00153                 groups.contains("Coverart") &&
00154                 groups.contains("Screenshots") &&
00155                 groups.contains("Banners"))
00156             problemFound = false;
00157         else
00158         {
00159             QString trMesg =
00160                 QObject::tr("You have a Video Storage "
00161                             "Group, but have not set up "
00162                             "all Image Groups.  If you continue, "
00163                             "video image downloads will be saved in "
00164                             "your Videos Storage Group.  Do you want "
00165                             "to store them in their own groups?");
00166             probs.push_back(trMesg);
00167             LOG(VB_GENERAL, LOG_ERR, trMesg);
00168             problemFound = true;
00169         }
00170     }            
00171 
00172     return problemFound;
00173 }
00174 
00175 // I keep forgetting to change the preset (starting channel) when I add cards,
00176 // so this checks that the assigned channel (which may be the default of 3)
00177 // actually exists. This should save a few beginner Live TV problems
00178 
00179 bool checkChannelPresets(QStringList &probs)
00180 {
00181     bool problemFound = false;
00182 
00183     MSqlQuery query(MSqlQuery::InitCon());
00184 
00185     query.prepare("SELECT cardid, startchan, sourceid, inputname"
00186                   " FROM cardinput;");
00187 
00188     if (!query.exec() || !query.isActive())
00189     {
00190         MythDB::DBError("checkChannelPresets", query);
00191         return false;
00192     }
00193 
00194     while (query.next())
00195     {
00196         int cardid    = query.value(0).toInt();
00197         QString startchan = query.value(1).toString();
00198         int sourceid  = query.value(2).toInt();
00199 
00200         if (query.value(1).toString().isEmpty())    // Logic from tv_rec.cpp
00201             startchan = "3";
00202 
00203         MSqlQuery channelExists(MSqlQuery::InitCon());
00204         QString   channelQuery;
00205         channelQuery = QString("SELECT chanid FROM channel"
00206                                " WHERE channum='%1' AND sourceid=%2;")
00207                               .arg(startchan).arg(sourceid);
00208         channelExists.prepare(channelQuery);
00209 
00210         if (!channelExists.exec() || !channelExists.isActive())
00211         {
00212             MythDB::DBError("checkChannelPresets", channelExists);
00213             return problemFound;
00214         }
00215 
00216         if (channelExists.size() == 0)
00217         {
00218             probs.push_back(QObject::tr("Card %1 (type %2) is set to start on "
00219                             "channel %3, which does not exist.")
00220                     .arg(cardid).arg(query.value(3).toString()).arg(startchan));
00221             problemFound = true;
00222         }
00223     }
00224 
00225     return problemFound;
00226 }
00227 
00230 
00231 bool CheckSetup(QStringList &problems)
00232 {
00233     return checkStoragePaths(problems)
00234         || checkChannelPresets(problems)
00235         || checkImageStoragePaths(problems);
00236 }
00237 
00238 bool needsMFDBReminder()
00239 {
00240     bool needsReminder = false;
00241     MSqlQuery query(MSqlQuery::InitCon());
00242 
00243     query.prepare("SELECT sourceid "
00244                   "FROM videosource "
00245                   "WHERE xmltvgrabber = 'schedulesdirect1' "
00246                   "OR xmltvgrabber = 'datadirect' "
00247                   "OR xmltvgrabber LIKE 'tv_grab_%';");
00248     if (!query.exec() || !query.isActive())
00249     {
00250         MythDB::DBError("needsMFDBReminder", query);
00251     }
00252     else if (query.size() >= 1)
00253     {
00254         needsReminder = true;
00255     }
00256 
00257     return needsReminder;
00258 }
00259 
00260 /* vim: set expandtab tabstop=4 shiftwidth=4: */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends