MythTV  0.26-pre
dvbrecorder.cpp
Go to the documentation of this file.
00001 /*
00002  *  Class DVBRecorder
00003  *
00004  *  Copyright (C) Daniel Thor Kristjansson 2010
00005  *
00006  *   This class glues the DVBStreamHandler which handles the DVB devices
00007  *   to the DTVRecorder that handles recordings in MythTV.
00008  *
00009  *   This program is free software; you can redistribute it and/or modify
00010  *   it under the terms of the GNU General Public License as published by
00011  *   the Free Software Foundation; either version 2 of the License, or
00012  *   (at your option) any later version.
00013  *
00014  *   This program is distributed in the hope that it will be useful,
00015  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *   GNU General Public License for more details.
00018  *
00019  *   You should have received a copy of the GNU General Public License
00020  *   along with this program; if not, write to the Free Software
00021  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  */
00023 
00024 // MythTV includes
00025 #include "dvbstreamhandler.h"
00026 #include "mpegstreamdata.h"
00027 #include "dvbrecorder.h"
00028 #include "dvbchannel.h"
00029 #include "tv_rec.h"
00030 #include "mythlogging.h"
00031 
00032 #define LOC      QString("DVBRec(%1:%2): ") \
00033                  .arg(tvrec->GetCaptureCardNum()).arg(videodevice)
00034 
00035 DVBRecorder::DVBRecorder(TVRec *rec, DVBChannel *channel)
00036     : DTVRecorder(rec), _channel(channel), _stream_handler(NULL)
00037 {
00038     videodevice = QString::null;
00039 }
00040 
00041 bool DVBRecorder::Open(void)
00042 {
00043     if (IsOpen())
00044     {
00045         LOG(VB_GENERAL, LOG_WARNING, LOC + "Card already open");
00046         return true;
00047     }
00048 
00049     if (videodevice.isEmpty())
00050         return false;
00051 
00052     ResetForNewFile();
00053 
00054     _stream_handler = DVBStreamHandler::Get(videodevice);
00055 
00056     LOG(VB_RECORD, LOG_INFO, LOC + "Card opened successfully");
00057 
00058     return true;
00059 }
00060 
00061 bool DVBRecorder::IsOpen(void) const
00062 {
00063     return (NULL != _stream_handler);
00064 }
00065 
00066 void DVBRecorder::Close(void)
00067 {
00068     LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- begin");
00069 
00070     DVBStreamHandler::Return(_stream_handler);
00071 
00072     LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- end");
00073 }
00074 
00075 void DVBRecorder::run(void)
00076 {
00077     if (!Open())
00078     {
00079         _error = "Failed to open DVB device";
00080         LOG(VB_GENERAL, LOG_ERR, LOC + _error);
00081         return;
00082     }
00083 
00084     {
00085         QMutexLocker locker(&pauseLock);
00086         request_recording = true;
00087         recording = true;
00088         recordingWait.wakeAll();
00089     }
00090 
00091     // Listen for time table on DVB standard streams
00092     if (_channel && (_channel->GetSIStandard() == "dvb"))
00093         _stream_data->AddListeningPID(DVB_TDT_PID);
00094 
00095     // Make sure the first things in the file are a PAT & PMT
00096     bool tmp = _wait_for_keyframe_option;
00097     _wait_for_keyframe_option = false;
00098     HandleSingleProgramPAT(_stream_data->PATSingleProgram());
00099     HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
00100     _wait_for_keyframe_option = tmp;
00101 
00102     _stream_data->AddAVListener(this);
00103     _stream_data->AddWritingListener(this);
00104     _stream_handler->AddListener(_stream_data, false, true);
00105 
00106     while (IsRecordingRequested() && !IsErrored())
00107     {
00108         if (PauseAndWait())
00109             continue;
00110 
00111         {   // sleep 100 milliseconds unless StopRecording() or Unpause()
00112             // is called, just to avoid running this too often.
00113             QMutexLocker locker(&pauseLock);
00114             if (!request_recording || request_pause)
00115                 continue;
00116             unpauseWait.wait(&pauseLock, 100);
00117         }
00118 
00119         if (!_input_pmt)
00120         {
00121             LOG(VB_GENERAL, LOG_WARNING, LOC +
00122                     "Recording will not commence until a PMT is set.");
00123             usleep(5000);
00124             continue;
00125         }
00126 
00127         if (!_stream_handler->IsRunning())
00128         {
00129             _error = "Stream handler died unexpectedly.";
00130             LOG(VB_GENERAL, LOG_ERR, LOC + _error);
00131         }
00132     }
00133 
00134     _stream_handler->RemoveListener(_stream_data);
00135     _stream_data->RemoveWritingListener(this);
00136     _stream_data->RemoveAVListener(this);
00137 
00138     Close();
00139 
00140     FinishRecording();
00141 
00142     QMutexLocker locker(&pauseLock);
00143     recording = false;
00144     recordingWait.wakeAll();
00145 }
00146 
00147 bool DVBRecorder::PauseAndWait(int timeout)
00148 {
00149     QMutexLocker locker(&pauseLock);
00150     if (request_pause)
00151     {
00152         if (!IsPaused(true))
00153         {
00154             _stream_handler->RemoveListener(_stream_data);
00155 
00156             paused = true;
00157             pauseWait.wakeAll();
00158             if (tvrec)
00159                 tvrec->RecorderPaused();
00160         }
00161 
00162         unpauseWait.wait(&pauseLock, timeout);
00163     }
00164 
00165     if (!request_pause && IsPaused(true))
00166     {
00167         paused = false;
00168         _stream_handler->AddListener(_stream_data, false, true);
00169         unpauseWait.wakeAll();
00170     }
00171 
00172     return IsPaused(true);
00173 }
00174 
00175 QString DVBRecorder::GetSIStandard(void) const
00176 {
00177     return _channel->GetSIStandard();
00178 }
00179 
00180 void DVBRecorder::SetCAMPMT(const ProgramMapTable *pmt)
00181 {
00182     _channel->SetPMT(pmt);
00183 }
00184 
00185 void DVBRecorder::UpdateCAMTimeOffset(void)
00186 {
00187     _channel->SetTimeOffset(GetStreamData()->TimeOffset());
00188 }
00189 
00190 /* vim: set expandtab tabstop=4 shiftwidth=4: */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends