|
MythTV
0.26-pre
|
00001 #include <iostream> 00002 00003 #include <QCursor> 00004 #include <QLayout> 00005 00006 #include "recordingprofile.h" 00007 #include "cardutil.h" 00008 #include "mythcorecontext.h" 00009 #include "mythdb.h" 00010 #include "mythlogging.h" 00011 #include "mythwizard.h" 00012 00013 QString RecordingProfileStorage::GetWhereClause(MSqlBindings &bindings) const 00014 { 00015 QString idTag(":WHEREID"); 00016 QString query("id = " + idTag); 00017 00018 bindings.insert(idTag, m_parent.getProfileNum()); 00019 00020 return query; 00021 } 00022 00023 class CodecParamStorage : public SimpleDBStorage 00024 { 00025 protected: 00026 CodecParamStorage(Setting *_setting, 00027 const RecordingProfile &parentProfile, 00028 QString name) : 00029 SimpleDBStorage(_setting, "codecparams", "value"), 00030 m_parent(parentProfile), codecname(name) 00031 { 00032 _setting->setName(name); 00033 } 00034 00035 virtual QString GetSetClause(MSqlBindings &bindings) const; 00036 virtual QString GetWhereClause(MSqlBindings &bindings) const; 00037 00038 const RecordingProfile &m_parent; 00039 QString codecname; 00040 }; 00041 00042 QString CodecParamStorage::GetSetClause(MSqlBindings &bindings) const 00043 { 00044 QString profileTag(":SETPROFILE"); 00045 QString nameTag(":SETNAME"); 00046 QString valueTag(":SETVALUE"); 00047 00048 QString query("profile = " + profileTag + ", name = " + nameTag 00049 + ", value = " + valueTag); 00050 00051 bindings.insert(profileTag, m_parent.getProfileNum()); 00052 bindings.insert(nameTag, codecname); 00053 bindings.insert(valueTag, user->GetDBValue()); 00054 00055 return query; 00056 } 00057 00058 QString CodecParamStorage::GetWhereClause(MSqlBindings &bindings) const 00059 { 00060 QString profileTag(":WHEREPROFILE"); 00061 QString nameTag(":WHERENAME"); 00062 00063 QString query("profile = " + profileTag + " AND name = " + nameTag); 00064 00065 bindings.insert(profileTag, m_parent.getProfileNum()); 00066 bindings.insert(nameTag, codecname); 00067 00068 return query; 00069 } 00070 00071 class AudioCodecName: public ComboBoxSetting, public RecordingProfileStorage 00072 { 00073 public: 00074 AudioCodecName(const RecordingProfile &parent) : 00075 ComboBoxSetting(this), 00076 RecordingProfileStorage(this, parent, "audiocodec") 00077 { 00078 setLabel(QObject::tr("Codec")); 00079 } 00080 }; 00081 00082 class MP3Quality : public SliderSetting, public CodecParamStorage 00083 { 00084 public: 00085 MP3Quality(const RecordingProfile &parent) : 00086 SliderSetting(this, 1, 9, 1), 00087 CodecParamStorage(this, parent, "mp3quality") 00088 { 00089 setLabel(QObject::tr("MP3 quality")); 00090 setValue(7); 00091 setHelpText(QObject::tr("The higher the slider number, the lower the " 00092 "quality of the audio. Better quality audio (lower " 00093 "numbers) requires more CPU.")); 00094 }; 00095 }; 00096 00097 class BTTVVolume : public SliderSetting, public CodecParamStorage 00098 { 00099 public: 00100 BTTVVolume(const RecordingProfile& parent) : 00101 SliderSetting(this, 0, 100, 1), 00102 CodecParamStorage(this, parent, "volume") 00103 { 00104 setLabel(QObject::tr("Volume (%)")); 00105 setValue(90); 00106 setHelpText(QObject::tr("Recording volume of the capture card.")); 00107 }; 00108 }; 00109 00110 class SampleRate : public ComboBoxSetting, public CodecParamStorage 00111 { 00112 public: 00113 SampleRate(const RecordingProfile &parent, bool analog = true) : 00114 ComboBoxSetting(this), CodecParamStorage(this, parent, "samplerate") 00115 { 00116 setLabel(QObject::tr("Sampling rate")); 00117 setHelpText(QObject::tr("Sets the audio sampling rate for your DSP. " 00118 "Ensure that you choose a sampling rate appropriate " 00119 "for your device. btaudio may only allow 32000.")); 00120 00121 rates.push_back(32000); 00122 rates.push_back(44100); 00123 rates.push_back(48000); 00124 00125 allowed_rate[48000] = true; 00126 for (uint i = 0; analog && (i < rates.size()); i++) 00127 allowed_rate[rates[i]] = true; 00128 00129 }; 00130 00131 void Load(void) 00132 { 00133 CodecParamStorage::Load(); 00134 QString val = getValue(); 00135 00136 clearSelections(); 00137 for (uint i = 0; i < rates.size(); i++) 00138 { 00139 if (allowed_rate[rates[i]]) 00140 addSelection(QString::number(rates[i])); 00141 } 00142 00143 int which = getValueIndex(val); 00144 setValue(max(which,0)); 00145 00146 if (allowed_rate.size() <= 1) 00147 setEnabled(false); 00148 } 00149 00150 void addSelection(const QString &label, 00151 QString value = QString::null, 00152 bool select = false) 00153 { 00154 QString val = value.isEmpty() ? label : value; 00155 uint rate = val.toUInt(); 00156 if (allowed_rate[rate]) 00157 { 00158 ComboBoxSetting::addSelection(label, value, select); 00159 } 00160 else 00161 { 00162 LOG(VB_GENERAL, LOG_ERR, QString("SampleRate: ") + 00163 QString("Attempted to add a rate %1 Hz, which is " 00164 "not in the list of allowed rates.").arg(rate)); 00165 } 00166 } 00167 00168 vector<uint> rates; 00169 QMap<uint,bool> allowed_rate; 00170 }; 00171 00172 class MPEG2audType : public ComboBoxSetting, public CodecParamStorage 00173 { 00174 public: 00175 MPEG2audType(const RecordingProfile &parent, 00176 bool layer1, bool layer2, bool layer3) : 00177 ComboBoxSetting(this), CodecParamStorage(this, parent, "mpeg2audtype"), 00178 allow_layer1(layer1), allow_layer2(layer2), allow_layer3(layer3) 00179 { 00180 setLabel(QObject::tr("Type")); 00181 00182 if (allow_layer1) 00183 addSelection("Layer I"); 00184 if (allow_layer2) 00185 addSelection("Layer II"); 00186 if (allow_layer3) 00187 addSelection("Layer III"); 00188 00189 uint allowed_cnt = 0; 00190 allowed_cnt += ((allow_layer1) ? 1 : 0); 00191 allowed_cnt += ((allow_layer2) ? 1 : 0); 00192 allowed_cnt += ((allow_layer3) ? 1 : 0); 00193 00194 if (1 == allowed_cnt) 00195 setEnabled(false); 00196 00197 setHelpText(QObject::tr("Sets the audio type")); 00198 } 00199 00200 void Load(void) 00201 { 00202 CodecParamStorage::Load(); 00203 QString val = getValue(); 00204 00205 if ((val == "Layer I") && !allow_layer1) 00206 { 00207 val = (allow_layer2) ? "Layer II" : 00208 ((allow_layer3) ? "Layer III" : val); 00209 } 00210 00211 if ((val == "Layer II") && !allow_layer2) 00212 { 00213 val = (allow_layer3) ? "Layer III" : 00214 ((allow_layer1) ? "Layer I" : val); 00215 } 00216 00217 if ((val == "Layer III") && !allow_layer3) 00218 { 00219 val = (allow_layer2) ? "Layer II" : 00220 ((allow_layer1) ? "Layer I" : val); 00221 } 00222 00223 if (getValue() != val) 00224 { 00225 int which = getValueIndex(val); 00226 if (which >= 0) 00227 setValue(which); 00228 } 00229 } 00230 00231 private: 00232 bool allow_layer1; 00233 bool allow_layer2; 00234 bool allow_layer3; 00235 }; 00236 00237 class MPEG2audBitrateL1 : public ComboBoxSetting, public CodecParamStorage 00238 { 00239 public: 00240 MPEG2audBitrateL1(const RecordingProfile &parent) : 00241 ComboBoxSetting(this), 00242 CodecParamStorage(this, parent, "mpeg2audbitratel1") 00243 { 00244 setLabel(QObject::tr("Bitrate")); 00245 00246 addSelection("32 kbps", "32"); 00247 addSelection("64 kbps", "64"); 00248 addSelection("96 kbps", "96"); 00249 addSelection("128 kbps", "128"); 00250 addSelection("160 kbps", "160"); 00251 addSelection("192 kbps", "192"); 00252 addSelection("224 kbps", "224"); 00253 addSelection("256 kbps", "256"); 00254 addSelection("288 kbps", "288"); 00255 addSelection("320 kbps", "320"); 00256 addSelection("352 kbps", "352"); 00257 addSelection("384 kbps", "384"); 00258 addSelection("416 kbps", "416"); 00259 addSelection("448 kbps", "448"); 00260 setValue(13); 00261 setHelpText(QObject::tr("Sets the audio bitrate")); 00262 }; 00263 }; 00264 00265 class MPEG2audBitrateL2 : public ComboBoxSetting, public CodecParamStorage 00266 { 00267 public: 00268 MPEG2audBitrateL2(const RecordingProfile &parent) : 00269 ComboBoxSetting(this), 00270 CodecParamStorage(this, parent, "mpeg2audbitratel2") 00271 { 00272 setLabel(QObject::tr("Bitrate")); 00273 00274 addSelection("32 kbps", "32"); 00275 addSelection("48 kbps", "48"); 00276 addSelection("56 kbps", "56"); 00277 addSelection("64 kbps", "64"); 00278 addSelection("80 kbps", "80"); 00279 addSelection("96 kbps", "96"); 00280 addSelection("112 kbps", "112"); 00281 addSelection("128 kbps", "128"); 00282 addSelection("160 kbps", "160"); 00283 addSelection("192 kbps", "192"); 00284 addSelection("224 kbps", "224"); 00285 addSelection("256 kbps", "256"); 00286 addSelection("320 kbps", "320"); 00287 addSelection("384 kbps", "384"); 00288 setValue(13); 00289 setHelpText(QObject::tr("Sets the audio bitrate")); 00290 }; 00291 }; 00292 00293 class MPEG2audBitrateL3 : public ComboBoxSetting, public CodecParamStorage 00294 { 00295 public: 00296 MPEG2audBitrateL3(const RecordingProfile &parent) : 00297 ComboBoxSetting(this), 00298 CodecParamStorage(this, parent, "mpeg2audbitratel3") 00299 { 00300 setLabel(QObject::tr("Bitrate")); 00301 00302 addSelection("32 kbps", "32"); 00303 addSelection("40 kbps", "40"); 00304 addSelection("48 kbps", "48"); 00305 addSelection("56 kbps", "56"); 00306 addSelection("64 kbps", "64"); 00307 addSelection("80 kbps", "80"); 00308 addSelection("96 kbps", "96"); 00309 addSelection("112 kbps", "112"); 00310 addSelection("128 kbps", "128"); 00311 addSelection("160 kbps", "160"); 00312 addSelection("192 kbps", "192"); 00313 addSelection("224 kbps", "224"); 00314 addSelection("256 kbps", "256"); 00315 addSelection("320 kbps", "320"); 00316 setValue(10); 00317 setHelpText(QObject::tr("Sets the audio bitrate")); 00318 }; 00319 }; 00320 00321 class MPEG2audVolume : public SliderSetting, public CodecParamStorage 00322 { 00323 public: 00324 MPEG2audVolume(const RecordingProfile &parent) : 00325 SliderSetting(this, 0, 100, 1), 00326 CodecParamStorage(this, parent, "mpeg2audvolume") 00327 { 00328 00329 setLabel(QObject::tr("Volume (%)")); 00330 setValue(90); 00331 setHelpText(QObject::tr("Volume of the recording ")); 00332 }; 00333 }; 00334 00335 class MPEG2AudioBitrateSettings : public TriggeredConfigurationGroup 00336 { 00337 public: 00338 MPEG2AudioBitrateSettings(const RecordingProfile &parent, 00339 bool layer1, bool layer2, bool layer3, 00340 uint default_layer) : 00341 TriggeredConfigurationGroup(false, true, true, true) 00342 { 00343 const QString layers[3] = { "Layer I", "Layer II", "Layer III", }; 00344 00345 SetVertical(false); 00346 setLabel(QObject::tr("Bitrate Settings")); 00347 00348 MPEG2audType *audType = new MPEG2audType( 00349 parent, layer1, layer2, layer3); 00350 00351 addChild(audType); 00352 setTrigger(audType); 00353 00354 addTarget(layers[0], new MPEG2audBitrateL1(parent)); 00355 addTarget(layers[1], new MPEG2audBitrateL2(parent)); 00356 addTarget(layers[2], new MPEG2audBitrateL3(parent)); 00357 00358 uint desired_layer = max(min(3U, default_layer), 1U) - 1; 00359 int which = audType->getValueIndex(layers[desired_layer]); 00360 if (which >= 0) 00361 audType->setValue(which); 00362 }; 00363 }; 00364 00365 class MPEG2Language : public ComboBoxSetting, public CodecParamStorage 00366 { 00367 public: 00368 MPEG2Language(const RecordingProfile &parent) : 00369 ComboBoxSetting(this), CodecParamStorage(this, parent, "mpeg2language") 00370 { 00371 setLabel(QObject::tr("SAP/Bilingual")); 00372 00373 addSelection(QObject::tr("Main Language"), "0"); 00374 addSelection(QObject::tr("SAP Language"), "1"); 00375 addSelection(QObject::tr("Dual"), "2"); 00376 00377 setValue(0); 00378 setHelpText(QObject::tr( 00379 "Chooses the language(s) to record when " 00380 "two languages are broadcast. Only Layer II " 00381 "supports the recording of two languages (Dual)." 00382 "Requires ivtv 0.4.0 or later.")); 00383 }; 00384 }; 00385 00386 class AudioCompressionSettings : public TriggeredConfigurationGroup 00387 { 00388 public: 00389 AudioCompressionSettings(const RecordingProfile &parent, QString profName) : 00390 TriggeredConfigurationGroup(false, true, false, false) 00391 { 00392 setSaveAll(false); 00393 00394 QString labelName; 00395 if (profName.isNull()) 00396 labelName = QString(QObject::tr("Audio Quality")); 00397 else 00398 labelName = profName + "->" + QObject::tr("Audio Quality"); 00399 setName(labelName); 00400 00401 codecName = new AudioCodecName(parent); 00402 addChild(codecName); 00403 setTrigger(codecName); 00404 00405 ConfigurationGroup* params = new VerticalConfigurationGroup(false); 00406 params->setLabel("MP3"); 00407 params->addChild(new SampleRate(parent)); 00408 params->addChild(new MP3Quality(parent)); 00409 params->addChild(new BTTVVolume(parent)); 00410 addTarget("MP3", params); 00411 00412 params = new VerticalConfigurationGroup(false, false, true, true); 00413 params->setLabel("MPEG-2 Hardware Encoder"); 00414 params->addChild(new SampleRate(parent, false)); 00415 params->addChild(new MPEG2AudioBitrateSettings( 00416 parent, false, true, false, 2)); 00417 params->addChild(new MPEG2Language(parent)); 00418 params->addChild(new MPEG2audVolume(parent)); 00419 addTarget("MPEG-2 Hardware Encoder", params); 00420 00421 params = new VerticalConfigurationGroup(false); 00422 params->setLabel("Uncompressed"); 00423 params->addChild(new SampleRate(parent)); 00424 params->addChild(new BTTVVolume(parent)); 00425 addTarget("Uncompressed", params); 00426 00427 params = new VerticalConfigurationGroup(false); 00428 params->setLabel("AC3 Hardware Encoder"); 00429 addTarget("AC3 Hardware Encoder", params); 00430 00431 params = new VerticalConfigurationGroup(false); 00432 params->setLabel("AAC Hardware Encoder"); 00433 addTarget("AAC Hardware Encoder", params); 00434 00435 }; 00436 00437 void selectCodecs(QString groupType) 00438 { 00439 if (!groupType.isNull()) 00440 { 00441 if (groupType == "MPEG") 00442 codecName->addSelection("MPEG-2 Hardware Encoder"); 00443 else if (groupType == "HDPVR") 00444 { 00445 codecName->addSelection("AC3 Hardware Encoder"); 00446 codecName->addSelection("AAC Hardware Encoder"); 00447 } 00448 else 00449 { 00450 // V4L, TRANSCODE (and any undefined types) 00451 codecName->addSelection("MP3"); 00452 codecName->addSelection("Uncompressed"); 00453 } 00454 } 00455 else 00456 { 00457 codecName->addSelection("MP3"); 00458 codecName->addSelection("Uncompressed"); 00459 codecName->addSelection("MPEG-2 Hardware Encoder"); 00460 } 00461 } 00462 private: 00463 AudioCodecName* codecName; 00464 }; 00465 00466 class VideoCodecName : public ComboBoxSetting, public RecordingProfileStorage 00467 { 00468 public: 00469 VideoCodecName(const RecordingProfile &parent) : 00470 ComboBoxSetting(this), 00471 RecordingProfileStorage(this, parent, "videocodec") 00472 { 00473 setLabel(QObject::tr("Codec")); 00474 } 00475 }; 00476 00477 class RTjpegQuality : public SliderSetting, public CodecParamStorage 00478 { 00479 public: 00480 RTjpegQuality(const RecordingProfile &parent) : 00481 SliderSetting(this, 1, 255, 1), 00482 CodecParamStorage(this, parent, "rtjpegquality") 00483 { 00484 setLabel(QObject::tr("RTjpeg Quality")); 00485 setValue(170); 00486 setHelpText(QObject::tr("Higher is better quality.")); 00487 }; 00488 }; 00489 00490 class RTjpegLumaFilter : public SpinBoxSetting, public CodecParamStorage 00491 { 00492 public: 00493 RTjpegLumaFilter(const RecordingProfile &parent) : 00494 SpinBoxSetting(this, 0, 31, 1), 00495 CodecParamStorage(this, parent, "rtjpeglumafilter") 00496 { 00497 setLabel(QObject::tr("Luma filter")); 00498 setValue(0); 00499 setHelpText(QObject::tr("Lower is better.")); 00500 }; 00501 }; 00502 00503 class RTjpegChromaFilter : public SpinBoxSetting, public CodecParamStorage 00504 { 00505 public: 00506 RTjpegChromaFilter(const RecordingProfile &parent) : 00507 SpinBoxSetting(this, 0, 31, 1), 00508 CodecParamStorage(this, parent, "rtjpegchromafilter") 00509 { 00510 setLabel(QObject::tr("Chroma filter")); 00511 setValue(0); 00512 setHelpText(QObject::tr("Lower is better.")); 00513 }; 00514 }; 00515 00516 class MPEG4bitrate : public SliderSetting, public CodecParamStorage 00517 { 00518 public: 00519 MPEG4bitrate(const RecordingProfile &parent) : 00520 SliderSetting(this, 100, 8000, 100), 00521 CodecParamStorage(this, parent, "mpeg4bitrate") 00522 { 00523 setLabel(QObject::tr("Bitrate (kb/s)")); 00524 setValue(2200); 00525 setHelpText(QObject::tr("Bitrate in kilobits/second. As a guide, " 00526 "2200 kb/s is approximately 1 GB/hr.")); 00527 }; 00528 }; 00529 00530 class ScaleBitrate : public CheckBoxSetting, public CodecParamStorage 00531 { 00532 public: 00533 ScaleBitrate(const RecordingProfile &parent) : 00534 CheckBoxSetting(this), 00535 CodecParamStorage(this, parent, "scalebitrate") 00536 { 00537 setLabel(QObject::tr("Scale bitrate for frame size")); 00538 setValue(true); 00539 setHelpText(QObject::tr("If set, the bitrate specified will be used " 00540 "for 640x480. If other resolutions are used, the " 00541 "bitrate will be scaled appropriately.")); 00542 }; 00543 }; 00544 00545 class MPEG4MinQuality : public SliderSetting, public CodecParamStorage 00546 { 00547 public: 00548 MPEG4MinQuality(const RecordingProfile &parent) : 00549 SliderSetting(this, 1, 31, 1), 00550 CodecParamStorage(this, parent, "mpeg4minquality") 00551 { 00552 setLabel(QObject::tr("Minimum quality")); 00553 setValue(15); 00554 setHelpText(QObject::tr("Modifying the default may have severe " 00555 "consequences.")); 00556 }; 00557 }; 00558 00559 class MPEG4MaxQuality : public SliderSetting, public CodecParamStorage 00560 { 00561 public: 00562 MPEG4MaxQuality(const RecordingProfile &parent) : 00563 SliderSetting(this, 1, 31, 1), 00564 CodecParamStorage(this, parent, "mpeg4maxquality") 00565 { 00566 setLabel(QObject::tr("Maximum quality")); 00567 setValue(2); 00568 setHelpText(QObject::tr("Modifying the default may have severe " 00569 "consequences.")); 00570 }; 00571 }; 00572 00573 class MPEG4QualDiff : public SliderSetting, public CodecParamStorage 00574 { 00575 public: 00576 MPEG4QualDiff(const RecordingProfile &parent) : 00577 SliderSetting(this, 1, 31, 1), 00578 CodecParamStorage(this, parent, "mpeg4qualdiff") 00579 { 00580 00581 setLabel(QObject::tr("Max quality difference between frames")); 00582 setValue(3); 00583 setHelpText(QObject::tr("Modifying the default may have severe " 00584 "consequences.")); 00585 }; 00586 }; 00587 00588 class MPEG4OptionIDCT : public CheckBoxSetting, public CodecParamStorage 00589 { 00590 public: 00591 MPEG4OptionIDCT(const RecordingProfile &parent) : 00592 CheckBoxSetting(this), 00593 CodecParamStorage(this, parent, "mpeg4optionidct") 00594 { 00595 setLabel(QObject::tr("Enable interlaced DCT encoding")); 00596 setValue(false); 00597 setHelpText(QObject::tr("If set, the MPEG4 encoder will use " 00598 "interlaced DCT encoding. You may want this when encoding " 00599 "interlaced video; however, this is experimental and may " 00600 "cause damaged video.")); 00601 }; 00602 }; 00603 00604 class MPEG4OptionIME : public CheckBoxSetting, public CodecParamStorage 00605 { 00606 public: 00607 MPEG4OptionIME(const RecordingProfile &parent) : 00608 CheckBoxSetting(this), 00609 CodecParamStorage(this, parent, "mpeg4optionime") 00610 { 00611 setLabel(QObject::tr("Enable interlaced motion estimation")); 00612 setValue(false); 00613 setHelpText(QObject::tr("If set, the MPEG4 encoder will use " 00614 "interlaced motion estimation. You may want this when " 00615 "encoding interlaced video; however, this is experimental " 00616 "and may cause damaged video.")); 00617 }; 00618 }; 00619 00620 class MPEG4OptionVHQ : public CheckBoxSetting, public CodecParamStorage 00621 { 00622 public: 00623 MPEG4OptionVHQ(const RecordingProfile &parent) : 00624 CheckBoxSetting(this), 00625 CodecParamStorage(this, parent, "mpeg4optionvhq") 00626 { 00627 setLabel(QObject::tr("Enable high-quality encoding")); 00628 setValue(false); 00629 setHelpText(QObject::tr("If set, the MPEG4 encoder will use " 00630 "'high-quality' encoding options. This requires much " 00631 "more processing, but can result in better video.")); 00632 }; 00633 }; 00634 00635 class MPEG4Option4MV : public CheckBoxSetting, public CodecParamStorage 00636 { 00637 public: 00638 MPEG4Option4MV(const RecordingProfile &parent) : 00639 CheckBoxSetting(this), 00640 CodecParamStorage(this, parent, "mpeg4option4mv") 00641 { 00642 setLabel(QObject::tr("Enable 4MV encoding")); 00643 setValue(false); 00644 setHelpText(QObject::tr("If set, the MPEG4 encoder will use '4MV' " 00645 "motion-vector encoding. This requires " 00646 "much more processing, but can result in better " 00647 "video. It is highly recommended that the HQ option is " 00648 "enabled if 4MV is enabled.")); 00649 }; 00650 }; 00651 00652 class EncodingThreadCount : public SliderSetting, public CodecParamStorage 00653 { 00654 public: 00655 EncodingThreadCount(const RecordingProfile &parent) : 00656 SliderSetting(this, 1, 8, 1), 00657 CodecParamStorage(this, parent, "encodingthreadcount") 00658 { 00659 00660 setLabel(QObject::tr("Number of threads")); 00661 setValue(1); 00662 setHelpText( 00663 QObject::tr("Threads to use for software encoding.") + " " + 00664 QObject::tr("Set to a value less than or equal to the " 00665 "number of processors on the backend that " 00666 "will be doing the encoding.")); 00667 }; 00668 }; 00669 00670 class AverageBitrate : public SliderSetting, public CodecParamStorage 00671 { 00672 public: 00673 AverageBitrate(const RecordingProfile &parent, 00674 QString setting = "mpeg2bitrate", 00675 uint min_br = 1000, uint max_br = 16000, 00676 uint default_br = 4500, uint increment = 100, 00677 QString label = QString::null) : 00678 SliderSetting(this, min_br, max_br, increment), 00679 CodecParamStorage(this, parent, setting) 00680 { 00681 if (label.isEmpty()) 00682 label = QObject::tr("Avg. Bitrate (kb/s)"); 00683 setLabel(label); 00684 setValue(default_br); 00685 setHelpText(QObject::tr( 00686 "Average bitrate in kilobits/second. As a guide, " 00687 "2200 kb/s is approximately 1 GB/hour.")); 00688 }; 00689 }; 00690 00691 class PeakBitrate : public SliderSetting, public CodecParamStorage 00692 { 00693 public: 00694 PeakBitrate(const RecordingProfile &parent, 00695 QString setting = "mpeg2maxbitrate", 00696 uint min_br = 1000, uint max_br = 16000, 00697 uint default_br = 6000, uint increment = 100, 00698 QString label = QString::null) : 00699 SliderSetting(this, min_br, max_br, increment), 00700 CodecParamStorage(this, parent, setting) 00701 { 00702 if (label.isEmpty()) 00703 label = QObject::tr("Max. Bitrate (kb/s)"); 00704 setLabel(label); 00705 setValue(default_br); 00706 setHelpText(QObject::tr("Maximum bitrate in kilobits/second. " 00707 "As a guide, 2200 kb/s is approximately 1 GB/hour.")); 00708 }; 00709 }; 00710 00711 class MPEG2streamType : public ComboBoxSetting, public CodecParamStorage 00712 { 00713 public: 00714 MPEG2streamType(const RecordingProfile &parent) : 00715 ComboBoxSetting(this), 00716 CodecParamStorage(this, parent, "mpeg2streamtype") 00717 { 00718 setLabel(QObject::tr("Stream Type")); 00719 00720 addSelection("MPEG-2 PS"); 00721 addSelection("MPEG-2 TS"); 00722 addSelection("MPEG-1 VCD"); 00723 addSelection("PES AV"); 00724 addSelection("PES V"); 00725 addSelection("PES A"); 00726 addSelection("DVD"); 00727 addSelection("DVD-Special 1"); 00728 addSelection("DVD-Special 2"); 00729 setValue(0); 00730 setHelpText(QObject::tr("Sets the type of stream generated by " 00731 "your PVR.")); 00732 }; 00733 }; 00734 00735 class MPEG2aspectRatio : public ComboBoxSetting, public CodecParamStorage 00736 { 00737 public: 00738 MPEG2aspectRatio(const RecordingProfile &parent) : 00739 ComboBoxSetting(this), 00740 CodecParamStorage(this, parent, "mpeg2aspectratio") 00741 { 00742 setLabel(QObject::tr("Aspect Ratio")); 00743 00744 addSelection(QObject::tr("Square"), "Square"); 00745 addSelection("4:3"); 00746 addSelection("16:9"); 00747 addSelection("2.21:1"); 00748 setValue(1); 00749 setHelpText(QObject::tr("Sets the aspect ratio of stream generated " 00750 "by your PVR.")); 00751 }; 00752 }; 00753 00754 class HardwareMJPEGQuality : public SliderSetting, public CodecParamStorage 00755 { 00756 public: 00757 HardwareMJPEGQuality(const RecordingProfile &parent) : 00758 SliderSetting(this, 0, 100, 1), 00759 CodecParamStorage(this, parent, "hardwaremjpegquality") 00760 { 00761 setLabel(QObject::tr("Quality")); 00762 setValue(100); 00763 }; 00764 }; 00765 00766 class HardwareMJPEGHDecimation : public ComboBoxSetting, 00767 public CodecParamStorage 00768 { 00769 public: 00770 HardwareMJPEGHDecimation(const RecordingProfile &parent) : 00771 ComboBoxSetting(this), 00772 CodecParamStorage(this, parent, "hardwaremjpeghdecimation") 00773 { 00774 setLabel(QObject::tr("Horizontal Decimation")); 00775 addSelection("1"); 00776 addSelection("2"); 00777 addSelection("4"); 00778 setValue(2); 00779 }; 00780 }; 00781 00782 class HardwareMJPEGVDecimation : public ComboBoxSetting, 00783 public CodecParamStorage 00784 { 00785 public: 00786 HardwareMJPEGVDecimation(const RecordingProfile &parent) : 00787 ComboBoxSetting(this), 00788 CodecParamStorage(this, parent, "hardwaremjpegvdecimation") { 00789 setLabel(QObject::tr("Vertical Decimation")); 00790 addSelection("1"); 00791 addSelection("2"); 00792 addSelection("4"); 00793 setValue(2); 00794 }; 00795 }; 00796 00797 class VideoCompressionSettings : public TriggeredConfigurationGroup 00798 { 00799 public: 00800 VideoCompressionSettings(const RecordingProfile &parent, QString profName) : 00801 TriggeredConfigurationGroup(false, true, false, false) 00802 { 00803 QString labelName; 00804 if (profName.isNull()) 00805 labelName = QObject::tr("Video Compression"); 00806 else 00807 labelName = profName + "->" + QObject::tr("Video Compression"); 00808 setName(labelName); 00809 00810 codecName = new VideoCodecName(parent); 00811 addChild(codecName); 00812 setTrigger(codecName); 00813 00814 ConfigurationGroup* params = new VerticalConfigurationGroup(); 00815 params->setLabel(QObject::tr("RTjpeg Parameters")); 00816 params->addChild(new RTjpegQuality(parent)); 00817 params->addChild(new RTjpegLumaFilter(parent)); 00818 params->addChild(new RTjpegChromaFilter(parent)); 00819 00820 addTarget("RTjpeg", params); 00821 00822 params = new VerticalConfigurationGroup(false); 00823 params->setLabel(QObject::tr("MPEG-4 Parameters")); 00824 params->addChild(new MPEG4bitrate(parent)); 00825 params->addChild(new MPEG4MaxQuality(parent)); 00826 params->addChild(new MPEG4MinQuality(parent)); 00827 params->addChild(new MPEG4QualDiff(parent)); 00828 params->addChild(new ScaleBitrate(parent)); 00829 00830 HorizontalConfigurationGroup *hq; 00831 hq = new HorizontalConfigurationGroup(false, false); 00832 hq->addChild(new MPEG4OptionVHQ(parent)); 00833 hq->addChild(new MPEG4Option4MV(parent)); 00834 params->addChild(hq); 00835 00836 HorizontalConfigurationGroup *inter; 00837 inter = new HorizontalConfigurationGroup(false, false); 00838 inter->addChild(new MPEG4OptionIDCT(parent)); 00839 inter->addChild(new MPEG4OptionIME(parent)); 00840 params->addChild(inter); 00841 #ifdef USING_FFMPEG_THREADS 00842 params->addChild(new EncodingThreadCount(parent)); 00843 #endif 00844 addTarget("MPEG-4", params); 00845 00846 params = new VerticalConfigurationGroup(false); 00847 params->setLabel(QObject::tr("MPEG-2 Parameters")); 00848 params->addChild(new AverageBitrate(parent)); 00849 params->addChild(new ScaleBitrate(parent)); 00850 //params->addChild(new MPEG4MaxQuality(parent)); 00851 //params->addChild(new MPEG4MinQuality(parent)); 00852 //params->addChild(new MPEG4QualDiff(parent)); 00853 //params->addChild(new MPEG4OptionVHQ(parent)); 00854 //params->addChild(new MPEG4Option4MV(parent)); 00855 #ifdef USING_FFMPEG_THREADS 00856 params->addChild(new EncodingThreadCount(parent)); 00857 #endif 00858 addTarget("MPEG-2", params); 00859 00860 params = new VerticalConfigurationGroup(); 00861 params->setLabel(QObject::tr("Hardware MJPEG Parameters")); 00862 params->addChild(new HardwareMJPEGQuality(parent)); 00863 params->addChild(new HardwareMJPEGHDecimation(parent)); 00864 params->addChild(new HardwareMJPEGVDecimation(parent)); 00865 00866 addTarget("Hardware MJPEG", params); 00867 00868 params = new VerticalConfigurationGroup(false); 00869 params->setLabel(QObject::tr("MPEG-2 Hardware Encoder")); 00870 params->addChild(new MPEG2streamType(parent)); 00871 params->addChild(new MPEG2aspectRatio(parent)); 00872 params->addChild(new AverageBitrate(parent)); 00873 params->addChild(new PeakBitrate(parent)); 00874 00875 addTarget("MPEG-2 Hardware Encoder", params); 00876 00877 params = new VerticalConfigurationGroup(false); 00878 params->setLabel(QObject::tr("MPEG-4 AVC Hardware Encoder")); 00879 ConfigurationGroup *h0 = new HorizontalConfigurationGroup( 00880 true, false, true, true); 00881 h0->setLabel(QObject::tr("Low Resolution")); 00882 h0->addChild(new AverageBitrate(parent, "low_mpeg4avgbitrate", 00883 1000, 13500, 4500, 500)); 00884 h0->addChild(new PeakBitrate(parent, "low_mpeg4peakbitrate", 00885 1100, 20200, 6000, 500)); 00886 params->addChild(h0); 00887 ConfigurationGroup *h1 = new HorizontalConfigurationGroup( 00888 true, false, true, true); 00889 h1->setLabel(QObject::tr("Medium Resolution")); 00890 h1->addChild(new AverageBitrate(parent, "medium_mpeg4avgbitrate", 00891 1000, 13500, 9000, 500)); 00892 h1->addChild(new PeakBitrate(parent, "medium_mpeg4peakbitrate", 00893 1100, 20200, 11000, 500)); 00894 params->addChild(h1); 00895 ConfigurationGroup *h2 = new HorizontalConfigurationGroup( 00896 true, false, true, true); 00897 h2->setLabel(QObject::tr("High Resolution")); 00898 h2->addChild(new AverageBitrate(parent, "high_mpeg4avgbitrate", 00899 1000, 13500, 13500, 500)); 00900 h2->addChild(new PeakBitrate(parent, "high_mpeg4peakbitrate", 00901 1100, 20200, 20200, 500)); 00902 params->addChild(h2); 00903 addTarget("MPEG-4 AVC Hardware Encoder", params); 00904 } 00905 00906 void selectCodecs(QString groupType) 00907 { 00908 if (!groupType.isNull()) 00909 { 00910 if (groupType == "HDPVR") 00911 codecName->addSelection("MPEG-4 AVC Hardware Encoder"); 00912 else if (groupType == "MPEG") 00913 codecName->addSelection("MPEG-2 Hardware Encoder"); 00914 else if (groupType == "MJPEG") 00915 codecName->addSelection("Hardware MJPEG"); 00916 else if (groupType == "GO7007") 00917 { 00918 codecName->addSelection("MPEG-4"); 00919 codecName->addSelection("MPEG-2"); 00920 } 00921 else 00922 { 00923 // V4L, TRANSCODE (and any undefined types) 00924 codecName->addSelection("RTjpeg"); 00925 codecName->addSelection("MPEG-4"); 00926 } 00927 } 00928 else 00929 { 00930 codecName->addSelection("RTjpeg"); 00931 codecName->addSelection("MPEG-4"); 00932 codecName->addSelection("Hardware MJPEG"); 00933 codecName->addSelection("MPEG-2 Hardware Encoder"); 00934 } 00935 } 00936 00937 private: 00938 VideoCodecName* codecName; 00939 }; 00940 00941 class AutoTranscode : public CheckBoxSetting, public CodecParamStorage 00942 { 00943 public: 00944 AutoTranscode(const RecordingProfile &parent) : 00945 CheckBoxSetting(this), 00946 CodecParamStorage(this, parent, "autotranscode") 00947 { 00948 setLabel(QObject::tr("Enable auto-transcode after recording")); 00949 setValue(false); 00950 setHelpText(QObject::tr("Automatically transcode when a recording is " 00951 "made using this profile and the recording's " 00952 "schedule is configured to allow transcoding.")); 00953 }; 00954 }; 00955 00956 class TranscodeResize : public CheckBoxSetting, public CodecParamStorage 00957 { 00958 public: 00959 TranscodeResize(const RecordingProfile &parent) : 00960 CheckBoxSetting(this), 00961 CodecParamStorage(this, parent, "transcoderesize") 00962 { 00963 setLabel(QObject::tr("Resize video while transcoding")); 00964 setValue(false); 00965 setHelpText(QObject::tr("Allows the transcoder to " 00966 "resize the video during transcoding.")); 00967 }; 00968 }; 00969 00970 class TranscodeLossless : public CheckBoxSetting, public CodecParamStorage 00971 { 00972 public: 00973 TranscodeLossless(const RecordingProfile &parent) : 00974 CheckBoxSetting(this), 00975 CodecParamStorage(this, parent, "transcodelossless") 00976 { 00977 setLabel(QObject::tr("Lossless transcoding")); 00978 setValue(false); 00979 setHelpText(QObject::tr("Only reencode where absolutely needed " 00980 "(normally only around cutpoints). Otherwise " 00981 "keep audio and video formats identical to " 00982 "the source. This should result in the " 00983 "highest quality, but won't save as much " 00984 "space.")); 00985 }; 00986 }; 00987 00988 class RecordingType : public ComboBoxSetting, public CodecParamStorage 00989 { 00990 public: 00991 RecordingType(const RecordingProfile &parent) : 00992 ComboBoxSetting(this), CodecParamStorage(this, parent, "recordingtype") 00993 { 00994 setLabel(QObject::tr("Recording Type")); 00995 00996 QString msg = QObject::tr( 00997 "This option allows you to filter out unwanted streams. " 00998 "'Normal' will record all relevant streams including " 00999 "interactive television data. 'TV Only' will record only " 01000 "audio, video and subtitle streams. "); 01001 setHelpText(msg); 01002 01003 addSelection(QObject::tr("Normal"), "all"); 01004 addSelection(QObject::tr("TV Only"), "tv"); 01005 addSelection(QObject::tr("Audio Only"), "audio"); 01006 setValue(0); 01007 }; 01008 }; 01009 01010 class RecordFullTSStream : public ComboBoxSetting, public CodecParamStorage 01011 { 01012 public: 01013 RecordFullTSStream(const RecordingProfile &parent) : 01014 ComboBoxSetting(this), CodecParamStorage(this, parent, "recordmpts") 01015 { 01016 setLabel(QObject::tr("Record Full TS?")); 01017 01018 QString msg = QObject::tr( 01019 "If set, extra files will be created for each recording with " 01020 "the name of the recording followed by '.ts' and a number. " 01021 "These extra files represent the full contents of the transport " 01022 "stream used to generate the recording."); 01023 setHelpText(msg); 01024 01025 addSelection(QObject::tr("Yes"), "1"); 01026 addSelection(QObject::tr("No"), "0"); 01027 setValue(1); 01028 }; 01029 }; 01030 01031 class TranscodeFilters : public LineEditSetting, public CodecParamStorage 01032 { 01033 public: 01034 TranscodeFilters(const RecordingProfile &parent) : 01035 LineEditSetting(this), 01036 CodecParamStorage(this, parent, "transcodefilters") 01037 { 01038 setLabel(QObject::tr("Custom filters")); 01039 setHelpText(QObject::tr("Filters used when transcoding with this " 01040 "profile. This value must be blank to perform " 01041 "lossless transcoding. Format: " 01042 "[[<filter>=<options>,]...]" 01043 )); 01044 }; 01045 }; 01046 01047 class ImageSize : public VerticalConfigurationGroup 01048 { 01049 public: 01050 class Width : public SpinBoxSetting, public CodecParamStorage 01051 { 01052 public: 01053 Width(const RecordingProfile &parent, 01054 uint defaultwidth, uint maxwidth, 01055 bool transcoding = false) : 01056 SpinBoxSetting(this, transcoding ? 0 : 160, 01057 maxwidth, 16, false, 01058 transcoding ? QObject::tr("Auto") : ""), 01059 CodecParamStorage(this, parent, "width") 01060 { 01061 setLabel(QObject::tr("Width")); 01062 setValue(defaultwidth); 01063 01064 QString help = (transcoding) ? 01065 QObject::tr("If the width is set to 'Auto', the width " 01066 "will be calculated based on the height and " 01067 "the recording's physical aspect ratio.") : 01068 QObject::tr("Width to use for encoding. " 01069 "Note: PVR-x50 cards may produce ghosting if " 01070 "this is not set to 720 or 768 for NTSC and " 01071 "PAL, respectively."); 01072 01073 setHelpText(help); 01074 }; 01075 }; 01076 01077 class Height: public SpinBoxSetting, public CodecParamStorage 01078 { 01079 public: 01080 Height(const RecordingProfile &parent, 01081 uint defaultheight, uint maxheight, 01082 bool transcoding = false): 01083 SpinBoxSetting(this, transcoding ? 0 : 160, 01084 maxheight, 16, false, 01085 transcoding ? QObject::tr("Auto") : QString()), 01086 CodecParamStorage(this, parent, "height") 01087 { 01088 setLabel(QObject::tr("Height")); 01089 setValue(defaultheight); 01090 01091 QString help = (transcoding) ? 01092 QObject::tr("If the height is set to 'Auto', the height " 01093 "will be calculated based on the width and " 01094 "the recording's physical aspect ratio.") : 01095 QObject::tr("Height to use for encoding. " 01096 "Note: PVR-x50 cards may produce ghosting if " 01097 "this is not set to 480 or 576 for NTSC and " 01098 "PAL, respectively."); 01099 01100 setHelpText(help); 01101 }; 01102 }; 01103 01104 ImageSize(const RecordingProfile &parent, 01105 QString tvFormat, QString profName) : 01106 VerticalConfigurationGroup(false, true, false, false) 01107 { 01108 ConfigurationGroup* imgSize = new HorizontalConfigurationGroup(false); 01109 QString labelName; 01110 if (profName.isNull()) 01111 labelName = QObject::tr("Image size"); 01112 else 01113 labelName = profName + "->" + QObject::tr("Image size"); 01114 setLabel(labelName); 01115 01116 QSize defaultsize(768, 576), maxsize(768, 576); 01117 bool transcoding = profName.left(11) == "Transcoders"; 01118 bool ivtv = profName.left(20) == "IVTV MPEG-2 Encoders"; 01119 01120 if (transcoding) 01121 { 01122 maxsize = QSize(1920, 1088); 01123 if (tvFormat.toLower() == "ntsc" || tvFormat.toLower() == "atsc") 01124 defaultsize = QSize(480, 480); 01125 else 01126 defaultsize = QSize(480, 576); 01127 } 01128 else if (tvFormat.toLower().left(4) == "ntsc") 01129 { 01130 maxsize = QSize(720, 480); 01131 defaultsize = (ivtv) ? QSize(720, 480) : QSize(480, 480); 01132 } 01133 else if (tvFormat.toLower() == "atsc") 01134 { 01135 maxsize = QSize(1920, 1088); 01136 defaultsize = QSize(1920, 1088); 01137 } 01138 else 01139 { 01140 maxsize = QSize(768, 576); 01141 defaultsize = (ivtv) ? QSize(720, 576) : QSize(480, 576); 01142 } 01143 01144 imgSize->addChild(new Width(parent, defaultsize.width(), 01145 maxsize.width(), transcoding)); 01146 imgSize->addChild(new Height(parent, defaultsize.height(), 01147 maxsize.height(), transcoding)); 01148 01149 addChild(imgSize); 01150 }; 01151 }; 01152 01153 typedef enum { 01154 RPPopup_OK = 0, 01155 RPPopup_CANCEL, 01156 RPPopup_DELETE 01157 } RPPopupResult; 01158 01159 class RecordingProfilePopup 01160 { 01161 public: 01162 static RPPopupResult showPopup(MythMainWindow *parent, QString title, 01163 QString message, QString& text) 01164 { 01165 MythPopupBox *popup = new MythPopupBox( 01166 parent, title.toLatin1().constData()); 01167 popup->addLabel(message); 01168 01169 MythLineEdit *textEdit = new MythLineEdit(popup, "chooseEdit"); 01170 textEdit->setText(text); 01171 popup->addWidget(textEdit); 01172 01173 popup->addButton(QObject::tr("OK"), popup, SLOT(accept())); 01174 popup->addButton(QObject::tr("Cancel"), popup, SLOT(reject())); 01175 01176 textEdit->setFocus(); 01177 01178 bool ok = (MythDialog::Accepted == popup->ExecPopup()); 01179 if (ok) 01180 text = textEdit->text(); 01181 01182 popup->hide(); 01183 popup->deleteLater(); 01184 01185 return (ok) ? RPPopup_OK : RPPopup_CANCEL; 01186 } 01187 }; 01188 01189 // id and name will be deleted by ConfigurationGroup's destructor 01190 RecordingProfile::RecordingProfile(QString profName) 01191 : id(new ID()), name(new Name(*this)), 01192 imageSize(NULL), videoSettings(NULL), 01193 audioSettings(NULL), profileName(profName), 01194 isEncoder(true) 01195 { 01196 // This must be first because it is needed to load/save the other settings 01197 addChild(id); 01198 01199 ConfigurationGroup* profile = new VerticalConfigurationGroup(false); 01200 QString labelName; 01201 if (profName.isNull()) 01202 labelName = QString(QObject::tr("Profile")); 01203 else 01204 labelName = profName + "->" + QObject::tr("Profile"); 01205 profile->setLabel(labelName); 01206 profile->addChild(name); 01207 01208 tr_filters = NULL; 01209 tr_lossless = NULL; 01210 tr_resize = NULL; 01211 01212 if (!profName.isEmpty()) 01213 { 01214 if (profName.left(11) == "Transcoders") 01215 { 01216 tr_filters = new TranscodeFilters(*this); 01217 tr_lossless = new TranscodeLossless(*this); 01218 tr_resize = new TranscodeResize(*this); 01219 profile->addChild(tr_filters); 01220 profile->addChild(tr_lossless); 01221 profile->addChild(tr_resize); 01222 } 01223 else 01224 profile->addChild(new AutoTranscode(*this)); 01225 } 01226 else 01227 { 01228 tr_filters = new TranscodeFilters(*this); 01229 tr_lossless = new TranscodeLossless(*this); 01230 tr_resize = new TranscodeResize(*this); 01231 profile->addChild(tr_filters); 01232 profile->addChild(tr_lossless); 01233 profile->addChild(tr_resize); 01234 profile->addChild(new AutoTranscode(*this)); 01235 } 01236 01237 addChild(profile); 01238 }; 01239 01240 void RecordingProfile::ResizeTranscode(bool resize) 01241 { 01242 MythWizard *wizard = (MythWizard *)dialog; 01243 if (!wizard) 01244 return; 01245 //page '1' is the Image Size page 01246 QWidget *size_page = wizard->page(1); 01247 wizard->setAppropriate(size_page, resize); 01248 } 01249 01250 void RecordingProfile::SetLosslessTranscode(bool lossless) 01251 { 01252 MythWizard *wizard = (MythWizard *)dialog; 01253 if (!wizard) 01254 return; 01255 01256 bool show_size = (lossless) ? false : tr_resize->boolValue(); 01257 wizard->setAppropriate(wizard->page(1), show_size); 01258 wizard->setAppropriate(wizard->page(2), ! lossless); 01259 wizard->setAppropriate(wizard->page(3), ! lossless); 01260 tr_resize->setEnabled(! lossless); 01261 wizard->setNextEnabled(wizard->page(0), ! lossless); 01262 wizard->setFinishEnabled(wizard->page(0), lossless); 01263 01264 if (tr_filters) 01265 tr_filters->setEnabled(!lossless); 01266 } 01267 01268 void RecordingProfile::loadByID(int profileId) 01269 { 01270 MSqlQuery result(MSqlQuery::InitCon()); 01271 result.prepare( 01272 "SELECT cardtype, profilegroups.name " 01273 "FROM profilegroups, recordingprofiles " 01274 "WHERE profilegroups.id = recordingprofiles.profilegroup AND " 01275 " recordingprofiles.id = :PROFILEID"); 01276 result.bindValue(":PROFILEID", profileId); 01277 01278 QString type; 01279 QString name; 01280 if (!result.exec()) 01281 { 01282 MythDB::DBError("RecordingProfile::loadByID -- cardtype", result); 01283 } 01284 else if (result.next()) 01285 { 01286 type = result.value(0).toString(); 01287 name = result.value(1).toString(); 01288 } 01289 01290 CompleteLoad(profileId, type, name); 01291 } 01292 01293 void RecordingProfile::FiltersChanged(const QString &val) 01294 { 01295 if (!tr_filters || !tr_lossless) 01296 return; 01297 01298 // If there are filters, we cannot do lossless transcoding 01299 if (!val.trimmed().isEmpty()) 01300 { 01301 tr_lossless->setValue(false); 01302 tr_lossless->setEnabled(false); 01303 } 01304 else 01305 { 01306 tr_lossless->setEnabled(true); 01307 } 01308 } 01309 01310 bool RecordingProfile::loadByType(const QString &name, const QString &cardtype) 01311 { 01312 QString hostname = gCoreContext->GetHostName().toLower(); 01313 uint profileId = 0; 01314 01315 MSqlQuery result(MSqlQuery::InitCon()); 01316 result.prepare( 01317 "SELECT recordingprofiles.id, profilegroups.hostname, " 01318 " profilegroups.is_default " 01319 "FROM recordingprofiles, profilegroups " 01320 "WHERE profilegroups.id = recordingprofiles.profilegroup AND " 01321 " profilegroups.cardtype = :CARDTYPE AND " 01322 " recordingprofiles.name = :NAME"); 01323 result.bindValue(":CARDTYPE", cardtype); 01324 result.bindValue(":NAME", name); 01325 01326 if (!result.exec()) 01327 { 01328 MythDB::DBError("RecordingProfile::loadByType()", result); 01329 return false; 01330 } 01331 01332 while (result.next()) 01333 { 01334 if (result.value(1).toString().toLower() == hostname) 01335 { 01336 profileId = result.value(0).toUInt(); 01337 } 01338 else if (result.value(2).toInt() == 1) 01339 { 01340 profileId = result.value(0).toUInt(); 01341 break; 01342 } 01343 } 01344 01345 if (profileId) 01346 { 01347 CompleteLoad(profileId, cardtype, name); 01348 return true; 01349 } 01350 01351 return false; 01352 } 01353 01354 bool RecordingProfile::loadByGroup(const QString &name, const QString &group) 01355 { 01356 MSqlQuery result(MSqlQuery::InitCon()); 01357 result.prepare( 01358 "SELECT recordingprofiles.id, cardtype " 01359 "FROM recordingprofiles, profilegroups " 01360 "WHERE recordingprofiles.profilegroup = profilegroups.id AND " 01361 " profilegroups.name = :GROUPNAME AND " 01362 " recordingprofiles.name = :NAME"); 01363 result.bindValue(":GROUPNAME", group); 01364 result.bindValue(":NAME", name); 01365 01366 if (!result.exec()) 01367 { 01368 MythDB::DBError("RecordingProfile::loadByGroup()", result); 01369 return false; 01370 } 01371 01372 if (result.next()) 01373 { 01374 uint profileId = result.value(0).toUInt(); 01375 QString type = result.value(1).toString(); 01376 01377 CompleteLoad(profileId, type, name); 01378 return true; 01379 } 01380 01381 return false; 01382 } 01383 01384 void RecordingProfile::CompleteLoad(int profileId, const QString &type, 01385 const QString &name) 01386 { 01387 if (profileName.isEmpty()) 01388 profileName = name; 01389 01390 isEncoder = CardUtil::IsEncoder(type); 01391 01392 if (isEncoder) 01393 { 01394 QString tvFormat = gCoreContext->GetSetting("TVFormat"); 01395 if (type.toUpper() != "HDPVR") 01396 addChild(new ImageSize(*this, tvFormat, profileName)); 01397 01398 videoSettings = new VideoCompressionSettings(*this, profileName); 01399 addChild(videoSettings); 01400 01401 audioSettings = new AudioCompressionSettings(*this, profileName); 01402 addChild(audioSettings); 01403 01404 if (!profileName.isEmpty() && profileName.left(11) == "Transcoders") 01405 { 01406 connect(tr_resize, SIGNAL(valueChanged (bool)), 01407 this, SLOT( ResizeTranscode(bool))); 01408 connect(tr_lossless, SIGNAL(valueChanged (bool)), 01409 this, SLOT( SetLosslessTranscode(bool))); 01410 connect(tr_filters, SIGNAL(valueChanged(const QString&)), 01411 this, SLOT(FiltersChanged(const QString&))); 01412 } 01413 } 01414 else if (type.toUpper() == "DVB") 01415 { 01416 addChild(new RecordingType(*this)); 01417 } 01418 else if (type.toUpper() == "ASI") 01419 { 01420 addChild(new RecordFullTSStream(*this)); 01421 } 01422 01423 id->setValue(profileId); 01424 Load(); 01425 } 01426 01427 void RecordingProfile::setCodecTypes() 01428 { 01429 if (videoSettings) 01430 videoSettings->selectCodecs(groupType()); 01431 if (audioSettings) 01432 audioSettings->selectCodecs(groupType()); 01433 } 01434 01435 DialogCode RecordingProfile::exec(void) 01436 { 01437 MythDialog *dialog = dialogWidget( 01438 GetMythMainWindow(), "Recording Profile"); 01439 01440 dialog->Show(); 01441 if (tr_lossless) 01442 SetLosslessTranscode(tr_lossless->boolValue()); 01443 if (tr_resize) 01444 ResizeTranscode(tr_resize->boolValue()); 01445 // Filters should be set last because it might disable lossless 01446 if (tr_filters) 01447 FiltersChanged(tr_filters->getValue()); 01448 01449 DialogCode ret = dialog->exec(); 01450 01451 dialog->deleteLater(); 01452 01453 return ret; 01454 } 01455 01456 void RecordingProfileEditor::open(int id) 01457 { 01458 if (id) 01459 { 01460 QString profName = RecordingProfile::getName(id); 01461 if (profName.isNull()) 01462 profName = labelName; 01463 else 01464 profName = labelName + "->" + profName; 01465 RecordingProfile* profile = new RecordingProfile(profName); 01466 01467 profile->loadByID(id); 01468 profile->setCodecTypes(); 01469 01470 if (profile->exec() == QDialog::Accepted) 01471 profile->Save(); 01472 delete profile; 01473 } 01474 else 01475 { 01476 QString profName; 01477 RPPopupResult result = RecordingProfilePopup::showPopup( 01478 GetMythMainWindow(), 01479 tr("Add Recording Profile"), 01480 tr("Enter the name of the new profile"), profName); 01481 if (result == RPPopup_CANCEL) 01482 return; 01483 01484 MSqlQuery query(MSqlQuery::InitCon()); 01485 query.prepare( 01486 "INSERT INTO recordingprofiles " 01487 "(name, videocodec, audiocodec, profilegroup) " 01488 "VALUES " 01489 "(:NAME, :VIDEOCODEC, :AUDIOCODEC, :PROFILEGROUP);"); 01490 query.bindValue(":NAME", profName); 01491 query.bindValue(":VIDEOCODEC", "MPEG-4"); 01492 query.bindValue(":AUDIOCODEC", "MP3"); 01493 query.bindValue(":PROFILEGROUP", group); 01494 if (!query.exec()) 01495 { 01496 MythDB::DBError("RecordingProfileEditor::open", query); 01497 } 01498 else 01499 { 01500 query.prepare( 01501 "SELECT id " 01502 "FROM recordingprofiles " 01503 "WHERE name = :NAME AND profilegroup = :PROFILEGROUP;"); 01504 query.bindValue(":NAME", profName); 01505 query.bindValue(":PROFILEGROUP", group); 01506 if (!query.exec()) 01507 { 01508 MythDB::DBError("RecordingProfileEditor::open", query); 01509 } 01510 else 01511 { 01512 if (query.next()) 01513 open(query.value(0).toInt()); 01514 } 01515 } 01516 } 01517 } 01518 01519 RecordingProfileEditor::RecordingProfileEditor(int id, QString profName) : 01520 listbox(new ListBoxSetting(this)), group(id), labelName(profName) 01521 { 01522 if (!labelName.isEmpty()) 01523 listbox->setLabel(labelName); 01524 addChild(listbox); 01525 } 01526 01527 void RecordingProfileEditor::Load(void) 01528 { 01529 listbox->clearSelections(); 01530 listbox->addSelection("(Create new profile)", "0"); 01531 RecordingProfile::fillSelections(listbox, group); 01532 } 01533 01534 DialogCode RecordingProfileEditor::exec(void) 01535 { 01536 while (ConfigurationDialog::exec() == kDialogCodeAccepted) 01537 open(listbox->getValue().toInt()); 01538 01539 return kDialogCodeRejected; 01540 } 01541 01542 void RecordingProfile::fillSelections(SelectSetting *setting, int group, 01543 bool foldautodetect) 01544 { 01545 if (!group) 01546 { 01547 for (uint i = 0; !availProfiles[i].isEmpty(); i++) 01548 setting->addSelection(availProfiles[i], availProfiles[i]); 01549 return; 01550 } 01551 01552 MSqlQuery result(MSqlQuery::InitCon()); 01553 result.prepare( 01554 "SELECT name, id " 01555 "FROM recordingprofiles " 01556 "WHERE profilegroup = :GROUP " 01557 "ORDER BY id"); 01558 result.bindValue(":GROUP", group); 01559 01560 if (!result.exec()) 01561 { 01562 MythDB::DBError("RecordingProfile::fillSelections 1", result); 01563 return; 01564 } 01565 else if (!result.next()) 01566 { 01567 return; 01568 } 01569 01570 if (group == RecordingProfile::TranscoderGroup && foldautodetect) 01571 { 01572 QString id = QString::number(RecordingProfile::TranscoderAutodetect); 01573 setting->addSelection(QObject::tr("Autodetect"), id); 01574 } 01575 01576 do 01577 { 01578 QString name = result.value(0).toString(); 01579 QString id = result.value(1).toString(); 01580 01581 if (group == RecordingProfile::TranscoderGroup) 01582 { 01583 if (name == "RTjpeg/MPEG4" || name == "MPEG2") 01584 { 01585 if (!foldautodetect) 01586 { 01587 setting->addSelection( 01588 QObject::tr("Autodetect from %1").arg(name), id); 01589 } 01590 } 01591 else 01592 { 01593 setting->addSelection(name, id); 01594 } 01595 continue; 01596 } 01597 01598 setting->addSelection(name, id); 01599 } 01600 while (result.next()); 01601 } 01602 01603 QMap<int, QString> RecordingProfile::listProfiles(int group) 01604 { 01605 QMap<int, QString> profiles; 01606 01607 if (!group) 01608 { 01609 for (uint i = 0; !availProfiles[i].isEmpty(); i++) 01610 profiles[i] = availProfiles[i]; 01611 return profiles; 01612 } 01613 01614 MSqlQuery result(MSqlQuery::InitCon()); 01615 result.prepare( 01616 "SELECT name, id " 01617 "FROM recordingprofiles " 01618 "WHERE profilegroup = :GROUP " 01619 "ORDER BY id"); 01620 result.bindValue(":GROUP", group); 01621 01622 if (!result.exec()) 01623 { 01624 MythDB::DBError("RecordingProfile::fillSelections 2", result); 01625 return profiles; 01626 } 01627 else if (!result.next()) 01628 { 01629 LOG(VB_GENERAL, LOG_WARNING, 01630 "RecordingProfile::fillselections, Warning: " 01631 "Failed to locate recording id for recording group."); 01632 return profiles; 01633 } 01634 01635 if (group == RecordingProfile::TranscoderGroup) 01636 { 01637 int id = RecordingProfile::TranscoderAutodetect; 01638 profiles[id] = QObject::tr("Transcode using Autodetect"); 01639 } 01640 01641 do 01642 { 01643 QString name = result.value(0).toString(); 01644 int id = result.value(1).toInt(); 01645 01646 if (group == RecordingProfile::TranscoderGroup) 01647 { 01648 /* RTjpeg/MPEG4 and MPEG2 are used by "Autodetect". */ 01649 if (name != "RTjpeg/MPEG4" && name != "MPEG2") 01650 { 01651 QString lbl = QObject::tr("Transcode using \"%1\"").arg(name); 01652 profiles[id] = lbl; 01653 } 01654 continue; 01655 } 01656 01657 QString lbl = QObject::tr("Record using the \"%1\" profile").arg(name); 01658 profiles[id] = lbl; 01659 } while (result.next()); 01660 01661 return profiles; 01662 } 01663 01664 QString RecordingProfile::groupType(void) const 01665 { 01666 MSqlQuery result(MSqlQuery::InitCon()); 01667 result.prepare( 01668 "SELECT profilegroups.cardtype " 01669 "FROM profilegroups, recordingprofiles " 01670 "WHERE profilegroups.id = recordingprofiles.profilegroup AND " 01671 " recordingprofiles.id = :ID"); 01672 result.bindValue(":ID", getProfileNum()); 01673 01674 if (!result.exec()) 01675 MythDB::DBError("RecordingProfile::groupType", result); 01676 else if (result.next()) 01677 return result.value(0).toString(); 01678 01679 return QString::null; 01680 } 01681 01682 QString RecordingProfile::getName(int id) 01683 { 01684 MSqlQuery result(MSqlQuery::InitCon()); 01685 result.prepare( 01686 "SELECT name " 01687 "FROM recordingprofiles " 01688 "WHERE id = :ID"); 01689 01690 result.bindValue(":ID", id); 01691 01692 if (!result.exec()) 01693 MythDB::DBError("RecordingProfile::getName", result); 01694 else if (result.next()) 01695 return result.value(0).toString(); 01696 01697 return QString::null; 01698 } 01699 01700 /* vim: set expandtab tabstop=4 shiftwidth=4: */
1.7.6.1