|
MythTV
0.26-pre
|
00001 // POSIX headers 00002 #include <sys/stat.h> 00003 #include <unistd.h> 00004 #include <errno.h> 00005 00006 // ANSI C headers 00007 #include <cstdlib> 00008 00009 // C++ headers 00010 #include <iostream> 00011 using namespace std; 00012 00013 // qt 00014 #include <QDomDocument> 00015 #include <QDir> 00016 00017 // myth 00018 #include <mythcontext.h> 00019 #include <programinfo.h> 00020 #include <mythmainwindow.h> 00021 #include <mythdialogbox.h> 00022 #include <mythmiscutil.h> 00023 #include <mythsystem.h> 00024 #include <exitcodes.h> 00025 #include <mythlogging.h> 00026 00027 // mytharchive 00028 #include "archiveutil.h" 00029 00030 00031 struct ArchiveDestination ArchiveDestinations[] = 00032 { 00033 {AD_DVD_SL, 00034 QT_TRANSLATE_NOOP("SelectDestination", "Single Layer DVD"), 00035 QT_TRANSLATE_NOOP("SelectDestination", "Single Layer DVD (4,482 MB)"), 00036 4482*1024}, 00037 {AD_DVD_DL, 00038 QT_TRANSLATE_NOOP("SelectDestination", "Dual Layer DVD"), 00039 QT_TRANSLATE_NOOP("SelectDestination", "Dual Layer DVD (8,964 MB)"), 00040 8964*1024}, 00041 {AD_DVD_RW, 00042 QT_TRANSLATE_NOOP("SelectDestination", "DVD +/- RW"), 00043 QT_TRANSLATE_NOOP("SelectDestination", "Rewritable DVD"), 00044 4482*1024}, 00045 {AD_FILE, 00046 QT_TRANSLATE_NOOP("SelectDestination", "File"), 00047 QT_TRANSLATE_NOOP("SelectDestination", "Any file accessable from your filesystem."), 00048 -1}, 00049 }; 00050 00051 int ArchiveDestinationsCount = sizeof(ArchiveDestinations) / sizeof(ArchiveDestinations[0]); 00052 00053 QString formatSize(int64_t sizeKB, int prec) 00054 { 00055 if (sizeKB>1024*1024*1024) // Terabytes 00056 { 00057 double sizeGB = sizeKB/(1024*1024*1024.0); 00058 return QString("%1 TB").arg(sizeGB, 0, 'f', (sizeGB>10)?0:prec); 00059 } 00060 else if (sizeKB>1024*1024) // Gigabytes 00061 { 00062 double sizeGB = sizeKB/(1024*1024.0); 00063 return QString("%1 GB").arg(sizeGB, 0, 'f', (sizeGB>10)?0:prec); 00064 } 00065 else if (sizeKB>1024) // Megabytes 00066 { 00067 double sizeMB = sizeKB/1024.0; 00068 return QString("%1 MB").arg(sizeMB, 0, 'f', (sizeMB>10)?0:prec); 00069 } 00070 // Kilobytes 00071 return QString("%1 KB").arg(sizeKB); 00072 } 00073 00074 QString getTempDirectory(bool showError) 00075 { 00076 QString tempDir = gCoreContext->GetSetting("MythArchiveTempDir", ""); 00077 00078 if (tempDir == "" && showError) 00079 ShowOkPopup(QObject::tr("Cannot find the MythArchive work directory.\n" 00080 "Have you set the correct path in the settings?"), 00081 NULL, NULL); 00082 00083 if (tempDir == "") 00084 return ""; 00085 00086 // make sure the temp directory setting ends with a trailing "/" 00087 if (!tempDir.endsWith("/")) 00088 { 00089 tempDir += "/"; 00090 gCoreContext->SaveSetting("MythArchiveTempDir", tempDir); 00091 } 00092 00093 return tempDir; 00094 } 00095 00096 void checkTempDirectory() 00097 { 00098 QString tempDir = getTempDirectory(); 00099 QString logDir = tempDir + "logs"; 00100 QString configDir = tempDir + "config"; 00101 QString workDir = tempDir + "work"; 00102 00103 // make sure the 'work', 'logs', and 'config' directories exist 00104 QDir dir(tempDir); 00105 if (!dir.exists()) 00106 { 00107 dir.mkdir(tempDir); 00108 if( chmod(qPrintable(tempDir), 0777) ) 00109 LOG(VB_GENERAL, LOG_ERR, 00110 "Failed to change permissions on archive directory: " + ENO); 00111 } 00112 00113 dir = QDir(workDir); 00114 if (!dir.exists()) 00115 { 00116 dir.mkdir(workDir); 00117 if( chmod(qPrintable(workDir), 0777) ) 00118 LOG(VB_GENERAL, LOG_ERR, 00119 "Failed to change permissions on archive work directory: " + 00120 ENO); 00121 } 00122 00123 dir = QDir(logDir); 00124 if (!dir.exists()) 00125 { 00126 dir.mkdir(logDir); 00127 if( chmod(qPrintable(logDir), 0777) ) 00128 LOG(VB_GENERAL, LOG_ERR, 00129 "Failed to change permissions on archive log directory: " + 00130 ENO); 00131 } 00132 dir = QDir(configDir); 00133 if (!dir.exists()) 00134 { 00135 dir.mkdir(configDir); 00136 if( chmod(qPrintable(configDir), 0777) ) 00137 LOG(VB_GENERAL, LOG_ERR, 00138 "Failed to change permissions on archive config directory: " + 00139 ENO); 00140 } 00141 } 00142 00143 QString getBaseName(const QString &filename) 00144 { 00145 QString baseName = filename; 00146 int pos = filename.lastIndexOf('/'); 00147 if (pos > 0) 00148 baseName = filename.mid(pos + 1); 00149 00150 return baseName; 00151 } 00152 00153 bool extractDetailsFromFilename(const QString &inFile, 00154 QString &chanID, QString &startTime) 00155 { 00156 LOG(VB_JOBQUEUE, LOG_INFO, "Extracting details from: " + inFile); 00157 00158 QString baseName = getBaseName(inFile); 00159 00160 MSqlQuery query(MSqlQuery::InitCon()); 00161 query.prepare("SELECT chanid, starttime FROM recorded " 00162 "WHERE basename = :BASENAME"); 00163 query.bindValue(":BASENAME", baseName); 00164 00165 if (query.exec() && query.next()) 00166 { 00167 chanID = query.value(0).toString(); 00168 startTime= query.value(1).toString(); 00169 } 00170 else 00171 { 00172 LOG(VB_JOBQUEUE, LOG_ERR, 00173 QString("Cannot find details for %1").arg(inFile)); 00174 return false; 00175 } 00176 00177 LOG(VB_JOBQUEUE, LOG_INFO, 00178 QString("chanid: %1 starttime:%2 ").arg(chanID).arg(startTime)); 00179 00180 return true; 00181 } 00182 00183 ProgramInfo *getProgramInfoForFile(const QString &inFile) 00184 { 00185 ProgramInfo *pinfo = NULL; 00186 QString chanID, startTime; 00187 bool bIsMythRecording = false; 00188 00189 bIsMythRecording = extractDetailsFromFilename(inFile, chanID, startTime); 00190 00191 if (bIsMythRecording) 00192 { 00193 uint chanid = chanID.toUInt(); 00194 QDateTime recstartts = myth_dt_from_string(startTime); 00195 pinfo = new ProgramInfo(chanid, recstartts); 00196 if (pinfo->GetChanID()) 00197 { 00198 pinfo->SetPathname(pinfo->GetPlaybackURL(false, true)); 00199 } 00200 else 00201 { 00202 delete pinfo; 00203 pinfo = NULL; 00204 } 00205 } 00206 00207 if (!pinfo) 00208 { 00209 // file is not a myth recording or is no longer in the db 00210 pinfo = new ProgramInfo(inFile); 00211 LOG(VB_JOBQUEUE, LOG_NOTICE, "File is not a MythTV recording."); 00212 } 00213 else 00214 LOG(VB_JOBQUEUE, LOG_NOTICE, "File is a MythTV recording."); 00215 00216 return pinfo; 00217 } 00218 00219 bool getFileDetails(ArchiveItem *a) 00220 { 00221 QString tempDir = gCoreContext->GetSetting("MythArchiveTempDir", ""); 00222 00223 if (!tempDir.endsWith("/")) 00224 tempDir += "/"; 00225 00226 QString inFile; 00227 int lenMethod = 0; 00228 if (a->type == "Recording") 00229 { 00230 inFile = a->filename; 00231 lenMethod = 2; 00232 } 00233 else 00234 { 00235 inFile = a->filename; 00236 } 00237 00238 inFile.replace("\'", "\\\'"); 00239 inFile.replace("\"", "\\\""); 00240 inFile.replace("`", "\\`"); 00241 00242 QString outFile = tempDir + "work/file.xml"; 00243 00244 // call mytharchivehelper to get files stream info etc. 00245 QString command = QString("mytharchivehelper --getfileinfo --infile \"%1\" " 00246 "--outfile \"%2\" --method %3") 00247 .arg(inFile).arg(outFile).arg(lenMethod); 00248 command += logPropagateArgs; 00249 if (!logPropagateQuiet()) 00250 command += " --quiet"; 00251 00252 uint flags = kMSDontBlockInputDevs | kMSDontDisableDrawing; 00253 if (myth_system(command, flags) != GENERIC_EXIT_OK) 00254 return false; 00255 00256 QDomDocument doc("mydocument"); 00257 QFile file(outFile); 00258 if (!file.open(QIODevice::ReadOnly)) 00259 return false; 00260 00261 if (!doc.setContent( &file )) 00262 { 00263 file.close(); 00264 return false; 00265 } 00266 file.close(); 00267 00268 // get file type and duration 00269 QDomElement docElem = doc.documentElement(); 00270 QDomNodeList nodeList = doc.elementsByTagName("file"); 00271 if (nodeList.count() < 1) 00272 return false; 00273 QDomNode n = nodeList.item(0); 00274 QDomElement e = n.toElement(); 00275 a->fileCodec = e.attribute("type"); 00276 a->duration = e.attribute("duration").toInt(); 00277 a->cutDuration = e.attribute("cutduration").toInt(); 00278 00279 // get frame size and video codec 00280 nodeList = doc.elementsByTagName("video"); 00281 if (nodeList.count() < 1) 00282 return false; 00283 n = nodeList.item(0); 00284 e = n.toElement(); 00285 a->videoCodec = e.attribute("codec"); 00286 a->videoWidth = e.attribute("width").toInt(); 00287 a->videoHeight = e.attribute("height").toInt(); 00288 00289 return true; 00290 } 00291 00292 void showWarningDialog(const QString msg) 00293 { 00294 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 00295 MythConfirmationDialog *dialog = new MythConfirmationDialog(popupStack, msg, false); 00296 00297 if (dialog->Create()) 00298 popupStack->AddScreen(dialog); 00299 } 00300 00301 void recalcItemSize(ArchiveItem *item) 00302 { 00303 EncoderProfile *profile = item->encoderProfile; 00304 if (!profile) 00305 return; 00306 00307 if (profile->name == "NONE") 00308 { 00309 if (item->hasCutlist && item->useCutlist) 00310 item->newsize = (int64_t) (item->size / 00311 ((float)item->duration / (float)item->cutDuration)); 00312 else 00313 item->newsize = item->size; 00314 } 00315 else 00316 { 00317 if (item->duration == 0) 00318 return; 00319 00320 int length; 00321 00322 if (item->hasCutlist && item->useCutlist) 00323 length = item->cutDuration; 00324 else 00325 length = item->duration; 00326 00327 float len = (float) length / 3600; 00328 item->newsize = (int64_t) (len * profile->bitrate * 1024 * 1024); 00329 } 00330 } 00331 00332 /* vim: set expandtab tabstop=4 shiftwidth=4: */
1.7.6.1