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