MythTV  0.26-pre
importrecorder.cpp
Go to the documentation of this file.
00001 /* -*- Mode: c++ -*-
00002  *   Class ImportRecorder
00003  *
00004  *   Copyright (C) Daniel Kristjansson 2009
00005  *
00006  *   This program is free software; you can redistribute it and/or modify
00007  *   it under the terms of the GNU General Public License as published by
00008  *   the Free Software Foundation; either version 2 of the License, or
00009  *   (at your option) any later version.
00010  *
00011  *   This program is distributed in the hope that it will be useful,
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *   GNU General Public License for more details.
00015  *
00016  *   You should have received a copy of the GNU General Public License
00017  *   along with this program; if not, write to the Free Software
00018  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 // POSIX
00022 #ifndef USING_MINGW
00023 #include <sys/select.h>
00024 #endif
00025 #include <sys/types.h>
00026 #include <sys/stat.h>
00027 #include <fcntl.h>
00028 
00029 // Qt
00030 #include <QDir>
00031 
00032 // MythTV
00033 #include "mythcommflagplayer.h"
00034 #include "importrecorder.h"
00035 #include "mythdirs.h"
00036 #include "tv_rec.h"
00037 #include "mythmiscutil.h"
00038 
00039 #define TVREC_CARDNUM \
00040         ((tvrec != NULL) ? QString::number(tvrec->GetCaptureCardNum()) : "NULL")
00041 
00042 #define LOC      QString("ImportRec(%1:%2): ") \
00043                  .arg(TVREC_CARDNUM).arg(videodevice)
00044 
00045 ImportRecorder::ImportRecorder(TVRec *rec) :
00046     DTVRecorder(rec), _import_fd(-1)
00047 {
00048 }
00049 
00050 ImportRecorder::~ImportRecorder()
00051 {
00052 }
00053 
00054 void ImportRecorder::SetOptionsFromProfile(RecordingProfile *profile,
00055                                            const QString &videodev,
00056                                            const QString &audiodev,
00057                                            const QString &vbidev)
00058 {
00059     (void)audiodev;
00060     (void)vbidev;
00061     (void)profile;
00062 
00063     QString testVideoDev = videodev;
00064 
00065     if (videodev.toLower().startsWith("file:"))
00066         testVideoDev = videodev.mid(5);
00067 
00068     QFileInfo fi(testVideoDev);
00069     if (fi.exists() && fi.isReadable() && fi.isFile() && fi.size() > 1560)
00070         SetOption("videodevice", testVideoDev);
00071     else
00072         SetOption("videodevice", "unknown file");
00073 
00074     SetOption("tvformat",    gCoreContext->GetSetting("TVFormat"));
00075     SetOption("vbiformat",   gCoreContext->GetSetting("VbiFormat"));
00076 }
00077 
00078 void ImportRecorder::run(void)
00079 {
00080     LOG(VB_RECORD, LOG_INFO, LOC + "run -- begin");
00081 
00082     {
00083         QMutexLocker locker(&pauseLock);
00084         request_recording = true;
00085         recording = true;
00086         recordingWait.wakeAll();
00087     }
00088 
00089     LOG(VB_RECORD, LOG_INFO, LOC + "run -- " +
00090         QString("attempting to open '%1'")
00091             .arg(curRecording->GetPathname()));
00092 
00093     // retry opening the file until StopRecording() is called.
00094     while (!Open() && IsRecordingRequested() && !IsErrored())
00095     {   // sleep 250 milliseconds unless StopRecording() or Unpause()
00096         // is called, just to avoid running this loop too often.
00097         QMutexLocker locker(&pauseLock);
00098         if (request_recording)
00099             unpauseWait.wait(&pauseLock, 250);
00100     }
00101 
00102     curRecording->SaveFilesize(ringBuffer->GetRealFileSize());
00103 
00104     // build seek table
00105     if (_import_fd && IsRecordingRequested() && !IsErrored())
00106     {
00107         MythCommFlagPlayer *cfp =
00108             new MythCommFlagPlayer((PlayerFlags)(kAudioMuted | kVideoIsNull));
00109         RingBuffer *rb = RingBuffer::Create(
00110             ringBuffer->GetFilename(), false, true, 6000);
00111 
00112         PlayerContext *ctx = new PlayerContext(kImportRecorderInUseID);
00113         ctx->SetPlayingInfo(curRecording);
00114         ctx->SetRingBuffer(rb);
00115         ctx->SetPlayer(cfp);
00116         cfp->SetPlayerInfo(NULL, NULL, ctx);
00117 
00118         cfp->RebuildSeekTable(false);
00119 
00120         delete ctx;
00121     }
00122 
00123     curRecording->SaveFilesize(ringBuffer->GetRealFileSize());
00124 
00125     // cleanup...
00126     Close();
00127 
00128     FinishRecording();
00129 
00130     QMutexLocker locker(&pauseLock);
00131     recording = false;
00132     recordingWait.wakeAll();
00133 
00134     LOG(VB_RECORD, LOG_INFO, LOC + "run -- end");
00135 }
00136 
00137 bool ImportRecorder::Open(void)
00138 {
00139     if (_import_fd >= 0)   // already open
00140         return true;
00141 
00142     if (!curRecording)
00143     {
00144         LOG(VB_RECORD, LOG_ERR, LOC + "no current recording!");
00145         return false;
00146     }
00147 
00148     ResetForNewFile();
00149 
00150     QString fn = curRecording->GetPathname();
00151 
00152     // Quick-and-dirty "copy" of sample prerecorded file.
00153     // Sadly, won't work on Windows.
00154     //
00155     QFile preRecorded(videodevice);
00156     QFile copy(fn);
00157     if (preRecorded.exists() && (!copy.exists() || copy.size() == 0))
00158     {
00159         if (copy.exists())   // always created by RecorderBase?
00160         {
00161             QDir targetDir(".");  // QDir::remove() needs an object
00162             targetDir.remove(fn);
00163         }
00164 
00165         LOG(VB_RECORD, LOG_INFO, LOC + QString("Trying to link %1 to %2")
00166                            .arg(videodevice).arg(fn));
00167 
00168         if (preRecorded.link(fn))
00169             LOG(VB_RECORD, LOG_DEBUG, LOC + "success!");
00170         else
00171             LOG(VB_RECORD, LOG_ERR, LOC + preRecorded.errorString());
00172     }
00173 
00174     if (fn.toLower().startsWith("myth://"))
00175     {
00176         LOG(VB_RECORD, LOG_ERR, LOC + "Malformed recording ProgramInfo.");
00177         return false;
00178     }
00179 
00180     QFileInfo f(fn);
00181     if (!f.exists())
00182     {
00183         LOG(VB_RECORD, LOG_INFO, LOC +
00184             QString("'%1' does not exist yet").arg(fn));
00185 
00186         // Slow down run open loop when debugging -v record.
00187         // This is just to make the debugging output less spammy.
00188         if (VERBOSE_LEVEL_CHECK(VB_RECORD, LOG_ANY))
00189             usleep(250 * 1000);
00190 
00191         return false;
00192     }
00193     else if (!f.isReadable())
00194     {
00195         LOG(VB_GENERAL, LOG_ERR, LOC +
00196             QString("'%1' is not readable").arg(fn));
00197         return false;
00198     }
00199 
00200     _import_fd = open(fn.toLocal8Bit().constData(), O_RDONLY);
00201     if (_import_fd < 0)
00202     {
00203         LOG(VB_GENERAL, LOG_ERR, LOC +
00204             QString("Couldn't open '%1'").arg(fn) + ENO);
00205     }
00206 
00207     return _import_fd >= 0;
00208 }
00209 
00210 void ImportRecorder::Close(void)
00211 {
00212     if (_import_fd >= 0)
00213     {
00214         close(_import_fd);
00215         _import_fd = -1;
00216     }
00217 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends