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
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
00851
00852
00853
00854
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
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
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
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
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
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
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
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