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