MythTV  0.26-pre
main.cpp
Go to the documentation of this file.
00001 // POSIX headers
00002 #include <sys/time.h>     // for setpriority
00003 #include <unistd.h>
00004 #include <sys/types.h>
00005 #include <sys/stat.h>
00006 #include <fcntl.h>
00007 #include <libgen.h>
00008 #include <signal.h>
00009 
00010 #include "mythconfig.h"
00011 #if CONFIG_DARWIN
00012     #include <sys/aio.h>    // O_SYNC
00013 #endif
00014 
00015 // C headers
00016 #include <cstdlib>
00017 #include <cerrno>
00018 
00019 // C++ headers
00020 #include <iostream>
00021 #include <fstream>
00022 using namespace std;
00023 
00024 #ifndef _WIN32
00025 #include <QCoreApplication>
00026 #else
00027 #include <QApplication>
00028 #endif
00029 
00030 #include <QFile>
00031 #include <QFileInfo>
00032 #include <QDir>
00033 #include <QMap>
00034 #include <QRegExp>
00035 
00036 #include "mythcontext.h"
00037 #include "mythcorecontext.h"
00038 #include "mythversion.h"
00039 #include "mythdb.h"
00040 #include "exitcodes.h"
00041 #include "compat.h"
00042 #include "storagegroup.h"
00043 #include "programinfo.h"
00044 #include "dbcheck.h"
00045 #include "previewgenerator.h"
00046 #include "commandlineparser.h"
00047 #include "mythsystemevent.h"
00048 #include "mythlogging.h"
00049 
00050 #define LOC      QString("MythPreviewGen: ")
00051 #define LOC_WARN QString("MythPreviewGen, Warning: ")
00052 #define LOC_ERR  QString("MythPreviewGen, Error: ")
00053 
00054 #ifdef Q_OS_MACX
00055     // 10.6 uses some file handles for its new Grand Central Dispatch thingy
00056     #define UNUSED_FILENO 5
00057 #else
00058     #define UNUSED_FILENO 3
00059 #endif
00060 
00061 namespace
00062 {
00063     void cleanup()
00064     {
00065         delete gContext;
00066         gContext = NULL;
00067     }
00068 
00069     class CleanupGuard
00070     {
00071       public:
00072         typedef void (*CleanupFunc)();
00073 
00074       public:
00075         CleanupGuard(CleanupFunc cleanFunction) :
00076             m_cleanFunction(cleanFunction) {}
00077 
00078         ~CleanupGuard()
00079         {
00080             m_cleanFunction();
00081         }
00082 
00083       private:
00084         CleanupFunc m_cleanFunction;
00085     };
00086 }
00087 
00088 int preview_helper(uint chanid, QDateTime starttime,
00089                    long long previewFrameNumber, long long previewSeconds,
00090                    const QSize &previewSize,
00091                    const QString &infile, const QString &outfile)
00092 {
00093     // Lower scheduling priority, to avoid problems with recordings.
00094     if (setpriority(PRIO_PROCESS, 0, 9))
00095         LOG(VB_GENERAL, LOG_ERR, "Setting priority failed." + ENO);
00096 
00097     if (!chanid || !starttime.isValid())
00098         ProgramInfo::QueryKeyFromPathname(infile, chanid, starttime);
00099 
00100     ProgramInfo *pginfo = NULL;
00101     if (chanid && starttime.isValid())
00102     {
00103         pginfo = new ProgramInfo(chanid, starttime);
00104         if (!pginfo->GetChanID())
00105         {
00106             LOG(VB_GENERAL, LOG_ERR,
00107                 QString("Cannot locate recording made on '%1' at '%2'")
00108                     .arg(chanid).arg(starttime.toString("yyyyMMddhhmmss")));
00109             delete pginfo;
00110             return GENERIC_EXIT_NOT_OK;
00111         }
00112         pginfo->SetPathname(pginfo->GetPlaybackURL(false, true));
00113     }
00114     else if (!infile.isEmpty())
00115     {
00116         if (!QFileInfo(infile).isReadable())
00117         {
00118             LOG(VB_GENERAL, LOG_ERR,
00119                 QString("Cannot read this file '%1'").arg(infile));
00120             return GENERIC_EXIT_NOT_OK;
00121         }
00122         pginfo = new ProgramInfo(
00123             infile, ""/*plot*/, ""/*title*/, ""/*subtitle*/, ""/*director*/,
00124             0/*season*/, 0/*episode*/, ""/*inetref*/, 120/*length_in_minutes*/,
00125             1895/*year*/, ""/*id*/);
00126     }
00127     else
00128     {
00129         LOG(VB_GENERAL, LOG_ERR, "Cannot locate recording to preview");
00130         return GENERIC_EXIT_NOT_OK;
00131     }
00132 
00133     PreviewGenerator *previewgen = new PreviewGenerator(
00134         pginfo, QString(), PreviewGenerator::kLocal);
00135 
00136     if (previewFrameNumber >= 0)
00137         previewgen->SetPreviewTimeAsFrameNumber(previewFrameNumber);
00138 
00139     if (previewSeconds >= 0)
00140         previewgen->SetPreviewTimeAsSeconds(previewSeconds);
00141 
00142     previewgen->SetOutputSize(previewSize);
00143     previewgen->SetOutputFilename(outfile);
00144     bool ok = previewgen->RunReal();
00145     previewgen->deleteLater();
00146 
00147     delete pginfo;
00148 
00149     return (ok) ? GENERIC_EXIT_OK : GENERIC_EXIT_NOT_OK;
00150 }
00151 
00152 int main(int argc, char **argv)
00153 {
00154     MythPreviewGeneratorCommandLineParser cmdline;
00155     if (!cmdline.Parse(argc, argv))
00156     {
00157         cmdline.PrintHelp();
00158         return GENERIC_EXIT_INVALID_CMDLINE;
00159     }
00160 
00161     if (cmdline.toBool("showhelp"))
00162     {
00163         cmdline.PrintHelp();
00164         return GENERIC_EXIT_OK;
00165     }
00166 
00167     if (cmdline.toBool("showversion"))
00168     {
00169         cmdline.PrintVersion();
00170         return GENERIC_EXIT_OK;
00171     }
00172 
00173 #ifndef _WIN32
00174     for (int i = UNUSED_FILENO; i < sysconf(_SC_OPEN_MAX) - 1; ++i)
00175         close(i);
00176     QCoreApplication a(argc, argv);
00177 #else
00178     // MINGW application needs a window to receive messages
00179     // such as socket notifications :[
00180     QApplication a(argc, argv);
00181 #endif
00182     QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHPREVIEWGEN);
00183 
00184     int retval;
00185     if ((retval = cmdline.ConfigureLogging()) != GENERIC_EXIT_OK)
00186         return retval;
00187 
00188     if ((!cmdline.toBool("chanid") || !cmdline.toBool("starttime")) &&
00189         !cmdline.toBool("inputfile"))
00190     {
00191         cerr << "--generate-preview must be accompanied by either " <<endl
00192              << "\nboth --chanid and --starttime parameters, " << endl
00193              << "\nor the --infile parameter." << endl;
00194         return GENERIC_EXIT_INVALID_CMDLINE;
00195     }
00196 
00198 
00199     // Don't listen to console input
00200     close(0);
00201 
00202     CleanupGuard callCleanup(cleanup);
00203 
00204     if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
00205         LOG(VB_GENERAL, LOG_WARNING, LOC + "Unable to ignore SIGPIPE");
00206 
00207     gContext = new MythContext(MYTH_BINARY_VERSION);
00208 
00209     if (!gContext->Init(false))
00210     {
00211         LOG(VB_GENERAL, LOG_ERR, "Failed to init MythContext.");
00212         return GENERIC_EXIT_NO_MYTHCONTEXT;
00213     }
00214     gCoreContext->SetBackend(false); // TODO Required?
00215 
00216     int ret = preview_helper(
00217         cmdline.toUInt("chanid"), cmdline.toDateTime("starttime"),
00218         cmdline.toLongLong("frame"), cmdline.toLongLong("seconds"),
00219         cmdline.toSize("size"),
00220         cmdline.toString("inputfile"), cmdline.toString("outputfile"));
00221     return ret;
00222 }
00223 
00224 /* vim: set expandtab tabstop=4 shiftwidth=4: */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends