MythTV  0.26-pre
asirecorder.cpp
Go to the documentation of this file.
00001 /*  -*- Mode: c++ -*-
00002  *   Class ASIRecorder
00003  *
00004  *   Copyright (C) Daniel Kristjansson 2010
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 // Qt includes
00022 #include <QString>
00023 
00024 // MythTV includes
00025 #include "asistreamhandler.h"
00026 #include "asirecorder.h"
00027 #include "asichannel.h"
00028 #include "ringbuffer.h"
00029 #include "tv_rec.h"
00030 
00031 #define LOC QString("ASIRec(%1): ").arg(tvrec->GetCaptureCardNum())
00032 
00033 ASIRecorder::ASIRecorder(TVRec *rec, ASIChannel *channel) :
00034     DTVRecorder(rec), m_channel(channel), m_stream_handler(NULL),
00035     m_record_mpts(false)
00036 {
00037     SetStreamData(new MPEGStreamData(-1,false));
00038     if (channel->GetProgramNumber() < 0 || !channel->GetMinorChannel())
00039         _stream_data->SetListeningDisabled(true);
00040 }
00041 
00042 void ASIRecorder::SetOptionsFromProfile(RecordingProfile *profile,
00043                                         const QString &videodev,
00044                                         const QString &audiodev,
00045                                         const QString &vbidev)
00046 {
00047     // We don't want to call DTVRecorder::SetOptionsFromProfile() since
00048     // we do not have a "recordingtype" in our profile.
00049     DTVRecorder::SetOption("videodevice", videodev);
00050     DTVRecorder::SetOption("tvformat", gCoreContext->GetSetting("TVFormat"));
00051     SetIntOption(profile, "recordmpts");
00052 }
00053 
00057 void ASIRecorder::SetOption(const QString &name, int value)
00058 {
00059     if (name == "recordmpts")
00060         m_record_mpts = (value == 1);
00061     else
00062         DTVRecorder::SetOption(name, value);
00063 }
00064 
00065 void ASIRecorder::run(void)
00066 {
00067     if (!Open())
00068     {
00069         _error = "Failed to open device";
00070         LOG(VB_GENERAL, LOG_ERR, LOC + _error);
00071         return;
00072     }
00073 
00074     if (!_stream_data)
00075     {
00076         _error = "MPEGStreamData pointer has not been set";
00077         LOG(VB_GENERAL, LOG_ERR, LOC + _error);
00078         Close();
00079         return;        
00080     }
00081 
00082     {
00083         QMutexLocker locker(&pauseLock);
00084         request_recording = true;
00085         recording = true;
00086         recordingWait.wakeAll();
00087     }
00088 
00089     if (m_channel->HasGeneratedPAT())
00090     {
00091         const ProgramAssociationTable *pat = m_channel->GetGeneratedPAT();
00092         const ProgramMapTable         *pmt = m_channel->GetGeneratedPMT();
00093         _stream_data->Reset(pat->ProgramNumber(0));
00094         _stream_data->HandleTables(MPEG_PAT_PID, *pat);
00095         _stream_data->HandleTables(pat->ProgramPID(0), *pmt);
00096     }
00097 
00098     // Listen for time table on DVB standard streams
00099     if (m_channel && (m_channel->GetSIStandard() == "dvb"))
00100         _stream_data->AddListeningPID(DVB_TDT_PID);
00101 
00102     // Make sure the first things in the file are a PAT & PMT
00103     bool tmp = _wait_for_keyframe_option;
00104     _wait_for_keyframe_option = false;
00105     HandleSingleProgramPAT(_stream_data->PATSingleProgram());
00106     HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
00107     _wait_for_keyframe_option = tmp;
00108 
00109     _stream_data->AddAVListener(this);
00110     _stream_data->AddWritingListener(this);
00111     m_stream_handler->AddListener(
00112         _stream_data, false, true,
00113         (m_record_mpts) ? ringBuffer->GetFilename() : QString());
00114 
00115     while (IsRecordingRequested() && !IsErrored())
00116     {
00117         if (PauseAndWait())
00118             continue;
00119 
00120         {   // sleep 100 milliseconds unless StopRecording() or Unpause()
00121             // is called, just to avoid running this too often.
00122             QMutexLocker locker(&pauseLock);
00123             if (!request_recording || request_pause)
00124                 continue;
00125             unpauseWait.wait(&pauseLock, 100);
00126         }
00127 
00128         if (!_input_pmt)
00129         {
00130             LOG(VB_GENERAL, LOG_WARNING, LOC +
00131                 "Recording will not commence until a PMT is set.");
00132             usleep(5000);
00133             continue;
00134         }
00135 
00136         if (!m_stream_handler->IsRunning())
00137         {
00138             _error = "Stream handler died unexpectedly.";
00139             LOG(VB_GENERAL, LOG_ERR, LOC + _error);
00140         }
00141     }
00142 
00143     m_stream_handler->RemoveListener(_stream_data);
00144     _stream_data->RemoveWritingListener(this);
00145     _stream_data->RemoveAVListener(this);
00146 
00147     Close();
00148 
00149     FinishRecording();
00150 
00151     QMutexLocker locker(&pauseLock);
00152     recording = false;
00153     recordingWait.wakeAll();
00154 }
00155 
00156 bool ASIRecorder::Open(void)
00157 {
00158     if (IsOpen())
00159     {
00160         LOG(VB_GENERAL, LOG_WARNING, LOC + "Card already open");
00161         return true;
00162     }
00163 
00164     ResetForNewFile();
00165 
00166     m_stream_handler = ASIStreamHandler::Get(m_channel->GetDevice());
00167 
00168     LOG(VB_RECORD, LOG_INFO, LOC + "Opened successfully");
00169 
00170     return true;
00171 }
00172 
00173 bool ASIRecorder::IsOpen(void) const
00174 {
00175     return m_stream_handler;
00176 }
00177 
00178 void ASIRecorder::Close(void)
00179 {
00180     LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- begin");
00181 
00182     if (IsOpen())
00183         ASIStreamHandler::Return(m_stream_handler);
00184 
00185     LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- end");
00186 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends