Ticket #1945: diseqc.patch5

File diseqc.patch5, 198.5 KB (added by yeasah@…, 19 years ago)
Line 
1Index: libs/libmythtv/dvbsignalmonitor.h
2===================================================================
3--- libs/libmythtv/dvbsignalmonitor.h (revision 10186)
4+++ libs/libmythtv/dvbsignalmonitor.h (working copy)
5@@ -10,6 +10,8 @@
6
7 typedef QMap<uint,int> FilterMap;
8
9+#define RETUNE_TIMEOUT 5000
10+
11 class DVBSignalMonitor: public DTVSignalMonitor
12 {
13 Q_OBJECT
14@@ -30,6 +32,7 @@
15 void StatusSignalToNoise(const SignalMonitorValue&);
16 void StatusBitErrorRate(const SignalMonitorValue&);
17 void StatusUncorrectedBlocks(const SignalMonitorValue&);
18+ void StatusRotorPosition(const SignalMonitorValue&);
19
20 protected:
21 DVBSignalMonitor(void);
22@@ -38,6 +41,7 @@
23 virtual void UpdateValues(void);
24 void EmitDVBSignals(void);
25
26+ void RetuneMonitor(void);
27 static void *TableMonitorThread(void *param);
28 void RunTableMonitor(void);
29 void RunTableMonitorTS(void);
30@@ -52,12 +56,15 @@
31 SignalMonitorValue signalToNoise;
32 SignalMonitorValue bitErrorRate;
33 SignalMonitorValue uncorrectedBlocks;
34+ SignalMonitorValue rotorPosition;
35
36 bool useSectionReader;
37 bool dtvMonitorRunning;
38 pthread_t table_monitor_thread;
39
40 FilterMap filters; ///< PID filters for table monitoring
41+
42+ bool is_rotor_done;
43 };
44
45 #endif // DVBSIGNALMONITOR_H
46Index: libs/libmythtv/channelutil.h
47===================================================================
48--- libs/libmythtv/channelutil.h (revision 10186)
49+++ libs/libmythtv/channelutil.h (working copy)
50@@ -145,6 +145,7 @@
51 static QString GetServiceName(int chanid);
52 static int GetSourceID(int mplexid);
53 static QString GetInputName(int sourceid);
54+ static int GetInputID(int sourceid, int cardid);
55 static QString GetDTVPrivateType(uint networkid, const QString &key,
56 const QString sitype = "dvb");
57
58Index: libs/libmythtv/cardutil.h
59===================================================================
60--- libs/libmythtv/cardutil.h (revision 10186)
61+++ libs/libmythtv/cardutil.h (working copy)
62@@ -15,38 +15,6 @@
63 class CardInput;
64 typedef QMap<int,QString> InputNames;
65
66-class DVBDiSEqCInput
67-{
68- public:
69- DVBDiSEqCInput() { clearValues(); }
70- DVBDiSEqCInput(const QString &in, const QString &prt, const QString &pos)
71- : input(in), port(prt), position(pos) {}
72-
73- void clearValues(void) { input = port = position = ""; }
74-
75- QString input;
76- QString port;
77- QString position;
78-};
79-typedef QValueList<DVBDiSEqCInput> DiSEqCList;
80-
81-/// \brief all the different dvb DiSEqC devices
82-enum DISEQC_TYPES
83-{
84- DISEQC_SINGLE = 0,
85- DISEQC_MINI_2 = 1,
86- DISEQC_SWITCH_2_1_0 = 2,
87- DISEQC_SWITCH_2_1_1 = 3,
88- DISEQC_SWITCH_4_1_0 = 4,
89- DISEQC_SWITCH_4_1_1 = 5,
90- DISEQC_POSITIONER_1_2 = 6,
91- DISEQC_POSITIONER_X = 7,
92- DISEQC_POSITIONER_1_2_SWITCH_2 = 8,
93- DISEQC_POSITIONER_X_SWITCH_2 = 9,
94- DISEQC_SW21 = 10,
95- DISEQC_SW64 = 11,
96-};
97-
98 QString get_on_source(const QString&, uint, uint);
99 QString get_on_input(const QString&, uint, const QString&);
100
101@@ -163,8 +131,7 @@
102 static QString ProbeSubTypeName(uint cardid, const QString &input);
103
104 static QStringList probeInputs(QString device,
105- QString cardtype = QString::null,
106- int diseqctype = -1);
107+ QString cardtype = QString::null);
108 static void GetCardInputs(int cardid,
109 QString device,
110 QString cardtype,
111@@ -188,8 +155,8 @@
112 static QString ProbeDVBType(uint device);
113 static bool HasDVBCRCBug(uint device);
114 static uint GetMinSignalMonitoringDelay(uint device);
115- static DISEQC_TYPES GetDISEqCType(uint cardid);
116 static QString GetDeviceName(dvb_dev_type_t, uint cardnum);
117+ static InputNames configuredDVBInputs(uint cardid);
118
119 // V4L info
120 static bool hasV4L2(int videofd);
121@@ -198,11 +165,8 @@
122
123 private:
124 static QStringList probeV4LInputs(QString device);
125- static QStringList probeDVBInputs(QString device, int diseqctype = -1);
126+ static QStringList probeDVBInputs(QString device);
127 static QStringList probeChildInputs(QString device);
128-
129- static QStringList fillDVBInputs(int dvb_diseqc_type);
130- static DiSEqCList fillDVBInputsDiSEqC(int dvb_diseqc_type);
131 };
132
133 #endif //_CARDUTIL_H_
134Index: libs/libmythtv/videosource.h
135===================================================================
136--- libs/libmythtv/videosource.h (revision 10186)
137+++ libs/libmythtv/videosource.h (working copy)
138@@ -6,6 +6,10 @@
139
140 #include "settings.h"
141 #include "datadirect.h"
142+#ifdef USING_DVB
143+#include "dvbdevtree.h"
144+#include "dvbdevtree_cfg.h"
145+#endif // USING_DVB
146
147 class SignalTimeout;
148 class ChannelTimeout;
149@@ -203,7 +207,6 @@
150
151 public slots:
152 void fillSelections(const QString &device);
153- void diseqcType(const QString &diseqcType);
154
155 private:
156 QString last_device;
157@@ -381,10 +384,8 @@
158 static void fillSelections(SelectSetting* setting);
159 static void fillSelections(SelectSetting* setting, bool no_children);
160
161- void load() {
162- ConfigurationWizard::load();
163- };
164-
165+ virtual void save();
166+
167 public slots:
168 void DiSEqCPanel();
169 void analogPanel();
170@@ -421,6 +422,9 @@
171 private:
172 ID *id;
173 ParentID *parentid;
174+#ifdef USING_DVB
175+ DVBDevTree tree;
176+#endif
177 };
178
179 class CardInput;
180@@ -525,18 +529,12 @@
181 class ChildID;
182 class InputName;
183 class SourceID;
184-class DVBLNBChooser;
185-class DiSEqCPos;
186-class DiSEqCPort;
187-class LNBLofSwitch;
188-class LNBLofLo;
189-class LNBLofHi;
190
191 class CardInput: public ConfigurationWizard
192 {
193 Q_OBJECT
194 public:
195- CardInput(bool is_dvb_card);
196+ CardInput(bool is_dvb_card, int cardid);
197
198 int getInputID(void) const { return id->intValue(); };
199
200@@ -544,7 +542,6 @@
201 void loadByInput(int cardid, QString input);
202 QString getSourceName(void) const;
203
204- void fillDiseqcSettingsInput(QString _pos, QString _port);
205 void SetChildCardID(uint);
206
207 virtual void save();
208@@ -553,6 +550,7 @@
209 public slots:
210 void channelScanner();
211 void sourceFetch();
212+ void diseqcConfig();
213
214 private:
215 class ID: virtual public IntegerSetting,
216@@ -578,13 +576,10 @@
217 ChildID *childid;
218 InputName *inputname;
219 SourceID *sourceid;
220- DVBLNBChooser *lnbsettings;
221- DiSEqCPos *diseqcpos;
222- DiSEqCPort *diseqcport;
223- LNBLofSwitch *lnblofswitch;
224- LNBLofLo *lnbloflo;
225- LNBLofHi *lnblofhi;
226 StartingChannel *startchan;
227+#ifdef USING_DVB
228+ DVBDevSettings settings;
229+#endif
230 };
231
232 #endif
233Index: libs/libmythtv/libmythtv.pro
234===================================================================
235--- libs/libmythtv/libmythtv.pro (revision 10186)
236+++ libs/libmythtv/libmythtv.pro (working copy)
237@@ -408,9 +408,11 @@
238
239 # Channel stuff
240 HEADERS += dvbchannel.h dvbsignalmonitor.h
241- HEADERS += dvbdiseqc.h dvbcam.h
242+ HEADERS += dvbdevtree.h dvbcam.h
243+ HEADERS += dvbdevtree_cfg.h
244 SOURCES += dvbchannel.cpp dvbsignalmonitor.cpp
245- SOURCES += dvbdiseqc.cpp dvbcam.cpp
246+ SOURCES += dvbdevtree.cpp dvbcam.cpp
247+ SOURCES += dvbdevtree_cfg.cpp
248
249 # DVB Recorder
250 HEADERS += dvbrecorder.h
251Index: libs/libmythtv/dbcheck.cpp
252===================================================================
253--- libs/libmythtv/dbcheck.cpp (revision 10186)
254+++ libs/libmythtv/dbcheck.cpp (working copy)
255@@ -8,6 +8,9 @@
256
257 #include "mythcontext.h"
258 #include "mythdbcon.h"
259+#ifdef USING_DVB
260+#include "dvbdevtree_cfg.h"
261+#endif
262
263 /// This is the DB schema version expected by the running MythTV instance.
264 const QString currentDatabaseVersion = "1143";
265@@ -419,6 +422,15 @@
266 */
267 bool UpgradeTVDatabaseSchema(void)
268 {
269+#ifdef USING_DVB
270+ // TODO: The code in DatabaseDiseqcUpgrade (just sequence of SQL queries)
271+ // should be versioned and added to the database creation/upgrade functions as
272+ // normal. DatabaseDiseqcImport() should be called as part of that upgrade
273+ // process as well.
274+ if(DatabaseDiseqcUpgrade())
275+ DatabaseDiseqcImport();
276+#endif
277+
278 QString dbver = gContext->GetSetting("DBSchemaVer");
279
280 VERBOSE(VB_IMPORTANT, QString("Current Schema Version: %1").arg(dbver));
281Index: libs/libmythtv/signalmonitor.h
282===================================================================
283--- libs/libmythtv/signalmonitor.h (revision 10186)
284+++ libs/libmythtv/signalmonitor.h (working copy)
285@@ -55,6 +55,7 @@
286 kDVBSigMon_WaitForSNR = 0x01000000,
287 kDVBSigMon_WaitForBER = 0x02000000,
288 kDVBSigMon_WaitForUB = 0x04000000,
289+ kDVBSigMon_WaitForPos = 0x08000000, ///< Wait for rotor
290 };
291
292 inline QString sm_flags_to_string(uint);
293Index: libs/libmythtv/dvbtypes.cpp
294===================================================================
295--- libs/libmythtv/dvbtypes.cpp (revision 10186)
296+++ libs/libmythtv/dvbtypes.cpp (working copy)
297@@ -416,6 +416,11 @@
298 }
299 }
300
301+char DVBTuning::PolarityChar() const
302+{
303+ return polariz;
304+}
305+
306 char DVBTuning::TransmissionModeChar() const
307 {
308 switch (params.u.ofdm.transmission_mode)
309@@ -539,6 +544,11 @@
310 return coderate(params.u.qam.fec_inner);
311 }
312
313+QString DVBTuning::QPSKInnerFECString() const
314+{
315+ return coderate(params.u.qpsk.fec_inner);
316+}
317+
318 QString DVBTuning::GuardIntervalString() const
319 {
320 //Guard Interval
321@@ -584,7 +594,7 @@
322 msg = QString("Frequency: %1 Symbol Rate: %2 Pol: %3 Inv: %4")
323 .arg(Frequency())
324 .arg(QPSKSymbolRate())
325- .arg((voltage == SEC_VOLTAGE_13) ? "V/R" : "H/L")
326+ .arg(PolarityChar())
327 .arg(InversionString());
328 }
329 else if (FE_QAM == type)
330@@ -676,12 +686,7 @@
331 bool DVBTuning::parseDVBS2(
332 const QString& frequency, const QString& inversion,
333 const QString& symbol_rate, const QString& fec_inner,
334- const QString& pol, const QString& _diseqc_type,
335- const QString& _diseqc_port,
336- const QString& _diseqc_pos,
337- const QString& _lnb_lof_switch,
338- const QString& _lnb_lof_hi,
339- const QString& _lnb_lof_lo,
340+ const QString& pol,
341 const QString &modulation)
342 {
343 bool ok = true;
344@@ -702,35 +707,19 @@
345 return false;
346 }
347
348- voltage = parsePolarity(pol, ok);
349- if (SEC_VOLTAGE_OFF == voltage)
350- {
351- VERBOSE(VB_IMPORTANT, LOC_ERR + "Invalid polarization, aborting.");
352- return false;
353- }
354+ if(!pol.isEmpty())
355+ polariz = QChar(pol[0]).lower();
356
357 p.fec_inner = parseCodeRate(fec_inner, ok);
358
359 p.modulation = parseModulation(modulation, ok);
360- diseqc_type = _diseqc_type.toInt();
361- diseqc_port = _diseqc_port.toInt();
362- diseqc_pos = _diseqc_pos.toFloat();
363- lnb_lof_switch = _lnb_lof_switch.toInt();
364- lnb_lof_hi = _lnb_lof_hi.toInt();
365- lnb_lof_lo = _lnb_lof_lo.toInt();
366 return true;
367 }
368 #endif
369
370-// TODO: Add in DiseqcPos when diseqc class supports it
371 bool DVBTuning::parseQPSK(const QString& frequency, const QString& inversion,
372 const QString& symbol_rate, const QString& fec_inner,
373- const QString& pol, const QString& _diseqc_type,
374- const QString& _diseqc_port,
375- const QString& _diseqc_pos,
376- const QString& _lnb_lof_switch,
377- const QString& _lnb_lof_hi,
378- const QString& _lnb_lof_lo)
379+ const QString& pol)
380 {
381 bool ok = true;
382
383@@ -753,22 +742,11 @@
384 return false;
385 }
386
387- voltage = parsePolarity(pol, ok);
388- if (SEC_VOLTAGE_OFF == voltage)
389- {
390- VERBOSE(VB_IMPORTANT, LOC_ERR + "Invalid polarization, aborting.");
391+ if(!pol.isEmpty())
392+ polariz = QChar(pol[0]).lower();
393
394- return false;
395- }
396-
397 p.fec_inner = parseCodeRate(fec_inner, ok);
398
399- diseqc_type = _diseqc_type.toInt();
400- diseqc_port = _diseqc_port.toInt();
401- diseqc_pos = _diseqc_pos.toFloat();
402- lnb_lof_switch = _lnb_lof_switch.toInt();
403- lnb_lof_hi = _lnb_lof_hi.toInt();
404- lnb_lof_lo = _lnb_lof_lo.toInt();
405 return true;
406 }
407
408@@ -823,20 +801,6 @@
409 return BANDWIDTH_AUTO;
410 }
411
412-fe_sec_voltage DVBTuning::parsePolarity(const QString &pol, bool &ok)
413-{
414- char polarity = QChar(pol[0]).lower();
415- ok = true;
416- switch (polarity)
417- {
418- case 'v':
419- case 'r': return SEC_VOLTAGE_13;
420- case 'h':
421- case 'l': return SEC_VOLTAGE_18;
422- default: return SEC_VOLTAGE_OFF;
423- }
424-}
425-
426 fe_guard_interval DVBTuning::parseGuardInterval(const QString &gi, bool &ok)
427 {
428 QString guard_interval = gi.lower();
429@@ -1015,7 +979,7 @@
430 {
431 switch (coderate)
432 {
433- case FEC_NONE: return "None";
434+ case FEC_NONE: return "none";
435 case FEC_1_2: return "1/2";
436 case FEC_2_3: return "2/3";
437 case FEC_3_4: return "3/4";
438@@ -1024,7 +988,7 @@
439 case FEC_6_7: return "6/7";
440 case FEC_7_8: return "7/8";
441 case FEC_8_9: return "8/9";
442- default: return "Auto";
443+ default: return "auto";
444 }
445 }
446
447Index: libs/libmythtv/scanwizardscanner.cpp
448===================================================================
449--- libs/libmythtv/scanwizardscanner.cpp (revision 10186)
450+++ libs/libmythtv/scanwizardscanner.cpp (working copy)
451@@ -269,41 +269,6 @@
452 popupProgress = NULL;
453 }
454
455-static bool get_diseqc(uint cardid, uint sourceid,
456- QMap<QString,QString> &startChan)
457-{
458- // SQL code to get the disqec paramters HERE
459- MSqlQuery query(MSqlQuery::InitCon());
460- query.prepare(
461- "SELECT dvb_diseqc_type, diseqc_port, diseqc_pos, "
462- " lnb_lof_switch, lnb_lof_hi, lnb_lof_lo "
463- "FROM cardinput, capturecard "
464- "WHERE cardinput.cardid = capturecard.cardid AND "
465- " cardinput.cardid = :CARDID AND "
466- " cardinput.sourceid = :SOURCEID ");
467- query.bindValue(":CARDID", cardid);
468- query.bindValue(":SOURCEID", sourceid);
469-
470- if (!query.exec() || !query.isActive())
471- {
472- MythContext::DBError("ScanWizardScanner::scan()", query);
473- return false;
474- }
475-
476- if (query.next())
477- {
478- startChan["diseqc_type"] = query.value(0).toString();
479- startChan["diseqc_port"] = query.value(1).toString();
480- startChan["diseqc_pos"] = query.value(2).toString();
481- startChan["lnb_lof_switch"] = query.value(3).toString();
482- startChan["lnb_lof_hi"] = query.value(4).toString();
483- startChan["lnb_lof_lo"] = query.value(5).toString();
484- return true;
485- }
486-
487- return false;
488-}
489-
490 // full scan of existing transports broken
491 // existing transport scan broken
492 void ScanWizardScanner::scan()
493@@ -375,8 +340,6 @@
494 startChan["modulation"] = "qpsk";
495 startChan["polarity"] = pane->polarity();
496
497- nit_scan_parse_failed = !get_diseqc(cardid, nVideoSource, startChan);
498-
499 #ifdef USING_DVB
500 if (!nit_scan_parse_failed)
501 {
502@@ -384,10 +347,7 @@
503 nit_scan_parse_failed = !tuning.parseQPSK(
504 startChan["frequency"], startChan["inversion"],
505 startChan["symbolrate"], startChan["fec"],
506- startChan["polarity"],
507- startChan["diseqc_type"], startChan["diseqc_port"],
508- startChan["diseqc_pos"], startChan["lnb_lof_switch"],
509- startChan["lnb_lof_hi"], startChan["lnb_lof_lo"]);
510+ startChan["polarity"]);
511 }
512 #endif // USING_DVB
513 }
514Index: libs/libmythtv/dvbdevtree_cfg.cpp
515===================================================================
516--- libs/libmythtv/dvbdevtree_cfg.cpp (revision 0)
517+++ libs/libmythtv/dvbdevtree_cfg.cpp (revision 0)
518@@ -0,0 +1,1375 @@
519+/*
520+ * \file dvbdevtree_cfg.cpp
521+ * \brief DVB-S Device Tree Configuration Classes.
522+ * \author Copyright (C) 2006, Yeasah Pell
523+ */
524+
525+#include "mythcontext.h"
526+#include "qsqldatabase.h"
527+#include "settings.h"
528+#include "dvbdevtree_cfg.h"
529+#include "dvbdevtree.h"
530+#include <set>
531+#include <cmath>
532+
533+/* Lat/Long items relocated from videosource.cpp */
534+
535+static GlobalLineEdit *DiSEqCLatitude()
536+{
537+ GlobalLineEdit *gc = new GlobalLineEdit("latitude");
538+ gc->setLabel("Latitude");
539+ gc->setHelpText(
540+ QObject::tr("The Cartesian latitude for your location.") + " " +
541+ QObject::tr("Use negative numbers for southern "
542+ "and western coordinates."));
543+ return gc;
544+}
545+
546+static GlobalLineEdit *DiSEqCLongitude()
547+{
548+ GlobalLineEdit *gc = new GlobalLineEdit("longitude");
549+ gc->setLabel("Longitude");
550+ gc->setHelpText(
551+ QObject::tr("The Cartesian longitude for your location.") + " " +
552+ QObject::tr("Use negative numbers for southern "
553+ "and western coordinates."));
554+ return gc;
555+}
556+
557+//////////////////////////////////////// DeviceTypeSetting
558+
559+class DeviceTypeSetting : public ComboBoxSetting
560+{
561+public:
562+ DeviceTypeSetting(DVBDevDevice& device) : m_device(device)
563+ {
564+ setLabel(QObject::tr("Device Type"));
565+ addSelection("Switch", QString::number((uint)DVBDEV_SWITCH));
566+ addSelection("Rotor", QString::number((uint)DVBDEV_ROTOR));
567+ addSelection("LNB", QString::number((uint)DVBDEV_LNB));
568+ }
569+
570+ virtual void load()
571+ {
572+ setValue(getValueIndex(QString::number((uint)m_device.GetDeviceType())));
573+ }
574+
575+ virtual void save()
576+ {
577+ m_device.SetDeviceType((dvbdev_t)getValue().toUInt());
578+ }
579+
580+private:
581+ DVBDevDevice& m_device;
582+};
583+
584+//////////////////////////////////////// DeviceDescrSetting
585+
586+class DeviceDescrSetting : public LineEditSetting
587+{
588+public:
589+ DeviceDescrSetting(DVBDevDevice& device) : m_device(device)
590+ {
591+ setLabel(QObject::tr("Description"));
592+ setHelpText(QObject::tr("Optional descriptive name for this "
593+ "device, to make it easier to configure "
594+ "settings later."));
595+ }
596+
597+ virtual void load()
598+ {
599+ setValue(m_device.GetDescription());
600+ }
601+
602+ virtual void save()
603+ {
604+ m_device.SetDescription(getValue());
605+ }
606+
607+private:
608+ DVBDevDevice& m_device;
609+};
610+
611+//////////////////////////////////////// SwitchTypeSetting
612+
613+class SwitchTypeSetting : public ComboBoxSetting
614+{
615+public:
616+ SwitchTypeSetting(DVBDevSwitch& switch_dev) : m_switch(switch_dev)
617+ {
618+ setLabel(QObject::tr("Switch Type"));
619+ setHelpText(QObject::tr("Select the type of switch from the list."));
620+
621+ addSelection("Tone", QString::number((uint)SWITCH_TONE));
622+ addSelection("DiSEqC", QString::number((uint)SWITCH_DISEQC_COMMITTED));
623+ addSelection("DiSEqC (Uncommitted)", QString::number((uint)SWITCH_DISEQC_UNCOMMITTED));
624+ addSelection("Legacy SW21", QString::number((uint)SWITCH_LEGACY_SW21));
625+ addSelection("Legacy SW42", QString::number((uint)SWITCH_LEGACY_SW42));
626+ addSelection("Legacy SW64", QString::number((uint)SWITCH_LEGACY_SW64));
627+ }
628+
629+ virtual void load()
630+ {
631+ setValue(getValueIndex(QString::number((uint)m_switch.GetType())));
632+ }
633+
634+ virtual void save()
635+ {
636+ m_switch.SetType((dvbdev_switch_t)getValue().toUInt());
637+ }
638+
639+private:
640+ DVBDevSwitch& m_switch;
641+};
642+
643+//////////////////////////////////////// SwitchPortsSetting
644+
645+class SwitchPortsSetting : public LineEditSetting
646+{
647+public:
648+ SwitchPortsSetting(DVBDevSwitch& switch_dev) : m_switch(switch_dev)
649+ {
650+ setLabel(QObject::tr("Number of ports"));
651+ setHelpText(QObject::tr("The number of ports this switch has."));
652+ }
653+
654+ virtual void load()
655+ {
656+ setValue(QString::number(m_switch.GetNumPorts()));
657+ }
658+
659+ virtual void save()
660+ {
661+ m_switch.SetNumPorts(getValue().toUInt());
662+ }
663+
664+private:
665+ DVBDevSwitch& m_switch;
666+};
667+
668+//////////////////////////////////////// SwitchConfig
669+
670+SwitchConfig::SwitchConfig(DVBDevSwitch& switch_dev)
671+{
672+ ConfigurationGroup* group =
673+ new VerticalConfigurationGroup(false, false);
674+ group->setLabel(QObject::tr("Switch Configuration"));
675+
676+ group->addChild(new DeviceDescrSetting(switch_dev));
677+ m_type = new SwitchTypeSetting(switch_dev);
678+ group->addChild(m_type);
679+ m_ports = new SwitchPortsSetting(switch_dev);
680+ group->addChild(m_ports);
681+
682+ connect(m_type, SIGNAL(valueChanged(const QString&)), this, SLOT(update()));
683+
684+ addChild(group);
685+}
686+
687+void SwitchConfig::update()
688+{
689+ switch((dvbdev_switch_t)m_type->getValue().toUInt())
690+ {
691+ case SWITCH_TONE:
692+ case SWITCH_LEGACY_SW21:
693+ case SWITCH_LEGACY_SW42:
694+ m_ports->setValue("2");
695+ m_ports->setEnabled(false);
696+ break;
697+ case SWITCH_LEGACY_SW64:
698+ m_ports->setValue("3");
699+ m_ports->setEnabled(false);
700+ break;
701+ case SWITCH_DISEQC_COMMITTED:
702+ case SWITCH_DISEQC_UNCOMMITTED:
703+ m_ports->setEnabled(true);
704+ break;
705+ }
706+}
707+
708+//////////////////////////////////////// RotorTypeSetting
709+
710+class RotorTypeSetting : public ComboBoxSetting
711+{
712+public:
713+ RotorTypeSetting(DVBDevRotor& rotor) : m_rotor(rotor)
714+ {
715+ setLabel(QObject::tr("Rotor Type"));
716+ setHelpText(QObject::tr("Select the type of rotor from the list."));
717+ addSelection("DiSEqC 1.2", QString::number((uint)ROTOR_DISEQC_1_2));
718+ addSelection("DiSEqC 1.3 (GotoX/USALS)", QString::number((uint)ROTOR_DISEQC_1_3));
719+ }
720+
721+ virtual void load()
722+ {
723+ setValue(getValueIndex(QString::number((uint)m_rotor.GetType())));
724+ }
725+
726+ virtual void save()
727+ {
728+ m_rotor.SetType((dvbdev_rotor_t)getValue().toUInt());
729+ }
730+
731+private:
732+ DVBDevRotor& m_rotor;
733+};
734+
735+//////////////////////////////////////// RotorLoSpeedSetting
736+
737+class RotorLoSpeedSetting : public LineEditSetting
738+{
739+public:
740+ RotorLoSpeedSetting(DVBDevRotor& rotor) : m_rotor(rotor)
741+ {
742+ setLabel(QObject::tr("Rotor Low Speed (deg/sec)"));
743+ setHelpText(QObject::tr("To allow the approximate monitoring of "
744+ "rotor movement, enter the rated angular "
745+ "speed of the rotor when powered at 13V."));
746+ }
747+
748+ virtual void load()
749+ {
750+ setValue(QString::number(m_rotor.GetLoSpeed()));
751+ }
752+
753+ virtual void save()
754+ {
755+ m_rotor.SetLoSpeed(getValue().toDouble());
756+ }
757+
758+private:
759+ DVBDevRotor& m_rotor;
760+};
761+
762+//////////////////////////////////////// RotorHiSpeedSetting
763+
764+class RotorHiSpeedSetting : public LineEditSetting
765+{
766+public:
767+ RotorHiSpeedSetting(DVBDevRotor& rotor) : m_rotor(rotor)
768+ {
769+ setLabel(QObject::tr("Rotor High Speed (deg/sec)"));
770+ setHelpText(QObject::tr("To allow the approximate monitoring of "
771+ "rotor movement, enter the rated angular "
772+ "speed of the rotor when powered at 18V."));
773+ }
774+
775+ virtual void load()
776+ {
777+ setValue(QString::number(m_rotor.GetHiSpeed()));
778+ }
779+
780+ virtual void save()
781+ {
782+ m_rotor.SetHiSpeed(getValue().toDouble());
783+ }
784+
785+private:
786+ DVBDevRotor& m_rotor;
787+};
788+
789+//////////////////////////////////////// RotorPosMap
790+
791+static QString AngleToString(double angle)
792+{
793+ QString str;
794+ if(angle >= 0.0)
795+ str = QString::number(angle) + "E";
796+ else if(angle < 0.0)
797+ str = QString::number(-angle) + "W";
798+ return str;
799+}
800+
801+static double AngleToFloat(const QString& angle)
802+{
803+ double pos;
804+ QChar postfix = angle.at(angle.length()-1);
805+ if(postfix.isLetter())
806+ {
807+ pos = angle.left(angle.length()-1).toDouble();
808+ if(postfix == 'W' || postfix == 'w')
809+ pos = -pos;
810+ }
811+ else
812+ pos = angle.toDouble();
813+
814+ return pos;
815+}
816+
817+RotorPosMap::RotorPosMap(DVBDevRotor& rotor) : m_rotor(rotor)
818+{
819+ connect(this, SIGNAL(editButtonPressed(int)), SLOT(edit()));
820+ connect(this, SIGNAL(deleteButtonPressed(int)), SLOT(del()));
821+ connect(this, SIGNAL(accepted(int)), SLOT(edit()));
822+}
823+
824+void RotorPosMap::load()
825+{
826+ m_posmap = m_rotor.GetPosMap();
827+ PopulateList();
828+}
829+
830+void RotorPosMap::save()
831+{
832+ m_rotor.SetPosMap(m_posmap);
833+}
834+
835+void RotorPosMap::edit()
836+{
837+ unsigned int id = getValue().toUInt();
838+
839+ QString angle;
840+ if(MythPopupBox::showGetTextPopup(gContext->GetMainWindow(),
841+ QString("Position Index %1").arg(id),
842+ "Orbital Position",
843+ angle))
844+ {
845+ m_posmap[id] = AngleToFloat(angle);
846+ PopulateList();
847+ }
848+}
849+
850+void RotorPosMap::del()
851+{
852+ unsigned int id = getValue().toUInt();
853+ m_posmap.erase(id);
854+ PopulateList();
855+}
856+
857+void RotorPosMap::PopulateList()
858+{
859+ int old_sel = getValueIndex(getValue());
860+ clearSelections();
861+ uint num_pos = 64;
862+ for(uint pos = 1; pos < num_pos; pos++)
863+ {
864+ DVBDevRotor::POSMAP::const_iterator p = m_posmap.find(pos);
865+ QString posval;
866+ if(p == m_posmap.end())
867+ posval = "None";
868+ else
869+ posval = AngleToString(p->second);
870+
871+ addSelection(QString("Position #%1 (%2)")
872+ .arg(pos)
873+ .arg(posval),
874+ QString::number(pos));
875+ }
876+ setCurrentItem(old_sel);
877+}
878+
879+//////////////////////////////////////// RotorPosConfig
880+
881+class RotorPosConfig : public VerticalConfigurationGroup,
882+ public ConfigurationDialog
883+{
884+public:
885+ RotorPosConfig(DVBDevRotor& rotor)
886+ {
887+ setLabel(QObject::tr("Rotor Position Map"));
888+ setUseLabel(true);
889+ addChild(new RotorPosMap(rotor));
890+ }
891+
892+ virtual int exec()
893+ {
894+ while (ConfigurationDialog::exec() == QDialog::Accepted) {}
895+ return QDialog::Rejected;
896+ }
897+};
898+
899+//////////////////////////////////////// RotorConfig
900+
901+RotorConfig::RotorConfig(DVBDevRotor& rotor) : m_rotor(rotor)
902+{
903+ ConfigurationGroup* group =
904+ new VerticalConfigurationGroup(false, false);
905+ group->setLabel(QObject::tr("Rotor Configuration"));
906+
907+ group->addChild(new DeviceDescrSetting(rotor));
908+
909+ ConfigurationGroup* tgroup =
910+ new HorizontalConfigurationGroup(false, false, true, true);
911+
912+ RotorTypeSetting* rtype = new RotorTypeSetting(rotor);
913+ connect(rtype, SIGNAL(valueChanged(const QString&)),
914+ SLOT(type_changed(const QString&)));
915+ tgroup->addChild(rtype);
916+
917+ m_pos = new TransButtonSetting();
918+ m_pos->setLabel(QObject::tr("Positions"));
919+ m_pos->setHelpText(QObject::tr("Rotor position setup."));
920+ m_pos->setEnabled(rotor.GetType() == ROTOR_DISEQC_1_2);
921+ connect(m_pos, SIGNAL(pressed()), SLOT(positions()));
922+ tgroup->addChild(m_pos);
923+
924+ group->addChild(tgroup);
925+ group->addChild(new RotorLoSpeedSetting(rotor));
926+ group->addChild(new RotorHiSpeedSetting(rotor));
927+ group->addChild(DiSEqCLatitude());
928+ group->addChild(DiSEqCLongitude());
929+
930+ addChild(group);
931+}
932+
933+void RotorConfig::type_changed(const QString& type)
934+{
935+ dvbdev_rotor_t rtype = (dvbdev_rotor_t)type.toUInt();
936+ m_pos->setEnabled(rtype == ROTOR_DISEQC_1_2);
937+}
938+
939+void RotorConfig::positions()
940+{
941+ RotorPosConfig config(m_rotor);
942+ config.exec();
943+ config.save();
944+}
945+
946+//////////////////////////////////////// LnbPresetSetting
947+
948+struct lnb_preset
949+{
950+ const char* name;
951+ dvbdev_lnb_t type;
952+ unsigned int lof_sw;
953+ unsigned int lof_lo;
954+ unsigned int lof_hi;
955+};
956+
957+static lnb_preset lnb_presets[] =
958+{
959+ /* description, type, LOF switch, LOF low, LOF high */
960+ { "Single (Europe)", LNB_VOLTAGE, 0, 9750000, 0 },
961+ { "Universal (Europe)", LNB_VOLTAGE_TONE, 11700000, 9750000, 10600000 },
962+ { "Circular (N. America)", LNB_VOLTAGE, 0, 11250000, 0 },
963+ { "Linear (N. America)", LNB_VOLTAGE, 0, 10750000, 0 },
964+ { "C Band", LNB_VOLTAGE, 0, 5150000, 0 },
965+ { NULL, LNB_VOLTAGE, 0, 0, 0 }
966+};
967+
968+unsigned int FindPreset(const DVBDevLnb& lnb)
969+{
970+ unsigned int i;
971+ for(i=0; lnb_presets[i].name != NULL; i++)
972+ {
973+ if(lnb_presets[i].type == lnb.GetType() &&
974+ lnb_presets[i].lof_sw == lnb.GetLOFSwitch() &&
975+ lnb_presets[i].lof_lo == lnb.GetLOFLow() &&
976+ lnb_presets[i].lof_hi == lnb.GetLOFHigh())
977+ break;
978+ }
979+ return i;
980+}
981+
982+class LnbPresetSetting : public ComboBoxSetting
983+{
984+public:
985+ LnbPresetSetting(DVBDevLnb& lnb) : m_lnb(lnb)
986+ {
987+ setLabel(QObject::tr("LNB Preset"));
988+ setHelpText(QObject::tr("Select the LNB preset from the list, or "
989+ "choose Custom and change the advanced "
990+ "settings below."));
991+
992+ unsigned int i;
993+ for(i=0; lnb_presets[i].name != NULL; i++)
994+ addSelection(lnb_presets[i].name, QString::number(i));
995+ addSelection(QObject::tr("Custom"), QString::number(i));
996+ }
997+
998+ virtual void load()
999+ {
1000+ setValue(FindPreset(m_lnb));
1001+ }
1002+
1003+ virtual void save()
1004+ {
1005+ }
1006+
1007+private:
1008+ DVBDevLnb& m_lnb;
1009+};
1010+
1011+//////////////////////////////////////// LnbTypeSetting
1012+
1013+class LnbTypeSetting : public ComboBoxSetting
1014+{
1015+public:
1016+ LnbTypeSetting(DVBDevLnb& lnb) : m_lnb(lnb)
1017+ {
1018+ setLabel(QObject::tr("LNB Type"));
1019+ setHelpText(QObject::tr("Select the type of LNB from the list."));
1020+ addSelection("Legacy (Fixed)", QString::number((uint)LNB_FIXED));
1021+ addSelection("Standard (Voltage)", QString::number((uint)LNB_VOLTAGE));
1022+ addSelection("Universal (Voltage+Tone)", QString::number((uint)LNB_VOLTAGE_TONE));
1023+ }
1024+
1025+ virtual void load()
1026+ {
1027+ setValue(getValueIndex(QString::number((uint)m_lnb.GetType())));
1028+ }
1029+
1030+ virtual void save()
1031+ {
1032+ m_lnb.SetType((dvbdev_lnb_t)getValue().toUInt());
1033+ }
1034+
1035+private:
1036+ DVBDevLnb& m_lnb;
1037+};
1038+
1039+//////////////////////////////////////// LnbLOFSwitchSetting
1040+
1041+class LnbLOFSwitchSetting : public LineEditSetting
1042+{
1043+public:
1044+ LnbLOFSwitchSetting(DVBDevLnb& lnb) : m_lnb(lnb)
1045+ {
1046+ setLabel(QObject::tr("LNB LOF Switch (MHz)"));
1047+ setHelpText(QObject::tr("This defines at what frequency "
1048+ "the LNB will do a switch from high to low "
1049+ "setting, and vice versa."));
1050+ }
1051+
1052+ virtual void load()
1053+ {
1054+ setValue(QString::number(m_lnb.GetLOFSwitch() / 1000));
1055+ }
1056+
1057+ virtual void save()
1058+ {
1059+ m_lnb.SetLOFSwitch(getValue().toUInt() * 1000);
1060+ }
1061+
1062+private:
1063+ DVBDevLnb& m_lnb;
1064+};
1065+
1066+//////////////////////////////////////// LnbLOFLowSetting
1067+
1068+class LnbLOFLowSetting : public LineEditSetting
1069+{
1070+public:
1071+ LnbLOFLowSetting(DVBDevLnb& lnb) : m_lnb(lnb)
1072+ {
1073+ setLabel(QObject::tr("LNB LOF Low (MHz)"));
1074+ setHelpText(QObject::tr("This defines the offset the "
1075+ "frequency coming from the LNB will be "
1076+ "in low setting."));
1077+ }
1078+
1079+ virtual void load()
1080+ {
1081+ setValue(QString::number(m_lnb.GetLOFLow() / 1000));
1082+ }
1083+
1084+ virtual void save()
1085+ {
1086+ m_lnb.SetLOFLow(getValue().toUInt() * 1000);
1087+ }
1088+
1089+private:
1090+ DVBDevLnb& m_lnb;
1091+};
1092+
1093+//////////////////////////////////////// LnbLOFHighSetting
1094+
1095+class LnbLOFHighSetting : public LineEditSetting
1096+{
1097+public:
1098+ LnbLOFHighSetting(DVBDevLnb& lnb) : m_lnb(lnb)
1099+ {
1100+ setLabel(QObject::tr("LNB LOF High (MHz)"));
1101+ setHelpText(QObject::tr("This defines the offset the "
1102+ "frequency coming from the LNB will be "
1103+ "in high setting."));
1104+ }
1105+
1106+ virtual void load()
1107+ {
1108+ setValue(QString::number(m_lnb.GetLOFHigh() / 1000));
1109+ }
1110+
1111+ virtual void save()
1112+ {
1113+ m_lnb.SetLOFHigh(getValue().toUInt() * 1000);
1114+ }
1115+
1116+private:
1117+ DVBDevLnb& m_lnb;
1118+};
1119+
1120+//////////////////////////////////////// LnbConfig
1121+
1122+LnbConfig::LnbConfig(DVBDevLnb& lnb)
1123+{
1124+ ConfigurationGroup* group =
1125+ new VerticalConfigurationGroup(false, false);
1126+ group->setLabel(QObject::tr("LNB Configuration"));
1127+
1128+ group->addChild(new DeviceDescrSetting(lnb));
1129+ LnbPresetSetting* preset = new LnbPresetSetting(lnb);
1130+ group->addChild(preset);
1131+ m_type = new LnbTypeSetting(lnb);
1132+ group->addChild(m_type);
1133+ m_lof_switch = new LnbLOFSwitchSetting(lnb);
1134+ group->addChild(m_lof_switch);
1135+ m_lof_lo = new LnbLOFLowSetting(lnb);
1136+ group->addChild(m_lof_lo);
1137+ m_lof_hi = new LnbLOFHighSetting(lnb);
1138+ group->addChild(m_lof_hi);
1139+ connect(m_type, SIGNAL(valueChanged(const QString&)), this, SLOT(update()));
1140+ connect(preset, SIGNAL(valueChanged(const QString&)), this, SLOT(preset(const QString&)));
1141+ addChild(group);
1142+}
1143+
1144+void LnbConfig::preset(const QString& value)
1145+{
1146+ unsigned int index = value.toUInt();
1147+ if(index >= (sizeof(lnb_presets) / sizeof(lnb_preset)))
1148+ return;
1149+
1150+ lnb_preset& preset = lnb_presets[index];
1151+ if(preset.name == NULL)
1152+ {
1153+ m_type->setEnabled(true);
1154+ update();
1155+ }
1156+ else
1157+ {
1158+ m_type->setValue(m_type->getValueIndex(QString::number((uint)preset.type)));
1159+ m_lof_switch->setValue(QString::number(preset.lof_sw / 1000));
1160+ m_lof_lo->setValue(QString::number(preset.lof_lo / 1000));
1161+ m_lof_hi->setValue(QString::number(preset.lof_hi / 1000));
1162+ m_type->setEnabled(false);
1163+ m_lof_switch->setEnabled(false);
1164+ m_lof_hi->setEnabled(false);
1165+ m_lof_lo->setEnabled(false);
1166+ }
1167+}
1168+
1169+void LnbConfig::update()
1170+{
1171+ if(m_type->isEnabled())
1172+ {
1173+ switch((dvbdev_switch_t)m_type->getValue().toUInt())
1174+ {
1175+ case LNB_FIXED:
1176+ case LNB_VOLTAGE:
1177+ m_lof_switch->setEnabled(false);
1178+ m_lof_hi->setEnabled(false);
1179+ m_lof_lo->setEnabled(true);
1180+ break;
1181+ case LNB_VOLTAGE_TONE:
1182+ m_lof_switch->setEnabled(true);
1183+ m_lof_hi->setEnabled(true);
1184+ m_lof_lo->setEnabled(true);
1185+ break;
1186+ }
1187+ }
1188+}
1189+
1190+//////////////////////////////////////// DeviceTree
1191+
1192+
1193+DeviceTree::DeviceTree(DVBDevTree& tree) : m_tree(tree)
1194+{
1195+ connect(this, SIGNAL(editButtonPressed(int)), SLOT(edit()));
1196+ connect(this, SIGNAL(deleteButtonPressed(int)), SLOT(del()));
1197+ connect(this, SIGNAL(accepted(int)), SLOT(edit()));
1198+}
1199+
1200+void DeviceTree::load()
1201+{
1202+ PopulateTree();
1203+}
1204+
1205+void DeviceTree::save()
1206+{
1207+}
1208+
1209+bool DeviceTree::editNode(int node_id)
1210+{
1211+ DVBDevDevice* dev = m_tree.FindDevice(node_id);
1212+ bool changed = false;
1213+ if(dev)
1214+ {
1215+ switch(dev->GetDeviceType())
1216+ {
1217+ case DVBDEV_SWITCH:
1218+ {
1219+ DVBDevSwitch* sw = dynamic_cast<DVBDevSwitch*>(dev);
1220+ if(sw)
1221+ {
1222+ SwitchConfig config(*sw);
1223+ changed = (config.exec() == MythDialog::Accepted);
1224+ }
1225+ }
1226+ break;
1227+ case DVBDEV_ROTOR:
1228+ {
1229+ DVBDevRotor* rotor = dynamic_cast<DVBDevRotor*>(dev);
1230+ if(rotor)
1231+ {
1232+ RotorConfig config(*rotor);
1233+ changed = (config.exec() == MythDialog::Accepted);
1234+ }
1235+ }
1236+ break;
1237+ case DVBDEV_LNB:
1238+ {
1239+ DVBDevLnb* lnb = dynamic_cast<DVBDevLnb*>(dev);
1240+ if(lnb)
1241+ {
1242+ LnbConfig config(*lnb);
1243+ changed = (config.exec() == MythDialog::Accepted);
1244+ }
1245+ }
1246+ break;
1247+ default:
1248+ break;
1249+ }
1250+ }
1251+
1252+ if(changed)
1253+ PopulateTree();
1254+ return changed;
1255+}
1256+
1257+bool DeviceTree::chooseType(dvbdev_t& type)
1258+{
1259+ MythPopupBox* popup = new MythPopupBox(gContext->GetMainWindow(), "");
1260+ popup->addLabel(tr("Select Type of Device"));
1261+
1262+ MythListBox* list = new MythListBox(popup);
1263+ list->setScrollBar(false);
1264+ list->setBottomScrollBar(false);
1265+ list->insertItem("Switch");
1266+ list->insertItem("Rotor");
1267+ list->insertItem("LNB");
1268+ list->setCurrentItem(0);
1269+
1270+ popup->addWidget(list);
1271+ connect(list, SIGNAL(accepted(int)), popup, SLOT(done(int)));
1272+ list->setFocus();
1273+
1274+ int res = popup->ExecPopup();
1275+ type = (dvbdev_t)list->currentItem();
1276+ delete popup;
1277+
1278+ return res >= 0;
1279+}
1280+
1281+void DeviceTree::newRootNode()
1282+{
1283+ dvbdev_t type;
1284+ if(chooseType(type))
1285+ {
1286+ DVBDevDevice* dev = DVBDevDevice::CreateByType(m_tree, type);
1287+ if(dev)
1288+ {
1289+ m_tree.SetRoot(dev);
1290+ if(!editNode(dev->DeviceID()))
1291+ m_tree.SetRoot(NULL);
1292+ PopulateTree();
1293+ }
1294+ }
1295+}
1296+
1297+void DeviceTree::newNode(int parent_id, unsigned int child_num)
1298+{
1299+ DVBDevDevice* parent = m_tree.FindDevice(parent_id);
1300+ if(parent)
1301+ {
1302+ dvbdev_t type;
1303+ if(chooseType(type))
1304+ {
1305+ DVBDevDevice* dev = DVBDevDevice::CreateByType(m_tree, type);
1306+ if(dev)
1307+ {
1308+ if(parent->SetChild(child_num, dev))
1309+ {
1310+ if(!editNode(dev->DeviceID()))
1311+ parent->SetChild(child_num, NULL);
1312+ PopulateTree();
1313+ }
1314+ else
1315+ delete dev;
1316+ }
1317+ }
1318+ }
1319+}
1320+
1321+void DeviceTree::edit()
1322+{
1323+ QString id = getValue();
1324+ if(id.find(':') == -1)
1325+ editNode(id.toInt());
1326+ else
1327+ {
1328+ QStringList vals = QStringList::split(':', id, true);
1329+ if(vals[0].isEmpty())
1330+ newRootNode();
1331+ else
1332+ newNode(vals[0].toInt(), vals[1].toUInt());
1333+ }
1334+ setFocus();
1335+}
1336+
1337+void DeviceTree::del()
1338+{
1339+ QString id = getValue();
1340+ if(id.find(':') == -1)
1341+ {
1342+ int node_id = id.toInt();
1343+ DVBDevDevice* dev = m_tree.FindDevice(node_id);
1344+ if(dev)
1345+ {
1346+ DVBDevDevice* parent = dev->GetParent();
1347+ if(parent)
1348+ parent->SetChild(dev->GetOrdinal(), NULL);
1349+ else
1350+ m_tree.SetRoot(NULL);
1351+
1352+ PopulateTree();
1353+ }
1354+ }
1355+ setFocus();
1356+}
1357+
1358+void DeviceTree::PopulateTree()
1359+{
1360+ int old_sel = getValueIndex(getValue());
1361+ clearSelections();
1362+ PopulateTree(m_tree.Root());
1363+ setCurrentItem(old_sel);
1364+}
1365+
1366+void DeviceTree::PopulateTree(DVBDevDevice* node,
1367+ DVBDevDevice* parent,
1368+ unsigned int childnum,
1369+ unsigned int depth)
1370+{
1371+ QString indent;
1372+ indent.fill('\t', depth);
1373+ if(node)
1374+ {
1375+ QString id = QString::number(node->DeviceID());
1376+ addSelection(indent + node->GetDescription(), id);
1377+ unsigned int num_ch = node->NumChildren();
1378+ for(unsigned int ch = 0; ch < num_ch; ch++)
1379+ PopulateTree(node->GetChild(ch), node, ch, depth+1);
1380+ }
1381+ else
1382+ {
1383+ QString id;
1384+ if(parent)
1385+ id = QString::number(parent->DeviceID());
1386+ id += ":" + QString::number(childnum);
1387+
1388+ addSelection(indent + "(Unconnected)", id);
1389+ }
1390+}
1391+
1392+//////////////////////////////////////// DTVDeviceTreeWizard
1393+
1394+DTVDeviceTreeWizard::DTVDeviceTreeWizard(DVBDevTree& tree)
1395+ : ConfigurationGroup(false, true, false, false),
1396+ VerticalConfigurationGroup(false, true, false, false)
1397+{
1398+ setLabel(QObject::tr("DVB-S Device Tree"));
1399+ setUseLabel(true);
1400+ addChild(new DeviceTree(tree));
1401+}
1402+
1403+int DTVDeviceTreeWizard::exec()
1404+{
1405+ while (ConfigurationDialog::exec() == QDialog::Accepted) {}
1406+ return QDialog::Rejected;
1407+}
1408+
1409+//////////////////////////////////////// SwitchSetting
1410+
1411+class SwitchSetting : public ComboBoxSetting
1412+{
1413+public:
1414+ SwitchSetting(DVBDevDevice& node, DVBDevSettings& settings)
1415+ : m_node(node), m_settings(settings)
1416+ {
1417+ setLabel(node.GetDescription());
1418+ setHelpText(QObject::tr("Choose a port to use for this switch."));
1419+
1420+ unsigned int num_children = node.NumChildren();
1421+ for(unsigned int ch = 0; ch < num_children; ch++)
1422+ {
1423+ QString val = QString("%1").arg(ch);
1424+ QString descr = QString("Port %1").arg(ch+1);
1425+ DVBDevDevice* child = node.GetChild(ch);
1426+ if(child)
1427+ descr += QString(" (%2)").arg(child->GetDescription());
1428+ addSelection(descr, val);
1429+ }
1430+ }
1431+
1432+ virtual void load()
1433+ {
1434+ double value = m_settings.GetValue(m_node.DeviceID());
1435+ setValue((unsigned int)value);
1436+ }
1437+
1438+ virtual void save()
1439+ {
1440+ m_settings.SetValue(m_node.DeviceID(), getValue().toDouble());
1441+ }
1442+
1443+private:
1444+ DVBDevDevice& m_node;
1445+ DVBDevSettings& m_settings;
1446+};
1447+
1448+//////////////////////////////////////// RotorSetting
1449+
1450+class RotorSetting : public ComboBoxSetting
1451+{
1452+public:
1453+ RotorSetting(DVBDevDevice& node, DVBDevSettings& settings)
1454+ : m_node(node), m_settings(settings)
1455+ {
1456+ setLabel(node.GetDescription());
1457+ setHelpText(QObject::tr("Choose a satellite position."));
1458+
1459+ DVBDevRotor* rotor = dynamic_cast<DVBDevRotor*>(&m_node);
1460+ if(rotor)
1461+ m_posmap = rotor->GetPosMap();
1462+ }
1463+
1464+ virtual void load()
1465+ {
1466+ clearSelections();
1467+ DVBDevRotor::POSMAP::iterator p;
1468+ for(p = m_posmap.begin(); p != m_posmap.end(); p++)
1469+ addSelection(AngleToString(p->second), QString::number(p->second));
1470+ double angle = m_settings.GetValue(m_node.DeviceID());
1471+ setValue(getValueIndex(QString::number(angle)));
1472+ }
1473+
1474+ virtual void save()
1475+ {
1476+ m_settings.SetValue(m_node.DeviceID(), getValue().toDouble());
1477+ }
1478+
1479+private:
1480+ DVBDevDevice& m_node;
1481+ DVBDevSettings& m_settings;
1482+ DVBDevRotor::POSMAP m_posmap;
1483+};
1484+
1485+//////////////////////////////////////// USALSRotorSetting
1486+
1487+class USALSRotorSetting : public LineEditSetting
1488+{
1489+public:
1490+ USALSRotorSetting(DVBDevDevice& node, DVBDevSettings& settings)
1491+ : m_node(node), m_settings(settings)
1492+ {
1493+ setLabel(node.GetDescription());
1494+ setHelpText(QObject::tr("The longitude of the satellite "
1495+ "you are aiming at. For western hemisphere "
1496+ "use a 'W' suffix. Value is in decimal."));
1497+ }
1498+
1499+ virtual void load()
1500+ {
1501+ setValue(AngleToString(m_settings.GetValue(m_node.DeviceID())));
1502+ }
1503+
1504+ virtual void save()
1505+ {
1506+ m_settings.SetValue(m_node.DeviceID(), AngleToFloat(getValue()));
1507+ }
1508+
1509+private:
1510+ DVBDevDevice& m_node;
1511+ DVBDevSettings& m_settings;
1512+};
1513+
1514+//////////////////////////////////////// DTVDeviceNeedsConfiguration
1515+
1516+bool DTVDeviceNeedsConfiguration(unsigned int card_id)
1517+{
1518+ bool needs_conf = false;
1519+ MSqlQuery query(MSqlQuery::InitCon());
1520+ query.prepare("SELECT dtv_dev_type"
1521+ " FROM dtv_device_tree, capturecard"
1522+ " WHERE capturecard.dtv_dev_id = dtv_device_tree.dtv_dev_id"
1523+ " AND capturecard.cardid = :CARDID");
1524+ query.bindValue(":CARDID", card_id);
1525+ if(query.exec() && query.isActive() && query.next())
1526+ needs_conf = (query.value(0).toString() != "lnb");
1527+ return needs_conf;
1528+}
1529+
1530+//////////////////////////////////////// DTVDeviceConfigWizard
1531+
1532+DTVDeviceConfigWizard::DTVDeviceConfigWizard(DVBDevSettings& settings,
1533+ unsigned int card_id)
1534+ : m_settings(settings)
1535+{
1536+ ConfigurationGroup* group =
1537+ new VerticalConfigurationGroup(false, false);
1538+ group->setLabel(QObject::tr("DTV Device Configuration"));
1539+
1540+ // load
1541+ m_tree.Load(card_id);
1542+
1543+ // initial UI setup
1544+ AddNodes(*group, m_tree.Root());
1545+ SelectNodes();
1546+
1547+ addChild(group);
1548+}
1549+
1550+DTVDeviceConfigWizard::~DTVDeviceConfigWizard()
1551+{
1552+}
1553+
1554+void DTVDeviceConfigWizard::AddNodes(ConfigurationGroup& group,
1555+ DVBDevDevice* node)
1556+{
1557+ if(node)
1558+ {
1559+ Setting* setting = NULL;
1560+ switch(node->GetDeviceType())
1561+ {
1562+ case DVBDEV_SWITCH:
1563+ setting = new SwitchSetting(*node, m_settings);
1564+ connect(setting, SIGNAL(valueChanged(const QString&)),
1565+ SLOT(SelectNodes()));
1566+ break;
1567+ case DVBDEV_ROTOR:
1568+ {
1569+ DVBDevRotor* rotor = dynamic_cast<DVBDevRotor*>(node);
1570+ if(rotor && rotor->GetType() == ROTOR_DISEQC_1_2)
1571+ setting = new RotorSetting(*node, m_settings);
1572+ else
1573+ setting = new USALSRotorSetting(*node, m_settings);
1574+ break;
1575+ }
1576+ default:
1577+ break;
1578+ }
1579+
1580+ if(setting)
1581+ {
1582+ // add this node
1583+ m_devs[node->DeviceID()] = setting;
1584+ group.addChild(setting);
1585+ }
1586+
1587+ // add children
1588+ unsigned int num_ch = node->NumChildren();
1589+ for(unsigned int ch = 0; ch < num_ch; ch++)
1590+ AddNodes(group, node->GetChild(ch));
1591+ }
1592+}
1593+
1594+void DTVDeviceConfigWizard::SelectNodes()
1595+{
1596+ save();
1597+
1598+ std::set<unsigned int> active;
1599+ DVBDevDevice* node = m_tree.Root();
1600+ while(node)
1601+ {
1602+ active.insert(node->DeviceID());
1603+ node = node->SelectedChild(m_settings);
1604+ }
1605+
1606+ for(DEVS::iterator i = m_devs.begin(); i != m_devs.end(); i++)
1607+ {
1608+ bool visible = active.find(i->first) != active.end();
1609+ i->second->setEnabled(visible);
1610+ }
1611+}
1612+
1613+//////////////////////////////////////// Database Upgrade
1614+
1615+enum OLD_DISEQC_TYPES
1616+{
1617+ DISEQC_SINGLE = 0,
1618+ DISEQC_MINI_2 = 1,
1619+ DISEQC_SWITCH_2_1_0 = 2,
1620+ DISEQC_SWITCH_2_1_1 = 3,
1621+ DISEQC_SWITCH_4_1_0 = 4,
1622+ DISEQC_SWITCH_4_1_1 = 5,
1623+ DISEQC_POSITIONER_1_2 = 6,
1624+ DISEQC_POSITIONER_X = 7,
1625+ DISEQC_POSITIONER_1_2_SWITCH_2 = 8,
1626+ DISEQC_POSITIONER_X_SWITCH_2 = 9,
1627+ DISEQC_SW21 = 10,
1628+ DISEQC_SW64 = 11,
1629+};
1630+
1631+bool DatabaseDiseqcUpgrade()
1632+{
1633+ bool success = true;
1634+ {
1635+ MSqlQuery query(MSqlQuery::InitCon());
1636+ query.prepare("CREATE TABLE dtv_device_config ("
1637+ "cardinputid int(11) unsigned NOT NULL,"
1638+ "dtv_dev_id int(11) unsigned NOT NULL,"
1639+ "value varchar(16) NOT NULL,"
1640+ "KEY id (cardinputid) )");
1641+ success = success && query.exec();
1642+ }
1643+ {
1644+ MSqlQuery query(MSqlQuery::InitCon());
1645+ query.prepare("CREATE TABLE dtv_device_tree ("
1646+ "dtv_dev_id int(11) unsigned NOT NULL auto_increment,"
1647+ "parent int(11) unsigned default NULL,"
1648+ "ordinal tinyint(3) unsigned NOT NULL,"
1649+ "dtv_dev_type varchar(16) NOT NULL,"
1650+ "dtv_dev_subtype varchar(16) NOT NULL,"
1651+ "dtv_dev_descr varchar(32),"
1652+ "switch_ports tinyint(3) unsigned default NULL,"
1653+ "rotor_hi_speed float default NULL,"
1654+ "rotor_lo_speed float default NULL,"
1655+ "rotor_positions varchar(256) default NULL,"
1656+ "lnb_lof_switch int(11) default NULL,"
1657+ "lnb_lof_hi int(11) default NULL,"
1658+ "lnb_lof_lo int(11) default NULL,"
1659+ "PRIMARY KEY (dtv_dev_id),"
1660+ "KEY parent (parent) )");
1661+ success = success && query.exec();
1662+ }
1663+ {
1664+ MSqlQuery query(MSqlQuery::InitCon());
1665+ query.prepare("ALTER TABLE capturecard"
1666+ " ADD dtv_dev_id int(10) unsigned default NULL");
1667+ success = success && query.exec();
1668+ }
1669+
1670+ /* Deprecated fields:
1671+ ALTER TABLE capturecard DROP dvb_diseqc_type;
1672+ ALTER TABLE cardinput DROP diseqc_port;
1673+ ALTER TABLE cardinput DROP diseqc_pos;
1674+ ALTER TABLE cardinput DROP lnb_lof_switch;
1675+ ALTER TABLE cardinput DROP lnb_lof_hi;
1676+ ALTER TABLE cardinput DROP lnb_lof_lo; */
1677+
1678+ return success;
1679+}
1680+
1681+// import old diseqc configuration into tree
1682+bool DatabaseDiseqcImport()
1683+{
1684+ MSqlQuery iquery(MSqlQuery::InitCon());
1685+
1686+ iquery.prepare("SELECT cardinputid, diseqc_port, diseqc_pos,"
1687+ " lnb_lof_switch, lnb_lof_hi, lnb_lof_lo"
1688+ " FROM cardinput"
1689+ " WHERE cardinput.cardid = :CARDID");
1690+
1691+ MSqlQuery cquery(MSqlQuery::InitCon());
1692+ cquery.prepare("SELECT cardid, dvb_diseqc_type FROM capturecard"
1693+ " WHERE dvb_diseqc_type IS NOT NULL AND"
1694+ " dtv_dev_id IS NULL");
1695+
1696+ // iterate through cards
1697+ if(!cquery.exec())
1698+ return false;
1699+ while(cquery.next())
1700+ {
1701+ unsigned cardid = cquery.value(0).toUInt();
1702+ OLD_DISEQC_TYPES type = (OLD_DISEQC_TYPES)cquery.value(1).toUInt();
1703+
1704+ DVBDevTree tree;
1705+ DVBDevDevice* root = NULL;
1706+ unsigned int add_lnbs = 0;
1707+ dvbdev_lnb_t lnb_type = LNB_VOLTAGE_TONE;
1708+
1709+ // create root of tree
1710+ switch(type)
1711+ {
1712+ case DISEQC_SINGLE:
1713+ {
1714+ // single LNB
1715+ root = DVBDevDevice::CreateByType(tree, DVBDEV_LNB);
1716+ break;
1717+ }
1718+
1719+ case DISEQC_MINI_2:
1720+ {
1721+ // tone switch + 2 LNBs
1722+ root = DVBDevDevice::CreateByType(tree, DVBDEV_SWITCH);
1723+ DVBDevSwitch* sw = dynamic_cast<DVBDevSwitch*>(root);
1724+ sw->SetType(SWITCH_TONE);
1725+ sw->SetNumPorts(2);
1726+ add_lnbs = 2;
1727+ break;
1728+ }
1729+
1730+ case DISEQC_SWITCH_2_1_0:
1731+ case DISEQC_SWITCH_2_1_1:
1732+ {
1733+ // 2 port diseqc + 2 LNBs
1734+ root = DVBDevDevice::CreateByType(tree, DVBDEV_SWITCH);
1735+ DVBDevSwitch* sw = dynamic_cast<DVBDevSwitch*>(root);
1736+ sw->SetType(SWITCH_DISEQC_COMMITTED);
1737+ sw->SetNumPorts(2);
1738+ add_lnbs = 2;
1739+ break;
1740+ }
1741+
1742+ case DISEQC_SWITCH_4_1_0:
1743+ case DISEQC_SWITCH_4_1_1:
1744+ {
1745+ // 4 port diseqc + 4 LNBs
1746+ root = DVBDevDevice::CreateByType(tree, DVBDEV_SWITCH);
1747+ DVBDevSwitch* sw = dynamic_cast<DVBDevSwitch*>(root);
1748+ sw->SetType(SWITCH_DISEQC_COMMITTED);
1749+ sw->SetNumPorts(4);
1750+ add_lnbs = 4;
1751+ break;
1752+ }
1753+
1754+ case DISEQC_POSITIONER_1_2:
1755+ {
1756+ // non-usals positioner + LNB
1757+ root = DVBDevDevice::CreateByType(tree, DVBDEV_ROTOR);
1758+ DVBDevRotor* rotor = dynamic_cast<DVBDevRotor*>(root);
1759+ rotor->SetType(ROTOR_DISEQC_1_2);
1760+ add_lnbs = 1;
1761+ break;
1762+ }
1763+
1764+ case DISEQC_POSITIONER_X:
1765+ {
1766+ // usals positioner + LNB (diseqc_pos)
1767+ root = DVBDevDevice::CreateByType(tree, DVBDEV_ROTOR);
1768+ DVBDevRotor* rotor = dynamic_cast<DVBDevRotor*>(root);
1769+ rotor->SetType(ROTOR_DISEQC_1_3);
1770+ add_lnbs = 1;
1771+ break;
1772+ }
1773+
1774+ case DISEQC_POSITIONER_1_2_SWITCH_2:
1775+ {
1776+ // 10 port uncommitted switch + 10 LNBs
1777+ root = DVBDevDevice::CreateByType(tree, DVBDEV_SWITCH);
1778+ DVBDevSwitch* sw = dynamic_cast<DVBDevSwitch*>(root);
1779+ sw->SetType(SWITCH_DISEQC_UNCOMMITTED);
1780+ sw->SetNumPorts(10);
1781+ add_lnbs = 10;
1782+ break;
1783+ }
1784+
1785+ case DISEQC_SW21:
1786+ {
1787+ // legacy SW21 + 2 fixed lnbs
1788+ root = DVBDevDevice::CreateByType(tree, DVBDEV_SWITCH);
1789+ DVBDevSwitch* sw = dynamic_cast<DVBDevSwitch*>(root);
1790+ sw->SetType(SWITCH_LEGACY_SW21);
1791+ sw->SetNumPorts(2);
1792+ add_lnbs = 2;
1793+ lnb_type = LNB_FIXED;
1794+ break;
1795+ }
1796+
1797+ case DISEQC_SW64:
1798+ {
1799+ // legacy SW64 + 3 fixed lnbs
1800+ root = DVBDevDevice::CreateByType(tree, DVBDEV_SWITCH);
1801+ DVBDevSwitch* sw = dynamic_cast<DVBDevSwitch*>(root);
1802+ sw->SetType(SWITCH_LEGACY_SW64);
1803+ sw->SetNumPorts(3);
1804+ add_lnbs = 3;
1805+ lnb_type = LNB_FIXED;
1806+ break;
1807+ }
1808+
1809+ default:
1810+ VERBOSE(VB_IMPORTANT, "Unknown DiSEqC device type, ignoring card");
1811+ break;
1812+ }
1813+ if(!root)
1814+ continue;
1815+ tree.SetRoot(root);
1816+
1817+ // create LNBs
1818+ for(unsigned int i=0; i < add_lnbs; i++)
1819+ {
1820+ DVBDevLnb* lnb = dynamic_cast<DVBDevLnb*>
1821+ (DVBDevDevice::CreateByType(tree, DVBDEV_LNB));
1822+ lnb->SetType(lnb_type);
1823+ lnb->SetDescription(QString("LNB #%1").arg(i+1));
1824+ if(!root->SetChild(i, lnb))
1825+ delete lnb;
1826+ }
1827+
1828+ // save the tree to get real device ids
1829+ tree.Store(cardid);
1830+
1831+ // iterate inputs
1832+ DVBDevSettings set;
1833+ iquery.bindValue(":CARDID", cardid);
1834+ if(!iquery.exec())
1835+ return false;
1836+ while(iquery.next())
1837+ {
1838+ unsigned int inputid = iquery.value(0).toUInt();
1839+ unsigned int port = iquery.value(1).toUInt();
1840+ double pos = iquery.value(2).toDouble();
1841+ DVBDevLnb* lnb = NULL;
1842+
1843+ // configure LNB and settings
1844+ switch(type)
1845+ {
1846+ case DISEQC_SINGLE:
1847+ lnb = dynamic_cast<DVBDevLnb*>(root);
1848+ break;
1849+
1850+ case DISEQC_MINI_2:
1851+ case DISEQC_SWITCH_2_1_0:
1852+ case DISEQC_SWITCH_2_1_1:
1853+ case DISEQC_SWITCH_4_1_0:
1854+ case DISEQC_SWITCH_4_1_1:
1855+ case DISEQC_SW21:
1856+ case DISEQC_SW64:
1857+ case DISEQC_POSITIONER_1_2_SWITCH_2:
1858+ lnb = dynamic_cast<DVBDevLnb*>(root->GetChild(port));
1859+ set.SetValue(root->DeviceID(), port);
1860+ break;
1861+
1862+ case DISEQC_POSITIONER_1_2:
1863+ case DISEQC_POSITIONER_X:
1864+ lnb = dynamic_cast<DVBDevLnb*>(root->GetChild(0));
1865+ set.SetValue(root->DeviceID(), pos);
1866+ break;
1867+
1868+ default:
1869+ break;
1870+ }
1871+
1872+ // configure lnb
1873+ if(lnb)
1874+ {
1875+ lnb->SetLOFSwitch(iquery.value(3).toUInt());
1876+ lnb->SetLOFHigh(iquery.value(4).toUInt());
1877+ lnb->SetLOFLow(iquery.value(5).toUInt());
1878+ }
1879+
1880+ // save settings
1881+ set.Store(inputid);
1882+ }
1883+
1884+ // save any LNB changes
1885+ tree.Store(cardid);
1886+
1887+ // invalidate cached devices
1888+ DVBDev trees;
1889+ trees.InvalidateTrees();
1890+ }
1891+
1892+ return true;
1893+}
1894Index: libs/libmythtv/siscan.cpp
1895===================================================================
1896--- libs/libmythtv/siscan.cpp (revision 10186)
1897+++ libs/libmythtv/siscan.cpp (working copy)
1898@@ -376,7 +376,7 @@
1899 bool wait_until_complete)
1900 {
1901 const DVBStreamData &dsd = (const DVBStreamData &)(*sd);
1902- if (wait_until_complete && !dsd.HasCachedSDT() && !dsd.HasCachedAllNIT())
1903+ if (wait_until_complete && (!dsd.HasCachedSDT() || !dsd.HasCachedAllNIT()))
1904 return;
1905
1906 emit ServiceScanUpdateText(tr("Updating Services"));
1907@@ -619,15 +619,18 @@
1908 // Tune to multiplex
1909 if (GetDVBChannel())
1910 {
1911+ // always wait for rotor to finish
1912+ GetDVBSignalMonitor()->AddFlags(kDVBSigMon_WaitForPos);
1913+
1914 if (item.mplexid > 0)
1915 {
1916- ok = GetDVBChannel()->TuneMultiplex(item.mplexid);
1917+ ok = GetDVBChannel()->TuneMultiplex(item.mplexid, item.SourceID);
1918 }
1919 else
1920 {
1921 DVBTuning tuning = item.tuning;
1922 tuning.params.frequency = freq;
1923- ok = GetDVBChannel()->Tune(tuning, true);
1924+ ok = GetDVBChannel()->Tune(tuning, true, item.SourceID);
1925 }
1926 }
1927 #endif // USING_DVB
1928@@ -827,10 +830,7 @@
1929 ok = tuning.parseQPSK(
1930 startChan["frequency"], startChan["inversion"],
1931 startChan["symbolrate"], startChan["fec"],
1932- startChan["polarity"],
1933- startChan["diseqc_type"], startChan["diseqc_port"],
1934- startChan["diseqc_pos"], startChan["lnb_lof_switch"],
1935- startChan["lnb_lof_hi"], startChan["lnb_lof_lo"]);
1936+ startChan["polarity"]);
1937 }
1938 else if (std == "dvb" && mod.left(3) == "qam")
1939 {
1940@@ -1340,6 +1340,30 @@
1941 QString::null /*inner FEC*/,tuning.ConstellationDB(),
1942 tuning.HierarchyChar(), tuning.HPCodeRateString(),
1943 tuning.LPCodeRateString(), tuning.GuardIntervalString());
1944+ else if (FE_QPSK == GetDVBChannel()->GetCardType())
1945+ mplexid = ChannelUtil::CreateMultiplex(
1946+ (*transport).SourceID, (*transport).standard,
1947+ tuning.Frequency(), (*transport).ModulationDB(),
1948+ sm->GetDetectedTransportID(),
1949+ sm->GetDetectedNetworkID(),
1950+ tuning.QPSKSymbolRate(), -1,
1951+ tuning.PolarityChar(), tuning.InversionChar(),
1952+ -1,
1953+ tuning.QPSKInnerFECString(),QString::null,
1954+ -1, QString::null,
1955+ QString::null, QString::null);
1956+ else if (FE_QAM == GetDVBChannel()->GetCardType())
1957+ mplexid = ChannelUtil::CreateMultiplex(
1958+ (*transport).SourceID, (*transport).standard,
1959+ tuning.Frequency(), tuning.ModulationString(),
1960+ sm->GetDetectedTransportID(),
1961+ sm->GetDetectedNetworkID(),
1962+ tuning.QAMSymbolRate(), -1,
1963+ -1, -1,
1964+ -1,
1965+ tuning.QAMInnerFECString(), QString::null,
1966+ -1, QString::null,
1967+ QString::null, QString::null);
1968 else
1969 mplexid = ChannelUtil::CreateMultiplex(
1970 (*transport).SourceID, (*transport).standard,
1971Index: libs/libmythtv/dvbchannel.h
1972===================================================================
1973--- libs/libmythtv/dvbchannel.h (revision 10186)
1974+++ libs/libmythtv/dvbchannel.h (working copy)
1975@@ -19,6 +19,7 @@
1976
1977 #ifdef USING_DVB
1978 #include "dvbtypes.h"
1979+#include "dvbdevtree.h"
1980 #else // if !USING_DVB
1981 typedef int fe_type_t;
1982 typedef int fe_modulation_t;
1983@@ -30,7 +31,6 @@
1984 class TVRec;
1985 class DVBCam;
1986 class DVBRecorder;
1987-class DVBDiSEqC;
1988
1989 class DVBChannel : public ChannelBase
1990 {
1991@@ -64,15 +64,30 @@
1992 bool SwitchToInput(const QString &inputname, const QString &chan);
1993 bool SwitchToInput(int newcapchannel, bool setstarting);
1994 bool SetChannelByString(const QString &chan);
1995- bool Tune(const DVBTuning &tuning, bool force_reset = false);
1996- bool TuneMultiplex(uint mplexid);
1997
1998+ // Tuning
1999+ bool Tune(const DVBTuning &tuning,
2000+ bool force_reset = false,
2001+ int sourceid = -1,
2002+ bool same_input = false);
2003+ bool TuneMultiplex(uint mplexid, int sourceid = -1);
2004+ bool Retune();
2005+
2006 bool GetTuningParams(DVBTuning &tuning) const;
2007
2008 // PID caching
2009 void SaveCachedPids(const pid_cache_t&) const;
2010 void GetCachedPids(pid_cache_t&) const;
2011
2012+ // Returns rotor object (or NULL)
2013+ const DVBDevRotor* GetRotor() const;
2014+
2015+ // If false, card needs retuning when lock is lost
2016+ bool CanRecover() const;
2017+
2018+ // Amount of time since last tuning request
2019+ int ElapsedSinceTune() const;
2020+
2021 private:
2022 int GetChanID(void) const;
2023 bool GetTransportOptions(int mplexid);
2024@@ -85,16 +100,18 @@
2025 bool ParseTuningParams(
2026 fe_type_t type,
2027 QString frequency, QString inversion, QString symbolrate,
2028- QString fec, QString polarity, QString dvb_diseqc_type,
2029- QString diseqc_port, QString diseqc_pos, QString lnb_lof_switch,
2030- QString lnb_lof_hi, QString lnb_lof_lo, QString _sistandard,
2031+ QString fec, QString polarity, QString _sistandard,
2032 QString hp_code_rate, QString lp_code_rate, QString constellation,
2033 QString trans_mode, QString guard_interval, QString hierarchy,
2034 QString modulation, QString bandwidth, QString _input_id);
2035
2036 private:
2037+#ifdef USING_DVB
2038 // Data
2039- DVBDiSEqC *diseqc; ///< Used to send commands to external devices
2040+ DVBDev dvbdev;
2041+ DVBDevTree* devtree;
2042+ DVBDevSettings devset;
2043+#endif
2044 DVBCam *dvbcam; ///< Used to decrypt encrypted streams
2045
2046 // Tuning State
2047@@ -113,6 +130,9 @@
2048 int cardnum; ///< DVB Card number
2049 bool has_crc_bug; ///< true iff our driver munges PMT
2050 int nextInputID; ///< Signal an input change
2051+
2052+ QTime tune_time;
2053+ QMutex tune_lock;
2054 };
2055
2056 #endif
2057Index: libs/libmythtv/dvbdevtree.cpp
2058===================================================================
2059--- libs/libmythtv/dvbdevtree.cpp (revision 0)
2060+++ libs/libmythtv/dvbdevtree.cpp (revision 0)
2061@@ -0,0 +1,1563 @@
2062+/*
2063+ * \file dvbdevtree.cpp
2064+ * \brief DVB-S Device Tree Control Classes.
2065+ * \author Copyright (C) 2006, Yeasah Pell
2066+ */
2067+
2068+#include <sys/time.h>
2069+#include <string.h>
2070+#include <cmath>
2071+#include "mythcontext.h"
2072+#include "mythdbcon.h"
2073+#include "dvbtypes.h"
2074+#include "dvbdevtree.h"
2075+
2076+#define LOC QString("DVBDevTree: ")
2077+#define LOC_ERR QString("DVBDevTree: ")
2078+
2079+//////////////////////////////////////// DVBDevSettings
2080+
2081+DVBDevSettings::DVBDevSettings()
2082+ : m_input_id((unsigned int)-1)
2083+{
2084+}
2085+
2086+bool DVBDevSettings::Load(unsigned int card_input_id)
2087+{
2088+ if(card_input_id != m_input_id)
2089+ {
2090+ m_config.clear();
2091+
2092+ // load settings from DB
2093+ MSqlQuery query(MSqlQuery::InitCon());
2094+ query.prepare("SELECT dtv_dev_id, value "
2095+ "FROM dtv_device_config "
2096+ "WHERE cardinputid = :INPUTID");
2097+ query.bindValue(":INPUTID", card_input_id);
2098+ if(query.exec() && query.isActive())
2099+ while(query.next())
2100+ m_config[query.value(0).toInt()] = query.value(1).toDouble();
2101+
2102+ m_input_id = card_input_id;
2103+ }
2104+
2105+ return true;
2106+}
2107+
2108+bool DVBDevSettings::Store(unsigned int card_input_id) const
2109+{
2110+ {
2111+ // clear out previous settings
2112+ MSqlQuery query(MSqlQuery::InitCon());
2113+ query.prepare("DELETE from dtv_device_config"
2114+ " WHERE cardinputid = :INPUTID");
2115+ query.bindValue(":INPUTID", card_input_id);
2116+ if(!query.exec())
2117+ return false;
2118+ }
2119+
2120+ {
2121+ // insert new settings
2122+ MSqlQuery query(MSqlQuery::InitCon());
2123+ query.prepare("INSERT INTO dtv_device_config"
2124+ " (cardinputid, dtv_dev_id, value) VALUES"
2125+ " (:INPUTID, :DEV_ID, :VALUE)");
2126+ for(CONFIG::const_iterator i = m_config.begin(); i != m_config.end(); i++)
2127+ {
2128+ query.bindValue(":INPUTID", card_input_id);
2129+ query.bindValue(":DEV_ID", i->first);
2130+ query.bindValue(":VALUE", i->second);
2131+ if(!query.exec())
2132+ return false;
2133+ }
2134+ }
2135+
2136+ return true;
2137+}
2138+
2139+double DVBDevSettings::GetValue(int dtv_dev_id) const
2140+{
2141+ double ret = 0.0;
2142+ CONFIG::const_iterator cfg = m_config.find(dtv_dev_id);
2143+ if(cfg != m_config.end())
2144+ ret = cfg->second;
2145+ return ret;
2146+}
2147+
2148+void DVBDevSettings::SetValue(int dtv_dev_id, double value)
2149+{
2150+ m_config[dtv_dev_id] = value;
2151+ m_input_id = (unsigned int)-1;
2152+}
2153+
2154+//////////////////////////////////////// DVBDev
2155+
2156+DVBDevTree* DVBDev::FindTree(unsigned int card_id)
2157+{
2158+ return m_trees.FindTree(card_id);
2159+}
2160+
2161+void DVBDev::InvalidateTrees()
2162+{
2163+ m_trees.InvalidateTrees();
2164+}
2165+
2166+DVBDevTrees DVBDev::m_trees;
2167+
2168+//////////////////////////////////////// DVBDevTrees
2169+
2170+DVBDevTrees::~DVBDevTrees()
2171+{
2172+ InvalidateTrees();
2173+}
2174+
2175+DVBDevTree* DVBDevTrees::FindTree(unsigned int card_id)
2176+{
2177+ QMutexLocker lock(&m_trees_lock);
2178+
2179+ DVBDevTree* tree = NULL;
2180+ TREES::iterator i = m_trees.find(card_id);
2181+ if(i == m_trees.end())
2182+ {
2183+ tree = new DVBDevTree;
2184+ tree->Load(card_id);
2185+ m_trees.insert(std::make_pair(card_id, tree));
2186+ }
2187+ else
2188+ tree = i->second;
2189+ return tree;
2190+}
2191+
2192+void DVBDevTrees::InvalidateTrees()
2193+{
2194+ QMutexLocker lock(&m_trees_lock);
2195+ for(TREES::iterator i = m_trees.begin(); i != m_trees.end(); i++)
2196+ delete i->second;
2197+ m_trees.clear();
2198+}
2199+
2200+//////////////////////////////////////// DVBDevTree
2201+
2202+DVBDevTree::DVBDevTree()
2203+ : m_fd_frontend(-1), m_root(NULL), m_next_cnt(0)
2204+{
2205+ Reset();
2206+}
2207+
2208+DVBDevTree::~DVBDevTree()
2209+{
2210+ delete m_root;
2211+}
2212+
2213+bool DVBDevTree::Load(unsigned int card_id)
2214+{
2215+ // clear children
2216+ delete m_root;
2217+ m_delete.clear();
2218+ m_root = NULL;
2219+
2220+ // lookup configuration for this card
2221+ MSqlQuery query(MSqlQuery::InitCon());
2222+ query.prepare("SELECT dtv_dev_id FROM capturecard "
2223+ "WHERE cardid = :CARDID");
2224+ query.bindValue(":CARDID", card_id);
2225+
2226+ if(query.exec() && query.next())
2227+ m_root = DVBDevDevice::CreateById(*this, query.value(0).toInt());
2228+ else
2229+ VERBOSE(VB_IMPORTANT, LOC_ERR +
2230+ QString("No device tree for cardid %1").arg(card_id));
2231+
2232+ return m_root != NULL;
2233+}
2234+
2235+bool DVBDevTree::Store(unsigned int card_id)
2236+{
2237+ // apply pending node deletions
2238+ if(!m_delete.empty())
2239+ {
2240+ MSqlQuery query(MSqlQuery::InitCon());
2241+ query.prepare("DELETE FROM dtv_device_tree WHERE dtv_dev_id = :DEVID");
2242+ MSqlQuery squery(MSqlQuery::InitCon());
2243+ squery.prepare("DELETE FROM dtv_device_config WHERE dtv_dev_id = :DEVID");
2244+ for(list<unsigned int>::const_iterator i = m_delete.begin(); i != m_delete.end(); i++)
2245+ {
2246+ query.bindValue(":DEVID", *i);
2247+ query.exec();
2248+ squery.bindValue(":DEVID", *i);
2249+ squery.exec();
2250+ }
2251+ m_delete.clear();
2252+ }
2253+
2254+ // store changed and new nodes
2255+ bool success = true;
2256+ if(m_root)
2257+ success = m_root->Store();
2258+ MSqlQuery query(MSqlQuery::InitCon());
2259+ query.prepare("UPDATE capturecard"
2260+ " SET dtv_dev_id = :DEVID"
2261+ " WHERE cardid = :CARDID");
2262+ if(m_root)
2263+ query.bindValue(":DEVID", m_root->DeviceID());
2264+ query.bindValue(":CARDID", card_id);
2265+ return success && query.exec();
2266+}
2267+
2268+bool DVBDevTree::SetTone(bool on)
2269+{
2270+ bool success = false;
2271+ for(unsigned int retry = 0; !success && retry < TIMEOUT_RETRIES; retry++)
2272+ {
2273+ if (ioctl(m_fd_frontend, FE_SET_TONE,
2274+ on ? SEC_TONE_ON : SEC_TONE_OFF) == 0)
2275+ success = true;
2276+ else
2277+ usleep(DISEQC_SHORT_WAIT);
2278+ }
2279+ if(!success)
2280+ VERBOSE(VB_IMPORTANT, LOC_ERR + "FE_SET_TONE failed" + ENO);
2281+ return success;
2282+}
2283+
2284+bool DVBDevTree::MiniDiseqc(fe_sec_mini_cmd cmd)
2285+{
2286+ bool success = false;
2287+ for(unsigned int retry = 0; !success && retry < TIMEOUT_RETRIES; retry++)
2288+ {
2289+ if (ioctl(m_fd_frontend, FE_DISEQC_SEND_BURST, cmd) == 0)
2290+ success = true;
2291+ else
2292+ usleep(DISEQC_SHORT_WAIT);
2293+ }
2294+ if(!success)
2295+ VERBOSE(VB_IMPORTANT, LOC_ERR + "FE_DISEQC_SEND_BURST failed" + ENO);
2296+ return success;
2297+}
2298+
2299+bool DVBDevTree::SendDiseqc(const dvb_diseqc_master_cmd& cmd)
2300+{
2301+ bool success = false;
2302+ for(unsigned int retry = 0; !success && retry < TIMEOUT_RETRIES; retry++)
2303+ {
2304+ if (ioctl(m_fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) == 0)
2305+ success = true;
2306+ else
2307+ usleep(DISEQC_SHORT_WAIT);
2308+ }
2309+ if(!success)
2310+ VERBOSE(VB_IMPORTANT, LOC_ERR +
2311+ "FE_DISEQC_SEND_MASTER_CMD failed" + ENO);
2312+ return success;
2313+}
2314+
2315+bool DVBDevTree::Execute(const DVBDevSettings& settings,
2316+ const DVBTuning& tuning)
2317+{
2318+ if(m_root)
2319+ {
2320+ // apply any voltage change
2321+ ApplyVoltage(settings, tuning);
2322+
2323+ // turn off tone burst first if commands need to be sent
2324+ if(m_root->NeedsCommand(settings))
2325+ {
2326+ SetTone(false);
2327+ usleep(DISEQC_SHORT_WAIT);
2328+ }
2329+
2330+ return m_root->Execute(settings, tuning);
2331+ }
2332+ else
2333+ {
2334+ VERBOSE(VB_IMPORTANT, LOC_ERR + "No root device tree node!");
2335+ return false;
2336+ }
2337+}
2338+
2339+void DVBDevTree::Reset()
2340+{
2341+ if(m_root)
2342+ m_root->Reset();
2343+ m_last_voltage = (fe_sec_voltage)-1;
2344+}
2345+
2346+DVBDevRotor* DVBDevTree::FindRotor(const DVBDevSettings& settings,
2347+ unsigned int index)
2348+{
2349+ DVBDevRotor* rotor = NULL;
2350+ DVBDevDevice* node = m_root;
2351+ unsigned int count = 0;
2352+ while(node)
2353+ {
2354+ rotor = dynamic_cast<DVBDevRotor*>(node);
2355+ if(rotor && ++count > index)
2356+ break;
2357+ node = node->SelectedChild(settings);
2358+ }
2359+ return rotor;
2360+}
2361+
2362+DVBDevLnb* DVBDevTree::FindLNB(const DVBDevSettings& settings)
2363+{
2364+ DVBDevLnb* lnb = NULL;
2365+ DVBDevDevice* node = m_root;
2366+ while(node)
2367+ {
2368+ lnb = dynamic_cast<DVBDevLnb*>(node);
2369+ if(lnb)
2370+ break;
2371+ node = node->SelectedChild(settings);
2372+ }
2373+ return lnb;
2374+}
2375+
2376+DVBDevDevice* DVBDevTree::FindDevice(int dev_id)
2377+{
2378+ DVBDevDevice* dev = NULL;
2379+ if(m_root)
2380+ dev = m_root->FindDevice(dev_id);
2381+ return dev;
2382+}
2383+
2384+void DVBDevTree::SetRoot(DVBDevDevice* root)
2385+{
2386+ delete m_root;
2387+ m_root = root;
2388+}
2389+
2390+bool DVBDevTree::SendCommand(unsigned int adr,
2391+ unsigned int cmd,
2392+ unsigned int repeats,
2393+ unsigned int data_len,
2394+ unsigned char* data)
2395+{
2396+ // check payload validity
2397+ if(data_len > 3 || (data_len > 0 && data == NULL))
2398+ {
2399+ VERBOSE(VB_IMPORTANT, LOC_ERR + "Bad DiSEqC command");
2400+ return false;
2401+ }
2402+
2403+ // prepare command
2404+ dvb_diseqc_master_cmd mcmd;
2405+ mcmd.msg[0] = DISEQC_FRM;
2406+ mcmd.msg[1] = adr;
2407+ mcmd.msg[2] = cmd;
2408+ mcmd.msg_len = data_len + 3;
2409+ if(data_len > 0)
2410+ memcpy(mcmd.msg+3, data, data_len);
2411+
2412+ // diagnostic
2413+ QString cmdstr;
2414+ for(unsigned int byte = 0; byte < mcmd.msg_len; byte++)
2415+ cmdstr += QString("%1 ").arg(mcmd.msg[byte], 2, 16);
2416+ VERBOSE(VB_CHANNEL, LOC + "Sending DiSEqC Command: " + cmdstr);
2417+
2418+ // send the command
2419+ for(unsigned int i = 0; i <= repeats; i++)
2420+ {
2421+ if (!SendDiseqc(mcmd))
2422+ {
2423+ VERBOSE(VB_IMPORTANT, LOC_ERR + "DiSEqC command failed" + ENO);
2424+ return false;
2425+ }
2426+ mcmd.msg[0] |= DISEQC_FRM_REPEAT;
2427+ usleep(DISEQC_SHORT_WAIT);
2428+ }
2429+
2430+ return true;
2431+}
2432+
2433+bool DVBDevTree::ResetDiseqc(bool hard_reset)
2434+{
2435+ Reset();
2436+
2437+ VERBOSE(VB_CHANNEL, LOC + "Resetting DiSEqC Bus");
2438+
2439+ // issue a global reset command
2440+ if(!SendCommand(DISEQC_ADR_ALL, DISEQC_CMD_RESET))
2441+ {
2442+ VERBOSE(VB_IMPORTANT, LOC_ERR +
2443+ "DiSEqC reset failed" + ENO);
2444+ return false;
2445+ }
2446+ usleep(DISEQC_LONG_WAIT);
2447+
2448+ // power cycle the bus if requested
2449+ if(hard_reset)
2450+ {
2451+ VERBOSE(VB_CHANNEL, LOC + "Power-cycling DiSEqC Bus");
2452+ SetVoltage(SEC_VOLTAGE_OFF);
2453+ usleep(DISEQC_LONG_WAIT);
2454+ SetVoltage(SEC_VOLTAGE_18);
2455+ usleep(DISEQC_LONG_WAIT);
2456+ }
2457+
2458+ return true;
2459+}
2460+
2461+void DVBDevTree::Open(int fd_frontend)
2462+{
2463+ m_fd_frontend = fd_frontend;
2464+ ResetDiseqc(true);
2465+}
2466+
2467+bool DVBDevTree::SetVoltage(fe_sec_voltage voltage)
2468+{
2469+ bool success = true;
2470+ if(voltage != m_last_voltage)
2471+ {
2472+ int volts = 0;
2473+ if(voltage == SEC_VOLTAGE_18)
2474+ volts = 18;
2475+ else if(voltage == SEC_VOLTAGE_13)
2476+ volts = 13;
2477+ VERBOSE(VB_CHANNEL, LOC +
2478+ QString("Changing LNB voltage to %1V").arg(volts));
2479+
2480+ success = false;
2481+ for(unsigned int retry = 0; !success && retry < TIMEOUT_RETRIES; retry++)
2482+ {
2483+ if (ioctl(m_fd_frontend, FE_SET_VOLTAGE, voltage) == 0)
2484+ success = true;
2485+ else
2486+ usleep(DISEQC_SHORT_WAIT);
2487+ }
2488+
2489+ if(!success)
2490+ VERBOSE(VB_IMPORTANT, LOC_ERR + "FE_SET_VOLTAGE failed" + ENO);
2491+ else
2492+ m_last_voltage = voltage;
2493+ }
2494+
2495+ return success;
2496+}
2497+
2498+bool DVBDevTree::ApplyVoltage(const DVBDevSettings& settings,
2499+ const DVBTuning& tuning)
2500+{
2501+ fe_sec_voltage voltage = SEC_VOLTAGE_18;
2502+ if(m_root)
2503+ voltage = m_root->GetVoltage(settings, tuning);
2504+ return SetVoltage(voltage);
2505+}
2506+
2507+//////////////////////////////////////// DVBDevDevice
2508+
2509+DVBDevDevice::DVBDevDevice(DVBDevTree& tree, int dtv_dev_id)
2510+ : m_dtv_dev_id(dtv_dev_id), m_tree(tree), m_parent(NULL), m_ordinal(0),
2511+ m_repeat(0)
2512+{
2513+}
2514+
2515+DVBDevDevice::~DVBDevDevice()
2516+{
2517+ if(DeviceID() >= 0)
2518+ m_tree.AddDeferredDelete(DeviceID());
2519+}
2520+
2521+DVBDevDevice* DVBDevDevice::FindDevice(int dev_id)
2522+{
2523+ DVBDevDevice* dev = NULL;
2524+
2525+ if(m_dtv_dev_id == dev_id)
2526+ dev = this;
2527+
2528+ unsigned int num_children = NumChildren();
2529+ for(unsigned int ch = 0; !dev && ch < num_children; ch++)
2530+ {
2531+ DVBDevDevice* child = GetChild(ch);
2532+ if(child)
2533+ {
2534+ if(child->DeviceID() == dev_id)
2535+ dev = child;
2536+ else
2537+ dev = child->FindDevice(dev_id);
2538+ }
2539+ }
2540+ return dev;
2541+}
2542+
2543+DVBDevDevice* DVBDevDevice::CreateById(DVBDevTree& tree,
2544+ int dtv_dev_id)
2545+{
2546+ DVBDevDevice* node = NULL;
2547+
2548+ // load settings from DB
2549+ MSqlQuery query(MSqlQuery::InitCon());
2550+ query.prepare("SELECT dtv_dev_type, dtv_dev_descr"
2551+ " FROM dtv_device_tree"
2552+ " WHERE dtv_dev_id = :DTV_DEV_ID");
2553+ query.bindValue(":DTV_DEV_ID", dtv_dev_id);
2554+
2555+ if(query.exec() && query.next())
2556+ {
2557+ dvbdev_t type = DevTypeFromString(query.value(0).toString());
2558+ node = CreateByType(tree, type, dtv_dev_id);
2559+
2560+ QString descr = query.value(1).toString();
2561+ if(node)
2562+ {
2563+ node->SetDescription(descr);
2564+ node->Load();
2565+ }
2566+ }
2567+
2568+ return node;
2569+}
2570+
2571+DVBDevDevice* DVBDevDevice::CreateByType(DVBDevTree& tree,
2572+ dvbdev_t type,
2573+ int dev_id)
2574+{
2575+ if(dev_id == -1)
2576+ dev_id = tree.NextFakeID();
2577+
2578+ DVBDevDevice* node = NULL;
2579+ switch(type)
2580+ {
2581+ case DVBDEV_SWITCH:
2582+ node = new DVBDevSwitch(tree, dev_id);
2583+ if(node)
2584+ node->SetDescription("Switch");
2585+ break;
2586+ case DVBDEV_ROTOR:
2587+ node = new DVBDevRotor(tree, dev_id);
2588+ if(node)
2589+ node->SetDescription("Rotor");
2590+ break;
2591+ case DVBDEV_LNB:
2592+ node = new DVBDevLnb(tree, dev_id);
2593+ if(node)
2594+ node->SetDescription("LNB");
2595+ break;
2596+ default:
2597+ break;
2598+ }
2599+ if(node)
2600+ node->SetDeviceType(type);
2601+ return node;
2602+}
2603+
2604+//////////////////////////////////////// DVBDevSwitch
2605+
2606+DVBDevSwitch::DVBDevSwitch(DVBDevTree& tree,
2607+ int dtv_dev_id)
2608+ : DVBDevDevice(tree, dtv_dev_id),
2609+ m_type(SWITCH_TONE), m_num_ports(2)
2610+{
2611+ m_children.resize(m_num_ports);
2612+ for(unsigned int i = 0; i < m_num_ports; i++)
2613+ m_children[i] = NULL;
2614+ Reset();
2615+}
2616+
2617+DVBDevSwitch::~DVBDevSwitch()
2618+{
2619+ for(CHILDREN::iterator i = m_children.begin(); i != m_children.end(); i++)
2620+ delete *i;
2621+}
2622+
2623+bool DVBDevSwitch::Execute(const DVBDevSettings& settings,
2624+ const DVBTuning& tuning)
2625+{
2626+ bool success = true;
2627+
2628+ // sanity check switch position
2629+ unsigned int pos;
2630+ if(!GetPosition(settings, pos))
2631+ return false;
2632+
2633+ // determine if switch command needs to be sent based on last pos
2634+ if(m_last_pos != pos)
2635+ {
2636+ // perform switching
2637+ switch(m_type)
2638+ {
2639+ case SWITCH_TONE:
2640+ success = ExecuteTone(settings, tuning, pos);
2641+ break;
2642+ case SWITCH_DISEQC_COMMITTED:
2643+ case SWITCH_DISEQC_UNCOMMITTED:
2644+ success = ExecuteDiseqc(settings, tuning, pos);
2645+ break;
2646+ case SWITCH_LEGACY_SW21:
2647+ case SWITCH_LEGACY_SW42:
2648+ case SWITCH_LEGACY_SW64:
2649+ success = ExecuteLegacy(settings, tuning, pos);
2650+ break;
2651+ default:
2652+ success = false;
2653+ VERBOSE(VB_IMPORTANT, LOC_ERR +
2654+ QString("Unknown switch type (%1)")
2655+ .arg((unsigned int)m_type));
2656+ break;
2657+ }
2658+
2659+ // if a child device will be sending a diseqc command, wait 100ms
2660+ if(m_children[pos]->NeedsCommand(settings))
2661+ {
2662+ VERBOSE(VB_CHANNEL, LOC + "Waiting for switch");
2663+ usleep(DISEQC_LONG_WAIT);
2664+ }
2665+
2666+ m_last_pos = pos;
2667+ }
2668+
2669+ // chain to child if the switch was successful
2670+ if(success)
2671+ success = m_children[pos]->Execute(settings, tuning);
2672+
2673+ return success;
2674+}
2675+
2676+void DVBDevSwitch::Reset()
2677+{
2678+ m_last_pos = (unsigned int)-1;
2679+ for(CHILDREN::iterator i = m_children.begin(); i != m_children.end(); i++)
2680+ if(*i)
2681+ (*i)->Reset();
2682+}
2683+
2684+bool DVBDevSwitch::NeedsCommand(const DVBDevSettings& settings) const
2685+{
2686+ // sanity check switch position
2687+ unsigned int pos;
2688+ if(!GetPosition(settings, pos))
2689+ return false;
2690+
2691+ // if position is changing, a command is definitely needed
2692+ if(pos != m_last_pos)
2693+ return true;
2694+
2695+ // otherwise, the child that will be selected may need a command
2696+ else
2697+ return m_children[pos]->NeedsCommand(settings);
2698+}
2699+
2700+DVBDevDevice* DVBDevSwitch::SelectedChild(const DVBDevSettings& settings) const
2701+{
2702+ DVBDevDevice* child = NULL;
2703+ unsigned int pos;
2704+ if(GetPosition(settings, pos))
2705+ child = m_children[pos];
2706+ return child;
2707+}
2708+
2709+unsigned int DVBDevSwitch::NumChildren() const
2710+{
2711+ return m_num_ports;
2712+}
2713+
2714+DVBDevDevice* DVBDevSwitch::GetChild(unsigned int ordinal)
2715+{
2716+ if(ordinal < m_children.size())
2717+ return m_children[ordinal];
2718+ else
2719+ return NULL;
2720+}
2721+
2722+bool DVBDevSwitch::SetChild(unsigned int ordinal, DVBDevDevice* device)
2723+{
2724+ if(ordinal < m_children.size())
2725+ {
2726+ delete m_children[ordinal];
2727+ m_children[ordinal] = device;
2728+ if(device)
2729+ {
2730+ device->SetOrdinal(ordinal);
2731+ device->SetParent(this);
2732+ }
2733+ return true;
2734+ }
2735+ return false;
2736+}
2737+
2738+fe_sec_voltage DVBDevSwitch::GetVoltage(const DVBDevSettings& settings,
2739+ const DVBTuning& tuning) const
2740+{
2741+ fe_sec_voltage voltage = SEC_VOLTAGE_18;
2742+ DVBDevDevice* child = SelectedChild(settings);
2743+ if(child)
2744+ voltage = child->GetVoltage(settings, tuning);
2745+ return voltage;
2746+}
2747+
2748+bool DVBDevSwitch::Load()
2749+{
2750+ // clear old children
2751+ for(CHILDREN::iterator i = m_children.begin(); i != m_children.end(); i++)
2752+ delete *i;
2753+ m_children.clear();
2754+
2755+ // populate switch parameters from db
2756+ {
2757+ MSqlQuery query(MSqlQuery::InitCon());
2758+ query.prepare("SELECT dtv_dev_subtype, switch_ports"
2759+ " FROM dtv_device_tree"
2760+ " WHERE dtv_dev_id = :DTV_DEV_ID");
2761+ query.bindValue(":DTV_DEV_ID", DeviceID());
2762+
2763+ if(query.exec() && query.next())
2764+ {
2765+ m_type = SwitchTypeFromString(query.value(0).toString());
2766+ m_num_ports = query.value(1).toInt();
2767+ m_children.resize(m_num_ports);
2768+ for(unsigned int i=0; i < m_num_ports; i++)
2769+ m_children[i] = NULL;
2770+ }
2771+ }
2772+
2773+ // load children from db
2774+ {
2775+ MSqlQuery query(MSqlQuery::InitCon());
2776+ query.prepare("SELECT dtv_dev_id, ordinal FROM dtv_device_tree "
2777+ "WHERE parent = :DTV_DEV_ID");
2778+ query.bindValue(":DTV_DEV_ID", DeviceID());
2779+ if(query.exec())
2780+ {
2781+ while(query.next())
2782+ {
2783+ unsigned int child_dev_id = query.value(0).toInt();
2784+ unsigned int ordinal = query.value(1).toInt();
2785+ DVBDevDevice* child = CreateById(m_tree, child_dev_id);
2786+ if(!SetChild(ordinal, child))
2787+ {
2788+ VERBOSE(VB_IMPORTANT, LOC_ERR +
2789+ QString("Switch port out of range (%d > %d)")
2790+ .arg(ordinal + 1)
2791+ .arg(m_num_ports));
2792+ delete child;
2793+ }
2794+ }
2795+ }
2796+ }
2797+
2798+ return true;
2799+}
2800+
2801+bool DVBDevSwitch::Store()
2802+{
2803+ QString type = SwitchTypeToString(m_type);
2804+ MSqlQuery query(MSqlQuery::InitCon());
2805+
2806+ // insert new or update old
2807+ if(m_dtv_dev_id >= 0)
2808+ {
2809+ query.prepare("UPDATE dtv_device_tree"
2810+ " SET parent = :PARENT,"
2811+ " ordinal = :ORDINAL,"
2812+ " dtv_dev_type = 'switch',"
2813+ " dtv_dev_descr = :DESCR,"
2814+ " dtv_dev_subtype = :TYPE,"
2815+ " switch_ports = :PORTS"
2816+ " WHERE dtv_dev_id = :DTV_DEV_ID");
2817+ }
2818+ else
2819+ {
2820+ query.prepare("INSERT INTO dtv_device_tree"
2821+ " (parent, ordinal, dtv_dev_type, dtv_dev_descr,"
2822+ " dtv_dev_subtype, switch_ports)"
2823+ " VALUES (:PARENT, :ORDINAL, 'switch', :DESCR,"
2824+ " :TYPE, :PORTS)");
2825+ }
2826+ if(m_parent)
2827+ query.bindValue(":PARENT", m_parent->DeviceID());
2828+ query.bindValue(":ORDINAL", m_ordinal);
2829+ query.bindValue(":DESCR", GetDescription());
2830+ query.bindValue(":TYPE", type);
2831+ query.bindValue(":PORTS", m_num_ports);
2832+ query.bindValue(":DTV_DEV_ID", DeviceID());
2833+
2834+ // chain to children
2835+ bool success = query.exec();
2836+ if(success)
2837+ {
2838+ if(m_dtv_dev_id < 0)
2839+ m_dtv_dev_id = query.lastInsertId().toInt();
2840+ for(unsigned int ch = 0; ch < m_children.size(); ch++)
2841+ if(m_children[ch])
2842+ success = success && m_children[ch]->Store();
2843+ }
2844+
2845+ return success;
2846+}
2847+
2848+void DVBDevSwitch::SetNumPorts(unsigned int num_ports)
2849+{
2850+ unsigned int old_num = m_children.size();
2851+ if(old_num > num_ports)
2852+ {
2853+ for(unsigned int ch = num_ports; ch < old_num; ch++)
2854+ delete m_children[ch];
2855+ m_children.resize(num_ports);
2856+ }
2857+ else if(old_num < num_ports)
2858+ {
2859+ m_children.resize(num_ports);
2860+ for(unsigned int ch = old_num; ch < num_ports; ch++)
2861+ m_children[ch] = NULL;
2862+ }
2863+ m_num_ports = num_ports;
2864+}
2865+
2866+bool DVBDevSwitch::ExecuteLegacy(const DVBDevSettings& settings,
2867+ const DVBTuning& tuning,
2868+ unsigned int pos)
2869+{
2870+#ifdef FE_DISHNETWORK_SEND_LEGACY_CMD
2871+
2872+ static const unsigned char sw21_cmds[] = { 0x34, 0x65 };
2873+ static const unsigned char sw42_cmds[] = { 0x46, 0x17 };
2874+ static const unsigned char sw64_v_cmds[] = { 0x39, 0x4b, 0x0d };
2875+ static const unsigned char sw64_h_cmds[] = { 0x1a, 0x5c, 0x2e };
2876+
2877+ const unsigned char *cmds = NULL;
2878+ unsigned int num_ports = 0;
2879+
2880+ // determine polarity from lnb
2881+ bool horizontal = false;
2882+ DVBDevLnb* lnb = m_tree.FindLNB(settings);
2883+ if(lnb)
2884+ horizontal = lnb->IsHorizontal(tuning);
2885+
2886+ // get command table for this switch
2887+ switch (m_type)
2888+ {
2889+ case SWITCH_LEGACY_SW21:
2890+ cmds = sw21_cmds;
2891+ num_ports = 2;
2892+ break;
2893+ case SWITCH_LEGACY_SW42:
2894+ cmds = sw42_cmds;
2895+ num_ports = 2;
2896+ break;
2897+ case SWITCH_LEGACY_SW64:
2898+ if (horizontal)
2899+ cmds = sw64_h_cmds;
2900+ else
2901+ cmds = sw64_v_cmds;
2902+ num_ports = 3;
2903+ break;
2904+ default:
2905+ return false;
2906+ }
2907+ pos %= num_ports;
2908+
2909+ VERBOSE(VB_CHANNEL, LOC + QString("Changing to Legacy switch port %1/%2")
2910+ .arg(pos+1)
2911+ .arg(num_ports));
2912+
2913+ // send command
2914+ if (ioctl(m_tree.FrontendFD(), FE_DISHNETWORK_SEND_LEGACY_CMD, cmds[pos]) == -1)
2915+ {
2916+ VERBOSE(VB_IMPORTANT, LOC_ERR +
2917+ "FE_DISHNETWORK_SEND_LEGACY_CMD failed" + ENO);
2918+ return false;
2919+ }
2920+
2921+ return true;
2922+
2923+#else
2924+
2925+ VERBOSE(VB_IMPORTANT, LOC_ERR +
2926+ "DVB API does not support FE_DISHNETWORK_SEND_LEGACY_CMD.");
2927+ return false;
2928+
2929+#endif
2930+}
2931+
2932+bool DVBDevSwitch::ExecuteTone(const DVBDevSettings& /*settings*/,
2933+ const DVBTuning& /*tuning*/,
2934+ unsigned int pos)
2935+{
2936+ VERBOSE(VB_CHANNEL, LOC + QString("Changing to Tone switch port %1/2")
2937+ .arg(pos+1));
2938+
2939+ bool success = m_tree.MiniDiseqc(pos == 0 ? SEC_MINI_A : SEC_MINI_B);
2940+ if(!success)
2941+ VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting Tone Switch failed." + ENO);
2942+ return success;
2943+}
2944+
2945+bool DVBDevSwitch::ExecuteDiseqc(const DVBDevSettings& settings,
2946+ const DVBTuning& tuning,
2947+ unsigned int pos)
2948+{
2949+ // retrieve LNB info
2950+ bool high_band = false;
2951+ bool horizontal = false;
2952+ DVBDevLnb* lnb = m_tree.FindLNB(settings);
2953+ if(lnb)
2954+ {
2955+ high_band = lnb->IsHighBand(tuning);
2956+ horizontal = lnb->IsHorizontal(tuning);
2957+ }
2958+
2959+ // check number of ports
2960+ if(m_type == SWITCH_DISEQC_COMMITTED && m_num_ports > 4 ||
2961+ m_type == SWITCH_DISEQC_UNCOMMITTED && m_num_ports > 16)
2962+ {
2963+ VERBOSE(VB_IMPORTANT, LOC_ERR +
2964+ QString("Invalid number of ports for DiSEqC 1.x Switch (%1)")
2965+ .arg(m_num_ports));
2966+ return false;
2967+ }
2968+
2969+ // build command
2970+ unsigned int cmd;
2971+ unsigned char data;
2972+ if(m_type == SWITCH_DISEQC_UNCOMMITTED)
2973+ {
2974+ cmd = DISEQC_CMD_WRITE_N1;
2975+ data = pos;
2976+ }
2977+ else
2978+ {
2979+ cmd = DISEQC_CMD_WRITE_N0;
2980+ data = ((pos << 2) |
2981+ (horizontal ? 2 : 0) |
2982+ (high_band ? 1 : 0));
2983+ }
2984+ data |= 0xf0;
2985+
2986+ VERBOSE(VB_CHANNEL, LOC +
2987+ QString("Changing to DiSEqC switch port %1/%2")
2988+ .arg(pos+1)
2989+ .arg(m_num_ports));
2990+
2991+ return m_tree.SendCommand(DISEQC_ADR_SW_ALL,
2992+ cmd,
2993+ m_repeat,
2994+ 1,
2995+ &data);
2996+}
2997+
2998+bool DVBDevSwitch::GetPosition(const DVBDevSettings& settings,
2999+ unsigned int& pos) const
3000+{
3001+ pos = (unsigned int)settings.GetValue(m_dtv_dev_id);
3002+ if(pos >= m_num_ports)
3003+ {
3004+ VERBOSE(VB_IMPORTANT, LOC_ERR +
3005+ QString("Port number out of range (%1 > %2)")
3006+ .arg(pos+1)
3007+ .arg(m_num_ports));
3008+ return false;
3009+ }
3010+ if(m_children[pos] == NULL)
3011+ {
3012+ VERBOSE(VB_IMPORTANT, LOC_ERR +
3013+ QString("Port has no connected devices configured (%1)")
3014+ .arg(pos+1));
3015+ return false;
3016+ }
3017+
3018+ return true;
3019+}
3020+
3021+//////////////////////////////////////// DVBDevRotor
3022+
3023+DVBDevRotor::DVBDevRotor(DVBDevTree& tree,
3024+ int dtv_dev_id)
3025+ : DVBDevDevice(tree, dtv_dev_id),
3026+ m_type(ROTOR_DISEQC_1_3), m_speed_hi(2.5), m_speed_lo(1.9),
3027+ m_child(NULL), m_last_position(0.0), m_last_azimuth(0.0),
3028+ m_move_time(0.0), m_last_pos_known(false)
3029+{
3030+ Reset();
3031+}
3032+
3033+DVBDevRotor::DVBDevRotor::~DVBDevRotor()
3034+{
3035+ delete m_child;
3036+}
3037+
3038+bool DVBDevRotor::Execute(const DVBDevSettings& settings,
3039+ const DVBTuning& tuning)
3040+{
3041+ bool success = true;
3042+
3043+ double position = settings.GetValue(m_dtv_dev_id);
3044+ if(!m_last_pos_known || position != m_last_position)
3045+ {
3046+ switch(m_type)
3047+ {
3048+ case ROTOR_DISEQC_1_2:
3049+ success = ExecuteRotor(settings, tuning, position);
3050+ break;
3051+ case ROTOR_DISEQC_1_3:
3052+ success = ExecuteUSALS(settings, tuning, position);
3053+ break;
3054+ default:
3055+ success = false;
3056+ VERBOSE(VB_IMPORTANT, LOC_ERR +
3057+ QString("Unknown rotor type (%1)")
3058+ .arg((unsigned int)m_type));
3059+ break;
3060+ }
3061+
3062+ m_last_position = position;
3063+ }
3064+
3065+ // chain to child
3066+ if(success && m_child)
3067+ success = m_child->Execute(settings, tuning);
3068+
3069+ return success;
3070+}
3071+
3072+void DVBDevRotor::Reset()
3073+{
3074+ if(m_child)
3075+ m_child->Reset();
3076+}
3077+
3078+bool DVBDevRotor::NeedsCommand(const DVBDevSettings& settings) const
3079+{
3080+ double position = settings.GetValue(m_dtv_dev_id);
3081+ if(position != m_last_position)
3082+ return true;
3083+ else if(m_child)
3084+ return m_child->NeedsCommand(settings);
3085+ else
3086+ return false;
3087+}
3088+
3089+DVBDevDevice* DVBDevRotor::SelectedChild(const DVBDevSettings& /*settings*/) const
3090+{
3091+ return m_child;
3092+}
3093+
3094+bool DVBDevRotor::SetChild(unsigned int ordinal, DVBDevDevice* device)
3095+{
3096+ if(ordinal == 0)
3097+ {
3098+ delete m_child;
3099+ m_child = device;
3100+ if(m_child)
3101+ {
3102+ m_child->SetOrdinal(ordinal);
3103+ m_child->SetParent(this);
3104+ }
3105+ return true;
3106+ }
3107+ return false;
3108+}
3109+
3110+fe_sec_voltage DVBDevRotor::GetVoltage(const DVBDevSettings& settings,
3111+ const DVBTuning& tuning) const
3112+{
3113+ fe_sec_voltage voltage = SEC_VOLTAGE_18;
3114+
3115+ // override voltage if the last position is known and the rotor is moving
3116+ if(!(m_last_pos_known && Progress() < 1.0) && m_child)
3117+ voltage = m_child->GetVoltage(settings, tuning);
3118+
3119+ return voltage;
3120+}
3121+
3122+bool DVBDevRotor::Load()
3123+{
3124+ // populate switch parameters from db
3125+ {
3126+ MSqlQuery query(MSqlQuery::InitCon());
3127+ query.prepare("SELECT dtv_dev_subtype,"
3128+ " rotor_hi_speed, rotor_lo_speed, rotor_positions"
3129+ " FROM dtv_device_tree"
3130+ " WHERE dtv_dev_id = :DTV_DEV_ID");
3131+ query.bindValue(":DTV_DEV_ID", DeviceID());
3132+
3133+ if(query.exec() && query.next())
3134+ {
3135+ m_type = RotorTypeFromString(query.value(0).toString());
3136+ m_speed_hi = query.value(1).toDouble();
3137+ m_speed_lo = query.value(2).toDouble();
3138+
3139+ // form of "angle1=index1:angle2=index2:..."
3140+ QString positions = query.value(3).toString();
3141+ QStringList pos = QStringList::split(":", positions);
3142+ for(unsigned int i=0; i < pos.count(); i++)
3143+ {
3144+ QStringList eq = QStringList::split("=", pos[i]);
3145+ if(eq.count() == 2)
3146+ m_posmap[eq[0].toFloat()] = eq[1].toUInt();
3147+ }
3148+ }
3149+ }
3150+
3151+ // load children from db
3152+ delete m_child;
3153+ m_child = NULL;
3154+ {
3155+ MSqlQuery query(MSqlQuery::InitCon());
3156+ query.prepare("SELECT dtv_dev_id FROM dtv_device_tree "
3157+ "WHERE parent = :DTV_DEV_ID");
3158+ query.bindValue(":DTV_DEV_ID", DeviceID());
3159+
3160+ if(query.exec() && query.next())
3161+ {
3162+ int child_dev_id = query.value(0).toInt();
3163+ SetChild(0, CreateById(m_tree, child_dev_id));
3164+ }
3165+ }
3166+
3167+ return true;
3168+}
3169+
3170+bool DVBDevRotor::Store()
3171+{
3172+ QString type = RotorTypeToString(m_type);
3173+ QString posmap;
3174+
3175+ if(!m_posmap.empty())
3176+ {
3177+ QStringList pos;
3178+ for(INTPOSMAP::iterator i = m_posmap.begin(); i != m_posmap.end(); i++)
3179+ pos.push_back(QString("%1=%2").arg(i->first).arg(i->second));
3180+ posmap = pos.join(":");
3181+ }
3182+
3183+ MSqlQuery query(MSqlQuery::InitCon());
3184+
3185+ // insert new or update old
3186+ if(m_dtv_dev_id >= 0)
3187+ {
3188+ query.prepare("UPDATE dtv_device_tree"
3189+ " SET parent = :PARENT,"
3190+ " ordinal = :ORDINAL,"
3191+ " dtv_dev_type = 'rotor',"
3192+ " dtv_dev_descr = :DESCR,"
3193+ " dtv_dev_subtype = :TYPE,"
3194+ " rotor_hi_speed = :HISPEED,"
3195+ " rotor_lo_speed = :LOSPEED,"
3196+ " rotor_positions = :POSMAP"
3197+ " WHERE dtv_dev_id = :DTV_DEV_ID");
3198+ }
3199+ else
3200+ {
3201+ query.prepare("INSERT INTO dtv_device_tree"
3202+ " (parent, ordinal, dtv_dev_type, dtv_dev_descr,"
3203+ " dtv_dev_subtype, rotor_hi_speed,"
3204+ " rotor_lo_speed, rotor_positions)"
3205+ " VALUES (:PARENT, :ORDINAL, 'rotor', :DESCR,"
3206+ " :TYPE, :HISPEED, :LOSPEED, :POSMAP)");
3207+ }
3208+ if(m_parent)
3209+ query.bindValue(":PARENT", m_parent->DeviceID());
3210+ query.bindValue(":ORDINAL", m_ordinal);
3211+ query.bindValue(":DESCR", GetDescription());
3212+ query.bindValue(":TYPE", type);
3213+ query.bindValue(":HISPEED", m_speed_hi);
3214+ query.bindValue(":LOSPEED", m_speed_lo);
3215+ query.bindValue(":POSMAP", posmap);
3216+ query.bindValue(":DTV_DEV_ID", DeviceID());
3217+
3218+ // chain to child
3219+ bool success = query.exec();
3220+ if(success)
3221+ {
3222+ if(m_dtv_dev_id < 0)
3223+ m_dtv_dev_id = query.lastInsertId().toInt();
3224+ if(m_child)
3225+ success = m_child->Store();
3226+ }
3227+
3228+ return success;
3229+}
3230+
3231+double DVBDevRotor::Progress() const
3232+{
3233+ double completed = 1.0;
3234+
3235+ if(m_move_time != 0.0)
3236+ {
3237+ // calculate duration of move
3238+ double speed =
3239+ (m_tree.GetVoltage() == SEC_VOLTAGE_18) ? m_speed_hi : m_speed_lo;
3240+ double change = fabs(m_desired_azimuth - m_last_azimuth);
3241+ double duration = change / speed;
3242+
3243+ // determine completion percentage
3244+ struct timeval curtime;
3245+ gettimeofday(&curtime, NULL);
3246+ double cursecond = curtime.tv_sec + (double)curtime.tv_usec / 1000000;
3247+ double time_since_move = cursecond - m_move_time;
3248+ completed = time_since_move / duration;
3249+
3250+ // move completed, finish up
3251+ if(completed > 1.0)
3252+ completed = 1.0;
3253+ }
3254+
3255+ return completed;
3256+}
3257+
3258+DVBDevRotor::POSMAP DVBDevRotor::GetPosMap() const
3259+{
3260+ POSMAP retposmap;
3261+ INTPOSMAP::const_iterator i;
3262+ for(i = m_posmap.begin(); i != m_posmap.end(); i++)
3263+ retposmap.insert(make_pair(i->second, i->first));
3264+ return retposmap;
3265+}
3266+
3267+void DVBDevRotor::SetPosMap(const POSMAP& posmap)
3268+{
3269+ m_posmap.clear();
3270+ POSMAP::const_iterator i;
3271+ for(i = posmap.begin(); i != posmap.end(); i++)
3272+ m_posmap.insert(make_pair(i->second, i->first));
3273+}
3274+
3275+bool DVBDevRotor::ExecuteRotor(const DVBDevSettings& /*settings*/,
3276+ const DVBTuning& /*tuning*/,
3277+ double angle)
3278+{
3279+ // determine stored position from position map
3280+ INTPOSMAP::const_iterator i = m_posmap.find(angle);
3281+ unsigned char index;
3282+ if(i != m_posmap.end())
3283+ {
3284+ index = i->second;
3285+ RotorMoving(CalculateAzimuth(angle));
3286+ }
3287+ else
3288+ index = (unsigned int) angle;
3289+
3290+ VERBOSE(VB_CHANNEL, LOC + QString("Rotor - Goto Stored Position %1")
3291+ .arg(index));
3292+
3293+ return m_tree.SendCommand(DISEQC_ADR_POS_AZ,
3294+ DISEQC_CMD_GOTO_POS,
3295+ m_repeat,
3296+ 1,
3297+ &index);
3298+}
3299+
3300+bool DVBDevRotor::ExecuteUSALS(const DVBDevSettings& /*settings*/,
3301+ const DVBTuning& /*tuning*/,
3302+ double angle)
3303+{
3304+ double azimuth = CalculateAzimuth(angle);
3305+ RotorMoving(azimuth);
3306+ VERBOSE(VB_CHANNEL, LOC + QString("USALS Rotor - Goto %1 (Azimuth %2)")
3307+ .arg(angle)
3308+ .arg(azimuth));
3309+
3310+ uint az16 = (unsigned int) (abs(azimuth) * 16.0);
3311+ unsigned char cmd[2];
3312+ cmd[0] = ((azimuth > 0.0) ? 0xE0 : 0xD0) | ((az16 >> 8) & 0x0f);
3313+ cmd[1] = (az16 & 0xff);
3314+
3315+ return m_tree.SendCommand(DISEQC_ADR_POS_AZ,
3316+ DISEQC_CMD_GOTO_X,
3317+ m_repeat,
3318+ 2,
3319+ cmd);
3320+}
3321+
3322+#define TO_RADS (M_PI / 180.0)
3323+#define TO_DEC (180.0 / M_PI)
3324+
3325+double DVBDevRotor::CalculateAzimuth(double angle) const
3326+{
3327+ // Equation lifted from VDR rotor plugin by
3328+ // Thomas Bergwinkl <Thomas.Bergwinkl@t-online.de>
3329+
3330+ // Earth Station Latitude and Longitude in radians
3331+ double P = gContext->GetSetting("Latitude", "").toFloat() * TO_RADS;
3332+ double Ue = gContext->GetSetting("Longitude", "").toFloat() * TO_RADS;
3333+
3334+ // Satellite Longitude in radians
3335+ double Us = angle * TO_RADS;
3336+
3337+ double az = M_PI + atan( tan(Us - Ue) / sin(P) );
3338+ double x = acos( cos(Us - Ue) * cos(P) );
3339+ double el = atan( (cos(x) - 0.1513) / sin(x) );
3340+ double tmp_a = -cos(el) * sin(az);
3341+ double tmp_b = (sin(el) * cos(P)) - (cos(el) * sin(P) * cos(az));
3342+ double azimuth = atan(tmp_a / tmp_b) * TO_DEC;
3343+
3344+ return azimuth;
3345+}
3346+
3347+double DVBDevRotor::GetApproxAzimuth()
3348+{
3349+ double approx = m_last_azimuth;
3350+
3351+ if(m_move_time != 0.0)
3352+ {
3353+ double change = m_desired_azimuth - m_last_azimuth;
3354+ double progress = Progress();
3355+ approx += (change * progress);
3356+ if(progress >= 1.0)
3357+ m_move_time = 0.0;
3358+ }
3359+
3360+ return approx;
3361+}
3362+
3363+void DVBDevRotor::RotorMoving(double azimuth)
3364+{
3365+ // set last to approximate current position (or worst case if unknown)
3366+ if(m_last_pos_known)
3367+ m_last_azimuth = GetApproxAzimuth();
3368+ else
3369+ m_last_azimuth = azimuth > 0.0 ? -75.0 : 75.0;
3370+
3371+ // save time and angle of this command
3372+ m_desired_azimuth = azimuth;
3373+ struct timeval curtime;
3374+ gettimeofday(&curtime, NULL);
3375+ m_move_time = curtime.tv_sec + (double)curtime.tv_usec / 1000000;
3376+
3377+ m_last_pos_known = true;
3378+}
3379+
3380+////////////////////////////////////////
3381+
3382+DVBDevLnb::DVBDevLnb(DVBDevTree& tree,
3383+ int dtv_dev_id)
3384+ : DVBDevDevice(tree, dtv_dev_id),
3385+ m_type(LNB_VOLTAGE_TONE),
3386+ m_lof_switch(11700000),
3387+ m_lof_hi(10600000),
3388+ m_lof_lo(9750000)
3389+{
3390+ Reset();
3391+}
3392+
3393+bool DVBDevLnb::Execute(const DVBDevSettings& /*settings*/,
3394+ const DVBTuning& tuning)
3395+{
3396+ // set voltage for polarization
3397+ if((m_type == LNB_VOLTAGE || m_type == LNB_VOLTAGE_TONE))
3398+ {
3399+ bool horiz = IsHorizontal(tuning);
3400+ fe_sec_voltage voltage = (horiz ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13);
3401+ m_tree.SetVoltage(voltage);
3402+ }
3403+
3404+ // set tone for bandselect
3405+ bool high_band = IsHighBand(tuning);
3406+ if(m_type == LNB_VOLTAGE_TONE)
3407+ m_tree.SetTone(high_band);
3408+
3409+ return true;
3410+}
3411+
3412+void DVBDevLnb::Reset()
3413+{
3414+ // i.e. diseqc lnbs would need reset
3415+}
3416+
3417+bool DVBDevLnb::NeedsCommand(const DVBDevSettings& /*settings*/) const
3418+{
3419+ // i.e. diseqc lnbs would return true
3420+ return false;
3421+}
3422+
3423+fe_sec_voltage DVBDevLnb::GetVoltage(const DVBDevSettings& /*settings*/,
3424+ const DVBTuning& tuning) const
3425+{
3426+ fe_sec_voltage voltage = SEC_VOLTAGE_18;
3427+
3428+ if((m_type == LNB_VOLTAGE || m_type == LNB_VOLTAGE_TONE))
3429+ voltage = (IsHorizontal(tuning) ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13);
3430+
3431+ return voltage;
3432+}
3433+
3434+bool DVBDevLnb::Load()
3435+{
3436+ // populate lnb parameters from db
3437+ MSqlQuery query(MSqlQuery::InitCon());
3438+ query.prepare("SELECT dtv_dev_subtype, lnb_lof_switch,"
3439+ " lnb_lof_hi, lnb_lof_lo"
3440+ " FROM dtv_device_tree WHERE dtv_dev_id = :DTV_DEV_ID");
3441+ query.bindValue(":DTV_DEV_ID", DeviceID());
3442+
3443+ if(query.exec() && query.next())
3444+ {
3445+ m_type = LnbTypeFromString(query.value(0).toString());
3446+ m_lof_switch = query.value(1).toInt();
3447+ m_lof_hi = query.value(2).toInt();
3448+ m_lof_lo = query.value(3).toInt();
3449+ }
3450+
3451+ return true;
3452+}
3453+
3454+bool DVBDevLnb::Store()
3455+{
3456+ QString type = LnbTypeToString(m_type);
3457+ MSqlQuery query(MSqlQuery::InitCon());
3458+
3459+ // insert new or update old
3460+ if(m_dtv_dev_id >= 0)
3461+ {
3462+ query.prepare("UPDATE dtv_device_tree"
3463+ " SET parent = :PARENT,"
3464+ " ordinal = :ORDINAL,"
3465+ " dtv_dev_type = 'lnb',"
3466+ " dtv_dev_descr = :DESCR,"
3467+ " dtv_dev_subtype = :TYPE,"
3468+ " lnb_lof_switch = :LOFSW,"
3469+ " lnb_lof_lo = :LOFLO,"
3470+ " lnb_lof_hi = :LOFHI"
3471+ " WHERE dtv_dev_id = :DTV_DEV_ID");
3472+ }
3473+ else
3474+ {
3475+ query.prepare("INSERT INTO dtv_device_tree"
3476+ " (parent, ordinal, dtv_dev_type, dtv_dev_descr,"
3477+ " dtv_dev_subtype, lnb_lof_switch,"
3478+ " lnb_lof_lo, lnb_lof_hi)"
3479+ " VALUES (:PARENT, :ORDINAL, 'lnb', :DESCR,"
3480+ " :TYPE, :LOFSW, :LOFLO, :LOFHI)");
3481+ }
3482+ if(m_parent)
3483+ query.bindValue(":PARENT", m_parent->DeviceID());
3484+ query.bindValue(":ORDINAL", m_ordinal);
3485+ query.bindValue(":DESCR", GetDescription());
3486+ query.bindValue(":TYPE", type);
3487+ query.bindValue(":LOFSW", m_lof_switch);
3488+ query.bindValue(":LOFLO", m_lof_lo);
3489+ query.bindValue(":LOFHI", m_lof_hi);
3490+ query.bindValue(":DTV_DEV_ID", DeviceID());
3491+
3492+ // update dev_id
3493+ bool success = query.exec();
3494+ if(success && m_dtv_dev_id < 0)
3495+ m_dtv_dev_id = query.lastInsertId().toInt();
3496+
3497+ return success;
3498+}
3499+
3500+bool DVBDevLnb::IsHighBand(const DVBTuning& tuning) const
3501+{
3502+ bool high_band = false;
3503+ if(m_type == LNB_VOLTAGE_TONE)
3504+ high_band = (tuning.params.frequency > m_lof_switch);
3505+ return high_band;
3506+}
3507+
3508+bool DVBDevLnb::IsHorizontal(const DVBTuning& tuning) const
3509+{
3510+ char pol = tuning.PolarityChar();
3511+ return (pol == 'h' || pol == 'l');
3512+}
3513+
3514+__u32 DVBDevLnb::GetIF(const DVBDevSettings& /*settings*/,
3515+ const DVBTuning& tuning) const
3516+{
3517+ unsigned int abs_freq = tuning.params.frequency;
3518+ unsigned int lof = (IsHighBand(tuning) ? m_lof_hi : m_lof_lo);
3519+ return (lof > abs_freq ? lof - abs_freq : abs_freq - lof);
3520+}
3521+
3522+////////////////////////////////////////
3523+
3524+struct TypeTable
3525+{
3526+ const char* name;
3527+ unsigned int value;
3528+};
3529+
3530+static QString TableToString(unsigned int type, const TypeTable* table)
3531+{
3532+ QString str;
3533+ for( ; table->name != NULL; table++)
3534+ {
3535+ if(type == table->value)
3536+ {
3537+ str = table->name;
3538+ break;
3539+ }
3540+ }
3541+ return str;
3542+}
3543+
3544+static unsigned int TableFromString(const QString& type, const TypeTable*table)
3545+{
3546+ for( ; table->name != NULL; table++)
3547+ if(type == table->name)
3548+ break;
3549+ return table->value;
3550+}
3551+
3552+static TypeTable DevTypeTable[] =
3553+{
3554+ { "switch", DVBDEV_SWITCH },
3555+ { "rotor", DVBDEV_ROTOR },
3556+ { "lnb", DVBDEV_LNB },
3557+ { NULL, DVBDEV_LNB }
3558+};
3559+
3560+static TypeTable SwitchTypeTable[] =
3561+{
3562+ { "legacy_sw21", SWITCH_LEGACY_SW21 },
3563+ { "legacy_sw42", SWITCH_LEGACY_SW42 },
3564+ { "legacy_sw64", SWITCH_LEGACY_SW64 },
3565+ { "tone", SWITCH_TONE },
3566+ { "diseqc", SWITCH_DISEQC_COMMITTED },
3567+ { "diseqc_uncom", SWITCH_DISEQC_UNCOMMITTED },
3568+ { NULL, SWITCH_TONE }
3569+};
3570+
3571+static TypeTable RotorTypeTable[] =
3572+{
3573+ { "diseqc_1_2", ROTOR_DISEQC_1_2 },
3574+ { "diseqc_1_3", ROTOR_DISEQC_1_3 },
3575+ { NULL, ROTOR_DISEQC_1_3 }
3576+};
3577+
3578+static TypeTable LnbTypeTable[] =
3579+{
3580+ { "fixed", LNB_FIXED },
3581+ { "voltage", LNB_VOLTAGE },
3582+ { "voltage_tone", LNB_VOLTAGE_TONE },
3583+ { NULL, LNB_VOLTAGE_TONE }
3584+};
3585+
3586+QString DevTypeToString(dvbdev_t type)
3587+{
3588+ return TableToString((unsigned int)type, DevTypeTable);
3589+}
3590+
3591+dvbdev_t DevTypeFromString(const QString& type)
3592+{
3593+ return (dvbdev_t)TableFromString(type, DevTypeTable);
3594+}
3595+
3596+QString SwitchTypeToString(dvbdev_switch_t type)
3597+{
3598+ return TableToString((unsigned int)type, SwitchTypeTable);
3599+}
3600+
3601+dvbdev_switch_t SwitchTypeFromString(const QString& type)
3602+{
3603+ return (dvbdev_switch_t)TableFromString(type, SwitchTypeTable);
3604+}
3605+
3606+QString RotorTypeToString(dvbdev_rotor_t type)
3607+{
3608+ return TableToString((unsigned int)type, RotorTypeTable);
3609+}
3610+
3611+dvbdev_rotor_t RotorTypeFromString(const QString& type)
3612+{
3613+ return (dvbdev_rotor_t)TableFromString(type, RotorTypeTable);
3614+}
3615+
3616+QString LnbTypeToString(dvbdev_lnb_t type)
3617+{
3618+ return TableToString((unsigned int)type, LnbTypeTable);
3619+}
3620+
3621+dvbdev_lnb_t LnbTypeFromString(const QString& type)
3622+{
3623+ return (dvbdev_lnb_t)TableFromString(type, LnbTypeTable);
3624+}
3625Index: libs/libmythtv/channelutil.cpp
3626===================================================================
3627--- libs/libmythtv/channelutil.cpp (revision 10186)
3628+++ libs/libmythtv/channelutil.cpp (working copy)
3629@@ -231,7 +231,7 @@
3630 // DVB specific
3631 tsid, netid,
3632 cd.SymbolRateHz(), -1,
3633- QChar(cd.PolarizationString()[0]), -1,
3634+ QChar(cd.PolarizationString()[0]), 'a',
3635 -1,
3636 cd.FECInnerString(), QString::null,
3637 -1, QString::null,
3638@@ -670,6 +670,24 @@
3639 return inputname;
3640 }
3641
3642+int ChannelUtil::GetInputID(int source_id, int card_id)
3643+{
3644+ int input_id = -1;
3645+
3646+ MSqlQuery query(MSqlQuery::InitCon());
3647+ query.prepare("SELECT cardinputid"
3648+ " FROM cardinput"
3649+ " WHERE sourceid = :SOURCEID"
3650+ " AND cardid = :CARDID");
3651+ query.bindValue(":SOURCEID", source_id);
3652+ query.bindValue(":CARDID", card_id);
3653+
3654+ if (query.exec() && query.isActive() && query.next())
3655+ input_id = query.value(0).toInt();
3656+
3657+ return input_id;
3658+}
3659+
3660 QString ChannelUtil::GetChannelValueStr(const QString &channel_field,
3661 uint cardid,
3662 const QString &input,
3663Index: libs/libmythtv/dvbdevtree_cfg.h
3664===================================================================
3665--- libs/libmythtv/dvbdevtree_cfg.h (revision 0)
3666+++ libs/libmythtv/dvbdevtree_cfg.h (revision 0)
3667@@ -0,0 +1,154 @@
3668+/*
3669+ * \file dvbdevtree_cfg.h
3670+ * \brief DVB-S Device Tree Configuration Classes.
3671+ * \author Copyright (C) 2006, Yeasah Pell
3672+ */
3673+
3674+#ifndef DVBDEVTREE_CFG_H
3675+#define DVBDEVTREE_CFG_H
3676+
3677+#include "dvbtypes.h"
3678+#include "dvbdevtree.h"
3679+#include "settings.h"
3680+
3681+class SwitchTypeSetting;
3682+class SwitchPortsSetting;
3683+
3684+class SwitchConfig : public ConfigurationWizard
3685+{
3686+ Q_OBJECT
3687+public:
3688+ SwitchConfig(DVBDevSwitch& switch_dev);
3689+
3690+public slots:
3691+ void update();
3692+
3693+private:
3694+ SwitchTypeSetting* m_type;
3695+ SwitchPortsSetting* m_ports;
3696+};
3697+
3698+class RotorPosMap : public ListBoxSetting
3699+{
3700+ Q_OBJECT
3701+public:
3702+ RotorPosMap(DVBDevRotor& rotor);
3703+
3704+ virtual void load();
3705+ virtual void save();
3706+
3707+public slots:
3708+ void edit();
3709+ void del();
3710+
3711+protected:
3712+ void PopulateList();
3713+
3714+private:
3715+ DVBDevRotor& m_rotor;
3716+ DVBDevRotor::POSMAP m_posmap;
3717+};
3718+
3719+class RotorConfig : public ConfigurationWizard
3720+{
3721+ Q_OBJECT
3722+public:
3723+ RotorConfig(DVBDevRotor& rotor);
3724+
3725+public slots:
3726+ void type_changed(const QString& type);
3727+ void positions();
3728+
3729+private:
3730+ DVBDevRotor& m_rotor;
3731+ TransButtonSetting* m_pos;
3732+};
3733+
3734+class LnbTypeSetting;
3735+class LnbLOFSwitchSetting;
3736+class LnbLOFLowSetting;
3737+class LnbLOFHighSetting;
3738+
3739+class LnbConfig : public ConfigurationWizard
3740+{
3741+ Q_OBJECT
3742+public:
3743+ LnbConfig(DVBDevLnb& lnb);
3744+
3745+public slots:
3746+ void preset(const QString& value);
3747+ void update();
3748+
3749+private:
3750+ LnbTypeSetting* m_type;
3751+ LnbLOFSwitchSetting* m_lof_switch;
3752+ LnbLOFLowSetting* m_lof_lo;
3753+ LnbLOFHighSetting* m_lof_hi;
3754+};
3755+
3756+class DeviceTree : public ListBoxSetting
3757+{
3758+ Q_OBJECT
3759+public:
3760+ DeviceTree(DVBDevTree& tree);
3761+
3762+ virtual void load();
3763+ virtual void save();
3764+
3765+protected:
3766+ bool editNode(int node_id);
3767+ void newRootNode();
3768+ void newNode(int parent_id, unsigned int child_num);
3769+
3770+ bool chooseType(dvbdev_t& type);
3771+ void PopulateTree();
3772+ void PopulateTree(DVBDevDevice* node,
3773+ DVBDevDevice* parent = NULL,
3774+ unsigned int childnum = 0,
3775+ unsigned int depth = 0);
3776+
3777+public slots:
3778+ void edit();
3779+ void del();
3780+
3781+private:
3782+ DVBDevTree& m_tree;
3783+};
3784+
3785+class DTVDeviceTreeWizard : public VerticalConfigurationGroup,
3786+ public ConfigurationDialog
3787+{
3788+ Q_OBJECT
3789+public:
3790+ DTVDeviceTreeWizard(DVBDevTree& tree);
3791+
3792+ virtual int exec();
3793+};
3794+
3795+bool DTVDeviceNeedsConfiguration(unsigned int input_id);
3796+
3797+class DTVDeviceConfigWizard : public ConfigurationWizard
3798+{
3799+ Q_OBJECT
3800+public:
3801+ DTVDeviceConfigWizard(DVBDevSettings& settings, unsigned int card_id);
3802+ ~DTVDeviceConfigWizard();
3803+
3804+public slots:
3805+ void SelectNodes();
3806+
3807+protected:
3808+ void AddNodes(ConfigurationGroup& group, DVBDevDevice* node);
3809+
3810+private:
3811+ DVBDevTree m_tree;
3812+ DVBDevSettings& m_settings;
3813+
3814+ typedef std::map<unsigned int, Setting*> DEVS;
3815+ DEVS m_devs;
3816+};
3817+
3818+bool DatabaseDiseqcImport();
3819+bool DatabaseDiseqcUpgrade();
3820+
3821+#endif // DVBDVBTREE_CFG_H
3822Index: libs/libmythtv/dvbdevtree.h
3823===================================================================
3824--- libs/libmythtv/dvbdevtree.h (revision 0)
3825+++ libs/libmythtv/dvbdevtree.h (revision 0)
3826@@ -0,0 +1,547 @@
3827+/*
3828+ * \file dvbdevtree.h
3829+ * \brief DVB-S Device Tree Control Classes.
3830+ * \author Copyright (C) 2006, Yeasah Pell
3831+ */
3832+
3833+#ifndef DVBDEVTREE_H
3834+#define DVBDEVTREE_H
3835+
3836+// prerequisites
3837+#include "dvbtypes.h"
3838+#include <linux/dvb/frontend.h>
3839+#include <map>
3840+#include <vector>
3841+
3842+// DiSEqC sleep intervals per eutelsat spec
3843+#define DISEQC_SHORT_WAIT (15 * 1000)
3844+#define DISEQC_LONG_WAIT (100 * 1000)
3845+
3846+// Number of times to retry ioctls after receiving ETIMEDOUT before giving up
3847+#define TIMEOUT_RETRIES 3
3848+
3849+// Framing byte
3850+#define DISEQC_FRM 0xe0
3851+#define DISEQC_FRM_REPEAT (1 << 0)
3852+#define DISEQC_FRM_REPLY_REQ (1 << 1)
3853+
3854+// Address byte
3855+#define DISEQC_ADR_ALL 0x00
3856+#define DISEQC_ADR_SW_ALL 0x10
3857+#define DISEQC_ADR_LNB 0x11
3858+#define DISEQC_ADR_LNB_SW 0x12
3859+#define DISEQC_ADR_SW_BLK 0x14
3860+#define DISEQC_ADR_SW 0x15
3861+#define DISEQC_ADR_SMATV 0x18
3862+#define DISEQC_ADR_POL_ALL 0x20
3863+#define DISEQC_ADR_POL_LIN 0x21
3864+#define DISEQC_ADR_POS_ALL 0x30
3865+#define DISEQC_ADR_POS_AZ 0x31
3866+#define DISEQC_ADR_POS_EL 0x32
3867+
3868+// Command byte
3869+#define DISEQC_CMD_RESET 0x00
3870+#define DISEQC_CMD_CLR_RESET 0x01
3871+#define DISEQC_CMD_WRITE_N0 0x38
3872+#define DISEQC_CMD_WRITE_N1 0x39
3873+#define DISEQC_CMD_WRITE_FREQ 0x58
3874+#define DISEQC_CMD_HALT 0x60
3875+#define DISEQC_CMD_LMT_OFF 0x63
3876+#define DISEQC_CMD_LMT_E 0x66
3877+#define DISEQC_CMD_LMT_W 0x67
3878+#define DISEQC_CMD_DRIVE_E 0x68
3879+#define DISEQC_CMD_DRIVE_W 0x69
3880+#define DISEQC_CMD_STORE_POS 0x6a
3881+#define DISEQC_CMD_GOTO_POS 0x6b
3882+#define DISEQC_CMD_GOTO_X 0x6e
3883+
3884+enum dvbdev_t
3885+{
3886+ DVBDEV_SWITCH = 0,
3887+ DVBDEV_ROTOR,
3888+ DVBDEV_LNB
3889+};
3890+
3891+QString DevTypeToString(dvbdev_t type);
3892+dvbdev_t DevTypeFromString(const QString& type);
3893+
3894+enum dvbdev_switch_t
3895+{
3896+ SWITCH_TONE = 0,
3897+ SWITCH_DISEQC_COMMITTED,
3898+ SWITCH_DISEQC_UNCOMMITTED,
3899+ SWITCH_LEGACY_SW21,
3900+ SWITCH_LEGACY_SW42,
3901+ SWITCH_LEGACY_SW64
3902+};
3903+
3904+QString SwitchTypeToString(dvbdev_switch_t type);
3905+dvbdev_switch_t SwitchTypeFromString(const QString& type);
3906+
3907+enum dvbdev_rotor_t
3908+{
3909+ ROTOR_DISEQC_1_2 = 0,
3910+ ROTOR_DISEQC_1_3
3911+};
3912+
3913+QString RotorTypeToString(dvbdev_rotor_t type);
3914+dvbdev_rotor_t RotorTypeFromString(const QString& type);
3915+
3916+enum dvbdev_lnb_t
3917+{
3918+ LNB_FIXED = 0,
3919+ LNB_VOLTAGE,
3920+ LNB_VOLTAGE_TONE
3921+};
3922+
3923+QString LnbTypeToString(dvbdev_lnb_t type);
3924+dvbdev_lnb_t LnbTypeFromString(const QString& type);
3925+
3926+/** DVB-S device settings class. Represents a single possible configuration
3927+ of a given network of DVB-S devices. */
3928+class DVBDevSettings
3929+{
3930+ public:
3931+ DVBDevSettings();
3932+
3933+ /** Loads configuration chain from DB for specified card input id.
3934+ \param card_input_id Desired capture card input ID.
3935+ \return True if successful. */
3936+ bool Load(unsigned int card_input_id);
3937+
3938+ /** Stores configuration chain to DB for specified card input id.
3939+ \param card_input_id Desired capture card input ID.
3940+ \return True if successful. */
3941+ bool Store(unsigned int card_input_id) const;
3942+
3943+ /** Retrieves a value from this configuration chain by device id.
3944+ \param dtv_dev_id Device id.
3945+ \return Device scalar value. */
3946+ double GetValue(int dtv_dev_id) const;
3947+
3948+ /** Sets a value for this configuration chain by device id.
3949+ \param dtv_dev_id Device id.
3950+ \param value Device scalar value. */
3951+ void SetValue(int dtv_dev_id, double value);
3952+
3953+ protected:
3954+
3955+ // map of dev tree id to configuration value
3956+ typedef std::map<int, double> CONFIG;
3957+ CONFIG m_config;
3958+
3959+ // current input id
3960+ unsigned int m_input_id;
3961+};
3962+
3963+class DVBDevTrees;
3964+class DVBDevTree;
3965+class DVBDevDevice;
3966+class DVBDevRotor;
3967+class DVBDevLnb;
3968+
3969+/** Main DVB-S device interface. */
3970+class DVBDev
3971+{
3972+ public:
3973+
3974+ /** Retrieve device tree.
3975+ \param card_id Capture card id.
3976+ \param fd_frontend DVB frontend device file descriptor. */
3977+ DVBDevTree* FindTree(unsigned int card_id);
3978+
3979+ /** Invalidate cached trees. */
3980+ void InvalidateTrees();
3981+
3982+ protected:
3983+ static DVBDevTrees m_trees;
3984+};
3985+
3986+/** Static-scoped locked tree list class. */
3987+class DVBDevTrees
3988+{
3989+ public:
3990+ ~DVBDevTrees();
3991+
3992+ DVBDevTree* FindTree(unsigned int card_id);
3993+ void InvalidateTrees();
3994+
3995+ protected:
3996+ typedef std::map<unsigned int, DVBDevTree*> TREES;
3997+ TREES m_trees;
3998+ QMutex m_trees_lock;
3999+};
4000+
4001+/** DVB-S device tree class. Represents a tree of DVB-S devices. */
4002+class DVBDevTree
4003+{
4004+ public:
4005+ /** Constructor. */
4006+ DVBDevTree();
4007+ ~DVBDevTree();
4008+
4009+ /** Loads the device tree from the database.
4010+ \param card_id Capture card id.
4011+ \return True if successful. */
4012+ bool Load(unsigned int card_id);
4013+
4014+ /** Stores the device tree to the database.
4015+ \param card_id Capture card id.
4016+ \return True if successful. */
4017+ bool Store(unsigned int card_id);
4018+
4019+ /** Applies settings to the entire tree.
4020+ \param settings Configuration chain to apply.
4021+ \param tuning Tuning parameters.
4022+ \return True if execution completed successfully. */
4023+ bool Execute(const DVBDevSettings& settings,
4024+ const DVBTuning& tuning);
4025+
4026+ /** Reset state of nodes in tree, forcing updates on the
4027+ next Execute command.
4028+ \return True if reset completed successfully. */
4029+ void Reset();
4030+
4031+ /** Returns the nth rotor device object in the tree.
4032+ \param settings Configuration chain in effect.
4033+ \param index 0 for first rotor, 1 for second, etc.
4034+ \return Pointer to rotor object if found, NULL otherwise. */
4035+ DVBDevRotor* FindRotor(const DVBDevSettings& settings,
4036+ unsigned int index = 0);
4037+
4038+ /** Returns the LNB device object selected by the configuration chain.
4039+ \param settings Configuration chain in effect.
4040+ \return Pointer to LNB object if found, NULL otherwise. */
4041+ DVBDevLnb* FindLNB(const DVBDevSettings& settings);
4042+
4043+ /** Returns a device by ID.
4044+ \param dev_id Device ID to find.
4045+ \return Pointer to device, or NULL if not found in this tree. */
4046+ DVBDevDevice* FindDevice(int dev_id);
4047+
4048+ /** Retrieves the root node in the tree.
4049+ \return Pointer to device, or NULL if no root. */
4050+ DVBDevDevice* Root() { return m_root; }
4051+
4052+ /** Changes the root node of the tree.
4053+ \param root New root node (may be NULL). */
4054+ void SetRoot(DVBDevDevice* root);
4055+
4056+ /** Sends a DiSEqC command.
4057+ \param adr DiSEqC destination address.
4058+ \param cmd DiSEqC command.
4059+ \param repeats Number of times to repeat command.
4060+ \param data_len Length of optional data.
4061+ \param data Pointer to optional data. */
4062+ bool SendCommand(unsigned int adr,
4063+ unsigned int cmd,
4064+ unsigned int repeats = 0,
4065+ unsigned int data_len = 0,
4066+ unsigned char* data = NULL);
4067+
4068+ /** Resets the DiSEqC bus.
4069+ \param hard_reset If true, the bus will be power cycled.
4070+ \return True if successful. */
4071+ bool ResetDiseqc(bool hard_reset);
4072+
4073+ // frontend fd
4074+ void Open(int fd_frontend);
4075+ void Close() { m_fd_frontend = -1; }
4076+ int FrontendFD() const { return m_fd_frontend; }
4077+
4078+ // frontend operations
4079+ bool SetTone(bool on);
4080+ bool MiniDiseqc(fe_sec_mini_cmd cmd);
4081+ bool SetVoltage(fe_sec_voltage voltage);
4082+ bool SendDiseqc(const dvb_diseqc_master_cmd& cmd);
4083+ fe_sec_voltage GetVoltage() const { return m_last_voltage; }
4084+
4085+ // tree management
4086+ void AddDeferredDelete(unsigned int dev_id) { m_delete.push_back(dev_id); }
4087+ int NextFakeID() { return --m_next_cnt; }
4088+
4089+ protected:
4090+ bool ApplyVoltage(const DVBDevSettings& settings,
4091+ const DVBTuning& tuning);
4092+
4093+ int m_fd_frontend;
4094+ DVBDevDevice *m_root;
4095+ fe_sec_voltage m_last_voltage;
4096+ mutable std::list<unsigned int> m_delete;
4097+
4098+ int m_next_cnt;
4099+};
4100+
4101+/** DVB-S device class. Represents a node in a DVB-S device network. */
4102+class DVBDevDevice
4103+{
4104+ public:
4105+ /** Constructor.
4106+ \param tree Parent reference to tree object.
4107+ \param dtv_dev_id Device ID of this node. */
4108+ DVBDevDevice(DVBDevTree& tree, int dtv_dev_id);
4109+
4110+ virtual ~DVBDevDevice();
4111+
4112+ /** Applies DiSEqC settings to this node and any children.
4113+ \param settings Configuration chain to apply.
4114+ \param tuning Tuning parameters.
4115+ \return True if execution completed successfully. */
4116+ virtual bool Execute(const DVBDevSettings& settings,
4117+ const DVBTuning& tuning) = 0;
4118+
4119+ /** Resets the last known settings for this device. Device
4120+ will not actually have commands issued until next Execute() method. */
4121+ virtual void Reset() = 0;
4122+
4123+ /** Determines if this device or any child will be sending a command
4124+ for the given configuration chain.
4125+ \param settings Configuration chain in effect.
4126+ \return True if a command would be sent if Execute() were called. */
4127+ virtual bool NeedsCommand(const DVBDevSettings& settings) const = 0;
4128+
4129+ /** Retrieves the selected child for this configuration, if any.
4130+ \param settings Configuration chain in effect.
4131+ \return Child node object, or NULL if none. */
4132+ virtual DVBDevDevice* SelectedChild(const DVBDevSettings& settings) const = 0;
4133+
4134+ /** Retrieves the proper number of children for this node.
4135+ \return Number of children */
4136+ virtual unsigned int NumChildren() const = 0;
4137+
4138+ /** Retrieves the nth child of this node.
4139+ \param ordinal Child number (starting at 0).
4140+ \return Pointer to device object, or NULL if no child. */
4141+ virtual DVBDevDevice* GetChild(unsigned int ordinal) = 0;
4142+
4143+ /** Changes the nth child of this node.
4144+ \param ordinal Child number (starting at 0).
4145+ \param device New child device. (may be NULL)
4146+ \return true if object was added to tree. */
4147+ virtual bool SetChild(unsigned int ordinal,
4148+ DVBDevDevice* device) = 0;
4149+
4150+ /** Retrives the desired voltage for this config.
4151+ \param settings Configuration chain in effect.
4152+ \param tuning Tuning parameters.
4153+ \return Voltage required. */
4154+ virtual fe_sec_voltage GetVoltage(const DVBDevSettings& settings,
4155+ const DVBTuning& tuning) const = 0;
4156+
4157+ /** Loads this device from the database.
4158+ \return True if successful. */
4159+ virtual bool Load() = 0;
4160+
4161+ /** Stores this device to the database.
4162+ \return True if successful. */
4163+ virtual bool Store() = 0;
4164+
4165+ /** Returns a device by ID.
4166+ \param dev_id Device ID to find.
4167+ \return Pointer to device, or NULL if not found in this tree. */
4168+ DVBDevDevice* FindDevice(int dev_id);
4169+
4170+ static DVBDevDevice* CreateById(DVBDevTree& tree,
4171+ int dtv_dev_id);
4172+ static DVBDevDevice* CreateByType(DVBDevTree& tree,
4173+ dvbdev_t type,
4174+ int dev_id = -1);
4175+
4176+ int DeviceID() const { return m_dtv_dev_id; }
4177+
4178+ DVBDevDevice* GetParent() const { return m_parent; }
4179+ void SetParent(DVBDevDevice* parent) { m_parent = parent; }
4180+ unsigned int GetOrdinal() const { return m_ordinal; }
4181+ void SetOrdinal(unsigned int ordinal) { m_ordinal = ordinal; }
4182+
4183+ void SetDeviceType(dvbdev_t type) { m_dev_type = type; }
4184+ dvbdev_t GetDeviceType() const { return m_dev_type; }
4185+
4186+ QString GetDescription() const { return m_descr; }
4187+ void SetDescription(const QString& descr) { m_descr = descr; }
4188+
4189+ protected:
4190+
4191+ int m_dtv_dev_id;
4192+ dvbdev_t m_dev_type;
4193+ QString m_descr;
4194+ DVBDevTree& m_tree;
4195+ DVBDevDevice* m_parent;
4196+ unsigned int m_ordinal;
4197+ unsigned int m_repeat;
4198+};
4199+
4200+/** Switch class, including tone, legacy and DiSEqC switches. */
4201+class DVBDevSwitch : public DVBDevDevice
4202+{
4203+ public:
4204+ DVBDevSwitch(DVBDevTree& tree, int dtv_dev_id);
4205+ ~DVBDevSwitch();
4206+
4207+ virtual bool Execute(const DVBDevSettings& settings,
4208+ const DVBTuning& tuning);
4209+ virtual void Reset();
4210+ virtual bool NeedsCommand(const DVBDevSettings& settings) const;
4211+ virtual DVBDevDevice* SelectedChild(const DVBDevSettings& settings) const;
4212+ virtual unsigned int NumChildren() const;
4213+ virtual DVBDevDevice* GetChild(unsigned int ordinal);
4214+ virtual bool SetChild(unsigned int ordinal, DVBDevDevice* device);
4215+ virtual fe_sec_voltage GetVoltage(const DVBDevSettings& settings,
4216+ const DVBTuning& tuning) const;
4217+ virtual bool Load();
4218+ virtual bool Store();
4219+
4220+ dvbdev_switch_t GetType() const { return m_type; }
4221+ void SetType(dvbdev_switch_t type) { m_type = type; }
4222+ unsigned int GetNumPorts() const { return m_num_ports; }
4223+ void SetNumPorts(unsigned int num_ports);
4224+
4225+ protected:
4226+ bool ExecuteLegacy(const DVBDevSettings& settings,
4227+ const DVBTuning& tuning,
4228+ unsigned int pos);
4229+ bool ExecuteTone(const DVBDevSettings& settings,
4230+ const DVBTuning& tuning,
4231+ unsigned int pos);
4232+ bool ExecuteDiseqc(const DVBDevSettings& settings,
4233+ const DVBTuning& tuning,
4234+ unsigned int pos);
4235+ bool GetPosition(const DVBDevSettings& settings,
4236+ unsigned int& pos) const;
4237+
4238+ private:
4239+ dvbdev_switch_t m_type;
4240+ unsigned int m_num_ports;
4241+ unsigned int m_last_pos;
4242+
4243+ typedef std::vector<DVBDevDevice*> CHILDREN;
4244+ CHILDREN m_children;
4245+};
4246+
4247+/** Rotor class. */
4248+class DVBDevRotor : public DVBDevDevice
4249+{
4250+ public:
4251+ DVBDevRotor(DVBDevTree& tree, int dtv_dev_id);
4252+ ~DVBDevRotor();
4253+
4254+ virtual bool Execute(const DVBDevSettings& settings,
4255+ const DVBTuning& tuning);
4256+ virtual void Reset();
4257+ virtual bool NeedsCommand(const DVBDevSettings& settings) const;
4258+ virtual DVBDevDevice* SelectedChild(const DVBDevSettings& settings) const;
4259+ virtual unsigned int NumChildren() const { return 1; }
4260+ virtual DVBDevDevice* GetChild(unsigned int) { return m_child; }
4261+ virtual bool SetChild(unsigned int ordinal, DVBDevDevice* device);
4262+ virtual fe_sec_voltage GetVoltage(const DVBDevSettings& settings,
4263+ const DVBTuning& tuning) const;
4264+ virtual bool Load();
4265+ virtual bool Store();
4266+
4267+ /** Returns an indication of rotor progress.
4268+ \return Scale from 0.0..1.0 indicating percentage complete of current
4269+ move. A value of 1.0 indicates motion is complete. */
4270+ double Progress() const;
4271+
4272+ /** Returns true if there is reasonable confidence in the value returned
4273+ by Progress() -- otherwise, Progress() returns progress toward
4274+ the time when the position will be approximately known. */
4275+ bool IsPositionKnown() const { return m_last_pos_known; }
4276+
4277+ dvbdev_rotor_t GetType() const { return m_type; }
4278+ void SetType(dvbdev_rotor_t type) { m_type = type; }
4279+ double GetLoSpeed() const { return m_speed_lo; }
4280+ void SetLoSpeed(double speed) { m_speed_lo = speed; }
4281+ double GetHiSpeed() const { return m_speed_hi; }
4282+ void SetHiSpeed(double speed) { m_speed_hi = speed; }
4283+
4284+ typedef std::map<unsigned int, double> POSMAP;
4285+ POSMAP GetPosMap() const;
4286+ void SetPosMap(const POSMAP& posmap);
4287+
4288+ protected:
4289+ bool ExecuteRotor(const DVBDevSettings& settings,
4290+ const DVBTuning& tuning,
4291+ double angle);
4292+ bool ExecuteUSALS(const DVBDevSettings& settings,
4293+ const DVBTuning& tuning,
4294+ double angle);
4295+
4296+ double CalculateAzimuth(double angle) const;
4297+ double GetApproxAzimuth();
4298+ void RotorMoving(double azimuth);
4299+
4300+ private:
4301+ // configuration
4302+ dvbdev_rotor_t m_type;
4303+ double m_speed_hi;
4304+ double m_speed_lo;
4305+ typedef std::map<double, unsigned int> INTPOSMAP;
4306+ INTPOSMAP m_posmap;
4307+ DVBDevDevice *m_child;
4308+
4309+ // state
4310+ double m_last_position;
4311+ double m_last_azimuth;
4312+ double m_desired_azimuth;
4313+ double m_move_time;
4314+ bool m_last_pos_known;
4315+};
4316+
4317+/** LNB Class. */
4318+class DVBDevLnb : public DVBDevDevice
4319+{
4320+ public:
4321+ DVBDevLnb(DVBDevTree& tree, int dtv_dev_id);
4322+
4323+ virtual bool Execute(const DVBDevSettings& settings,
4324+ const DVBTuning& tuning);
4325+ virtual void Reset();
4326+ virtual bool NeedsCommand(const DVBDevSettings& settings) const;
4327+
4328+ // no children on LNBs
4329+ virtual DVBDevDevice* SelectedChild(const DVBDevSettings&) const { return NULL; }
4330+ virtual unsigned int NumChildren() const { return 0; }
4331+ virtual DVBDevDevice* GetChild(unsigned int) { return NULL; }
4332+ virtual bool SetChild(unsigned int, DVBDevDevice*) { return false; }
4333+ fe_sec_voltage GetVoltage(const DVBDevSettings& settings,
4334+ const DVBTuning& tuning) const;
4335+ virtual bool Load();
4336+ virtual bool Store();
4337+
4338+ /** Determine if the high frequency band is active (for switchable LNBs).
4339+ \param tuning Tuning parameters.
4340+ \return True if high band is active. */
4341+ bool IsHighBand(const DVBTuning& tuning) const;
4342+
4343+ /** Determine if horizontal polarity is active (for switchable LNBs).
4344+ \param tuning Tuning parameters.
4345+ \return True if polarity is horizontal. */
4346+ bool IsHorizontal(const DVBTuning& tuning) const;
4347+
4348+ /** Calculate proper intermediate frequency for the given settings and
4349+ tuning parameters.
4350+ \param settings Configuration chain in effect.
4351+ \param tuning Tuning parameters.
4352+ \return Frequency for use with FE_SET_FRONTEND. */
4353+ __u32 GetIF(const DVBDevSettings& settings,
4354+ const DVBTuning& tuning) const;
4355+
4356+ dvbdev_lnb_t GetType() const { return m_type; }
4357+ void SetType(dvbdev_lnb_t type) { m_type = type; }
4358+ unsigned int GetLOFSwitch() const { return m_lof_switch; }
4359+ void SetLOFSwitch(unsigned int lof_switch) { m_lof_switch = lof_switch; }
4360+ unsigned int GetLOFHigh() const { return m_lof_hi; }
4361+ void SetLOFHigh(unsigned int lof_hi) { m_lof_hi = lof_hi; }
4362+ unsigned int GetLOFLow() const { return m_lof_lo; }
4363+ void SetLOFLow(unsigned int lof_lo) { m_lof_lo = lof_lo; }
4364+
4365+ private:
4366+ dvbdev_lnb_t m_type;
4367+
4368+ unsigned int m_lof_switch;
4369+ unsigned int m_lof_hi;
4370+ unsigned int m_lof_lo;
4371+};
4372+
4373+#endif // DVBDISEQC_H
4374Index: libs/libmythtv/dvbtypes.h
4375===================================================================
4376--- libs/libmythtv/dvbtypes.h (revision 10186)
4377+++ libs/libmythtv/dvbtypes.h (working copy)
4378@@ -318,22 +318,13 @@
4379 {
4380 public:
4381 DVBTuning()
4382- : voltage(SEC_VOLTAGE_OFF), tone(SEC_TONE_OFF),
4383- diseqc_type(0), diseqc_port(0), diseqc_pos(0.0f),
4384- lnb_lof_switch(0), lnb_lof_hi(0), lnb_lof_lo(0)
4385+ : polariz('v')
4386 {
4387 bzero(&params, sizeof(dvb_fe_params));
4388 }
4389
4390 struct dvb_fe_params params;
4391- fe_sec_voltage_t voltage;
4392- fe_sec_tone_mode_t tone;
4393- unsigned int diseqc_type;
4394- unsigned int diseqc_port;
4395- float diseqc_pos;
4396- unsigned int lnb_lof_switch;
4397- unsigned int lnb_lof_hi;
4398- unsigned int lnb_lof_lo;
4399+ char polariz;
4400
4401 bool equalQPSK(const DVBTuning& other, uint range = 0) const
4402 { return equal_qpsk(params, other.params, range); }
4403@@ -348,6 +339,7 @@
4404
4405 // Helper functions to get the paramaters as DB friendly strings
4406 char InversionChar() const;
4407+ char PolarityChar() const;
4408 char TransmissionModeChar() const;
4409 char BandwidthChar() const;
4410 char HierarchyChar() const;
4411@@ -356,7 +348,6 @@
4412
4413 // Helper functions to parse params from DB friendly strings
4414 static fe_bandwidth parseBandwidth( const QString&, bool &ok);
4415- static fe_sec_voltage parsePolarity( const QString&, bool &ok);
4416 static fe_guard_interval parseGuardInterval(const QString&, bool &ok);
4417 static fe_transmit_mode parseTransmission( const QString&, bool &ok);
4418 static fe_hierarchy parseHierarchy( const QString&, bool &ok);
4419@@ -375,6 +366,7 @@
4420 QString HPCodeRateString() const;
4421 QString LPCodeRateString() const;
4422 QString QAMInnerFECString() const;
4423+ QString QPSKInnerFECString() const;
4424 QString ModulationString() const;
4425 QString ConstellationString() const;
4426 QString HierarchyString() const;
4427@@ -390,10 +382,7 @@
4428
4429 bool parseQPSK(const QString& frequency, const QString& inversion,
4430 const QString& symbol_rate, const QString& fec_inner,
4431- const QString& pol, const QString& diseqc_type,
4432- const QString& diseqc_port, const QString& diseqc_pos,
4433- const QString& lnb_lof_switch, const QString& lnb_lof_hi,
4434- const QString& lnb_lof_lo);
4435+ const QString& pol);
4436
4437 bool parseQAM(const QString& frequency, const QString& inversion,
4438 const QString& symbol_rate, const QString& fec_inner,
4439@@ -405,10 +394,7 @@
4440 uint DVBS2SymbolRate() const { return params.u.qpsk2.symbol_rate; }
4441 bool parseDVBS2(const QString& frequency, const QString& inversion,
4442 const QString& symbol_rate, const QString& fec_inner,
4443- const QString& pol, const QString& diseqc_type,
4444- const QString& diseqc_port, const QString& diseqc_pos,
4445- const QString& lnb_lof_switch, const QString& lnb_lof_hi,
4446- const QString& lnb_lof_lo, const QString& modulation);
4447+ const QString& pol);
4448 #endif
4449 };
4450
4451Index: libs/libmythtv/dvbchannel.cpp
4452===================================================================
4453--- libs/libmythtv/dvbchannel.cpp (revision 10186)
4454+++ libs/libmythtv/dvbchannel.cpp (working copy)
4455@@ -52,17 +52,16 @@
4456 #include "mythdbcon.h"
4457 #include "tv_rec.h"
4458 #include "cardutil.h"
4459+#include "channelutil.h"
4460
4461 #include "dvbtypes.h"
4462 #include "dvbchannel.h"
4463 #include "dvbrecorder.h"
4464-#include "dvbdiseqc.h"
4465+#include "dvbdevtree.h"
4466 #include "dvbcam.h"
4467
4468-static uint tuned_frequency(const DVBTuning&, fe_type_t, fe_sec_tone_mode_t *);
4469 static void drain_dvb_events(int fd);
4470 static bool wait_for_backend(int fd, int timeout_ms);
4471-static bool handle_diseq(const DVBTuning&, DVBDiSEqC*, bool reset);
4472
4473 #define LOC QString("DVBChan(%1): ").arg(cardnum)
4474 #define LOC_WARN QString("DVBChan(%1) Warning: ").arg(cardnum)
4475@@ -76,7 +75,8 @@
4476 DVBChannel::DVBChannel(int aCardNum, TVRec *parent)
4477 : ChannelBase(parent),
4478 // Helper classes
4479- diseqc(NULL), dvbcam(NULL),
4480+ devtree(NULL),
4481+ dvbcam(NULL),
4482 // Tuning
4483 tuning_delay(0), sigmon_delay(25),
4484 first_tune(true),
4485@@ -93,11 +93,8 @@
4486 DVBChannel::~DVBChannel()
4487 {
4488 Close();
4489- if (dvbcam)
4490- {
4491- delete dvbcam;
4492- dvbcam = NULL;
4493- }
4494+ delete dvbcam;
4495+ dvbcam = NULL;
4496 }
4497
4498 void DVBChannel::Close()
4499@@ -106,16 +103,13 @@
4500
4501 if (fd_frontend >= 0)
4502 {
4503+ if(devtree)
4504+ devtree->Close();
4505+
4506 close(fd_frontend);
4507 fd_frontend = -1;
4508
4509 dvbcam->Stop();
4510-
4511- if (diseqc)
4512- {
4513- delete diseqc;
4514- diseqc = NULL;
4515- }
4516 }
4517 }
4518
4519@@ -189,23 +183,9 @@
4520 if (info.type == FE_QPSK)
4521 #endif
4522 {
4523- if (ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF) < 0)
4524- {
4525- VERBOSE(VB_GENERAL, LOC_WARN +
4526- "Initial Tone setting failed." + ENO);
4527- }
4528-
4529- if (ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13) < 0)
4530- {
4531- VERBOSE(VB_GENERAL, LOC_WARN +
4532- "Initial Voltage setting failed." + ENO);
4533- }
4534-
4535- if (diseqc == NULL)
4536- {
4537- diseqc = new DVBDiSEqC(cardnum, fd_frontend);
4538- diseqc->DiseqcReset();
4539- }
4540+ devtree = dvbdev.FindTree(GetCardID());
4541+ if(devtree)
4542+ devtree->Open(fd_frontend);
4543 }
4544
4545 dvbcam->Start();
4546@@ -228,7 +208,7 @@
4547 *
4548 * mplexid is how the db indexes each transport
4549 */
4550-bool DVBChannel::TuneMultiplex(uint mplexid)
4551+bool DVBChannel::TuneMultiplex(uint mplexid, int sourceid)
4552 {
4553 if (!GetTransportOptions(mplexid))
4554 return false;
4555@@ -236,7 +216,7 @@
4556 CheckOptions();
4557 VERBOSE(VB_CHANNEL, LOC + cur_tuning.toString(info.type));
4558
4559- if (!Tune(cur_tuning))
4560+ if (!Tune(cur_tuning, false, sourceid))
4561 return false;
4562
4563 return true;
4564@@ -406,9 +386,7 @@
4565 // Query for our DVBTuning params
4566 query.prepare(
4567 "SELECT frequency, inversion, symbolrate, "
4568- " fec, polarity, dvb_diseqc_type, "
4569- " diseqc_port, diseqc_pos, lnb_lof_switch, "
4570- " lnb_lof_hi, lnb_lof_lo, sistandard, "
4571+ " fec, polarity, sistandard, "
4572 " hp_code_rate, lp_code_rate, constellation, "
4573 " transmission_mode, guard_interval, hierarchy, "
4574 " modulation, bandwidth, cardinputid "
4575@@ -444,18 +422,13 @@
4576 query.value(8).toString(), query.value(9).toString(),
4577 query.value(10).toString(), query.value(11).toString(),
4578 query.value(12).toString(), query.value(13).toString(),
4579- query.value(14).toString(), query.value(15).toString(),
4580- query.value(16).toString(), query.value(17).toString(),
4581- query.value(18).toString(), query.value(19).toString(),
4582- query.value(20).toString());
4583+ query.value(14).toString());
4584 }
4585
4586 bool DVBChannel::ParseTuningParams(
4587 fe_type_t type,
4588 QString frequency, QString inversion, QString symbolrate,
4589- QString fec, QString polarity, QString dvb_diseqc_type,
4590- QString diseqc_port, QString diseqc_pos, QString lnb_lof_switch,
4591- QString lnb_lof_hi, QString lnb_lof_lo, QString _sistandard,
4592+ QString fec, QString polarity, QString _sistandard,
4593 QString hp_code_rate, QString lp_code_rate, QString constellation,
4594 QString trans_mode, QString guard_interval, QString hierarchy,
4595 QString modulation, QString bandwidth, QString _input_id)
4596@@ -465,9 +438,7 @@
4597
4598 if (FE_QPSK == type)
4599 return cur_tuning.parseQPSK(
4600- frequency, inversion, symbolrate, fec, polarity,
4601- dvb_diseqc_type, diseqc_port, diseqc_pos,
4602- lnb_lof_switch, lnb_lof_hi, lnb_lof_lo);
4603+ frequency, inversion, symbolrate, fec, polarity);
4604 else if (FE_QAM == type)
4605 return cur_tuning.parseQAM(
4606 frequency, inversion, symbolrate, fec, modulation);
4607@@ -499,7 +470,13 @@
4608 t.params.inversion = INVERSION_OFF;
4609 }
4610
4611- uint frequency = tuned_frequency(t, info.type, NULL);
4612+ uint frequency = t.params.frequency;
4613+ if(devtree)
4614+ {
4615+ DVBDevLnb* lnb = devtree->FindLNB(devset);
4616+ if(lnb)
4617+ frequency = lnb->GetIF(devset, t);
4618+ }
4619
4620 if ((info.frequency_min > 0 && info.frequency_max > 0) &&
4621 (frequency < info.frequency_min || frequency > info.frequency_max))
4622@@ -690,18 +667,33 @@
4623 * \param channel Info on transport to tune to
4624 * \param force_reset If true, frequency tuning is done
4625 * even if it should not be needed.
4626+ * \param source_id Optional, forces specific sourceid (for diseqc setup).
4627+ * \param same_input Optional, doesn't change input (for retuning).
4628 * \return true on success, false on failure
4629 */
4630-bool DVBChannel::Tune(const DVBTuning &tuning, bool force_reset)
4631+bool DVBChannel::Tune(const DVBTuning &tuning,
4632+ bool force_reset,
4633+ int source_id,
4634+ bool same_input)
4635 {
4636- bool reset = (force_reset || first_tune);
4637- bool has_diseq = (FE_QPSK == info.type) && diseqc;
4638- struct dvb_fe_params params = tuning.params;
4639+ QMutexLocker lock(&tune_lock);
4640
4641+ bool reset = (force_reset || first_tune);
4642+ bool is_dvbs = (FE_QPSK == info.type);
4643 #ifdef FE_GET_EXTENDED_INFO
4644- has_diseq |= (FE_DVB_S2 == info.type) && diseqc;
4645+ is_dvbs |= (FE_DVB_S2 == info.type);
4646 #endif // FE_GET_EXTENDED_INFO
4647+ bool has_diseqc = (devtree != NULL);
4648+ struct dvb_fe_params params = tuning.params;
4649
4650+ tune_time.start();
4651+
4652+ if(is_dvbs && !has_diseqc)
4653+ {
4654+ VERBOSE(VB_IMPORTANT, LOC_ERR + "DVB-S needs device tree");
4655+ return false;
4656+ }
4657+
4658 if (fd_frontend < 0)
4659 {
4660 VERBOSE(VB_IMPORTANT, LOC_ERR + "Tune(): Card not open!");
4661@@ -712,13 +704,37 @@
4662 // Remove any events in queue before tuning.
4663 drain_dvb_events(fd_frontend);
4664
4665- // Send DisEq commands to external hardware if we need to.
4666- if (has_diseq && !handle_diseq(tuning, diseqc, reset))
4667+ // send DVB-S setup
4668+ if (is_dvbs)
4669 {
4670- VERBOSE(VB_IMPORTANT, LOC_ERR + "Tune(): "
4671- "Failed to transmit DisEq commands");
4672+ // configure for new input
4673+ if(!same_input)
4674+ {
4675+ devset.Load(source_id == -1 ? nextInputID :
4676+ ChannelUtil::GetInputID(source_id, GetCardID()));
4677+ }
4678+
4679+ // execute diseqc commands
4680+ if(!devtree->Execute(devset, tuning))
4681+ {
4682+ VERBOSE(VB_IMPORTANT, LOC_ERR + "Tune(): "
4683+ "Failed to setup DiSEqC devices");
4684+ return false;
4685+ }
4686
4687- return false;
4688+ // retrieve actual intermediate frequency
4689+ DVBDevLnb* lnb = devtree->FindLNB(devset);
4690+ if(!lnb)
4691+ {
4692+ VERBOSE(VB_IMPORTANT, LOC_ERR + "Tune(): "
4693+ "No LNB for this configuration");
4694+ return false;
4695+ }
4696+ params.frequency = lnb->GetIF(devset, tuning);
4697+
4698+ // if card can auto-FEC, use it -- sometimes NITs are inaccurate
4699+ if(info.caps & FE_CAN_FEC_AUTO)
4700+ params.u.qpsk.fec_inner = FEC_AUTO;
4701 }
4702
4703 VERBOSE(VB_CHANNEL, LOC + "Old Params: " +
4704@@ -726,11 +742,15 @@
4705 "\n\t\t\t" + LOC + "New Params: " +
4706 tuning.toString(info.type));
4707
4708- if (reset || !prev_tuning.equal(info.type, tuning, 500000))
4709- {
4710- // Adjust for Satelite recievers which offset the frequency.
4711- params.frequency = tuned_frequency(tuning, info.type, NULL);
4712+ // DVB-S is in kHz, other DVB is in Hz
4713+ int freq_mult = is_dvbs ? 1 : 1000;
4714+ const char* suffix = is_dvbs ? "kHz" : "Hz";
4715
4716+ if (reset || !prev_tuning.equal(info.type, tuning, 500 * freq_mult))
4717+ {
4718+ VERBOSE(VB_CHANNEL, LOC + QString("Tune(): Tuning to %1%2")
4719+ .arg(params.frequency)
4720+ .arg(suffix));
4721 #ifdef FE_GET_EXTENDED_INFO
4722 if (info.type == FE_DVB_S2)
4723 {
4724@@ -767,6 +787,11 @@
4725 return true;
4726 }
4727
4728+bool DVBChannel::Retune()
4729+{
4730+ return Tune(prev_tuning, true, -1, true);
4731+}
4732+
4733 /** \fn DVBChannel::GetTuningParams(DVBTuning& tuning) const
4734 * \brief Fetches DVBTuning params from driver
4735 * \return true on success, false on failure
4736@@ -836,6 +861,22 @@
4737 ChannelBase::GetCachedPids(chanid, pid_cache);
4738 }
4739
4740+const DVBDevRotor* DVBChannel::GetRotor() const
4741+{
4742+ const DVBDevRotor* rotor = devtree ? devtree->FindRotor(devset) : NULL;
4743+ return rotor;
4744+}
4745+
4746+bool DVBChannel::CanRecover() const
4747+{
4748+ return info.caps & FE_CAN_RECOVER;
4749+}
4750+
4751+int DVBChannel::ElapsedSinceTune() const
4752+{
4753+ return first_tune ? 0 : tune_time.elapsed();
4754+}
4755+
4756 /** \fn drain_dvb_events(int)
4757 * \brief Reads all the events off the queue, so we can use select
4758 * in wait_for_backend(int,int).
4759@@ -846,28 +887,6 @@
4760 while (ioctl(fd, FE_GET_EVENT, &event) == 0);
4761 }
4762
4763-static uint tuned_frequency(const DVBTuning &tuning, fe_type_t type,
4764- fe_sec_tone_mode_t *p_tone)
4765-{
4766-#ifdef FE_GET_EXTENDED_INFO
4767- if (FE_QPSK != type && FE_DVB_S2 != type)
4768- return tuning.Frequency();
4769-#else
4770- if (FE_QPSK != type)
4771- return tuning.Frequency();
4772-#endif
4773-
4774- uint freq = tuning.Frequency();
4775- bool tone = freq >= tuning.lnb_lof_switch;
4776- uint lnb_hi = (uint) abs((int)freq - (int)tuning.lnb_lof_hi);
4777- uint lnb_lo = (uint) abs((int)freq - (int)tuning.lnb_lof_lo);
4778-
4779- if (p_tone)
4780- *p_tone = (tone) ? SEC_TONE_ON : SEC_TONE_OFF;
4781-
4782- return (tone) ? lnb_hi : lnb_lo;
4783-}
4784-
4785 /** \fn wait_for_backend(int,int)
4786 * \brief Waits for backend to get tune message.
4787 *
4788@@ -916,26 +935,3 @@
4789 .arg(toString(status)));
4790 return true;
4791 }
4792-
4793-/** \fn handle_diseq(const DVBTuning&, DVBDiSEqC*, bool)
4794- * \brief Sends DisEq commands to external hardware.
4795- *
4796- */
4797-static bool handle_diseq(const DVBTuning &ct, DVBDiSEqC *diseqc, bool reset)
4798-{
4799- if (!diseqc)
4800- return false;
4801-
4802- bool tuned = false;
4803- DVBTuning t = ct;
4804- t.params.frequency = tuned_frequency(ct, FE_QPSK, &t.tone);
4805-
4806- for (uint i = 0; i < 64 && !tuned; i++)
4807- if (!diseqc->Set(t, reset, tuned))
4808- return false;
4809-
4810- // Wait 10 ms, recommended by Marcus Metzler, see #1552
4811- usleep(10 * 1000);
4812-
4813- return true;
4814-}
4815Index: libs/libmythtv/cardutil.cpp
4816===================================================================
4817--- libs/libmythtv/cardutil.cpp (revision 10186)
4818+++ libs/libmythtv/cardutil.cpp (working copy)
4819@@ -332,28 +332,6 @@
4820 return "DVB" == GetRawCardType(cardid, inputname);
4821 }
4822
4823-/** \fn CardUtil::GetDISEqCType(uint)
4824- * \brief Returns the disqec type associated with a DVB card
4825- * \param nCardID card id to check
4826- * \return the disqec type
4827- */
4828-enum DISEQC_TYPES CardUtil::GetDISEqCType(uint nCardID)
4829-{
4830- int iRet = 0;
4831- MSqlQuery query(MSqlQuery::InitCon());
4832- query.prepare("SELECT dvb_diseqc_type "
4833- "FROM capturecard "
4834- "WHERE capturecard.cardid = :CARDID");
4835- query.bindValue(":CARDID", nCardID);
4836-
4837- if (!query.exec() || !query.isActive())
4838- MythContext::DBError("CardUtil::GetDISEqCType()", query);
4839- else if (query.next())
4840- iRet = query.value(0).toInt();
4841-
4842- return (DISEQC_TYPES)iRet;
4843-}
4844-
4845 /** \fn CardUtil::GetDefaultInput(uint)
4846 * \brief Returns the default input for the card
4847 * \param nCardID card id to check
4848@@ -564,9 +542,25 @@
4849 return list;
4850 }
4851
4852-QStringList CardUtil::probeInputs(QString device, QString cardtype,
4853- int diseqctype)
4854+InputNames CardUtil::configuredDVBInputs(uint cardid)
4855 {
4856+ InputNames list;
4857+ MSqlQuery query(MSqlQuery::InitCon());
4858+ query.prepare("SELECT cardinputid, inputname"
4859+ " FROM cardinput"
4860+ " WHERE cardid = :CARDID");
4861+ query.bindValue(":CARDID", cardid);
4862+
4863+ if (query.exec() && query.isActive() && query.size() > 0)
4864+ {
4865+ while(query.next())
4866+ list[query.value(0).toUInt()] = query.value(1).toString();
4867+ }
4868+ return list;
4869+}
4870+
4871+QStringList CardUtil::probeInputs(QString device, QString cardtype)
4872+{
4873 QStringList ret;
4874
4875 if (("FIREWIRE" == cardtype) ||
4876@@ -577,7 +571,7 @@
4877 ret += "MPEG2TS";
4878 }
4879 else if ("DVB" == cardtype)
4880- ret += probeDVBInputs(device, diseqctype);
4881+ ret += probeDVBInputs(device);
4882 else
4883 ret += probeV4LInputs(device);
4884
4885@@ -616,28 +610,24 @@
4886 return ret;
4887 }
4888
4889-QStringList CardUtil::probeDVBInputs(QString device, int diseqc_type)
4890+QStringList CardUtil::probeDVBInputs(QString device)
4891 {
4892 QStringList ret;
4893
4894 #ifdef USING_DVB
4895- if (diseqc_type < 0)
4896+ int cardid = CardUtil::GetCardID(device);
4897+ if (cardid <= 0)
4898+ return ret;
4899+
4900+ InputNames list = configuredDVBInputs(cardid);
4901+ InputNames::iterator it;
4902+ for (it = list.begin(); it != list.end(); ++it)
4903 {
4904- int cardid = CardUtil::GetCardID(device);
4905- if (cardid <= 0)
4906- return ret;
4907- diseqc_type = GetDISEqCType(cardid);
4908+ if (it.key() >= 0)
4909+ ret += *it;
4910 }
4911-
4912- QValueList<DVBDiSEqCInput> dvbinput;
4913- dvbinput = fillDVBInputsDiSEqC(diseqc_type);
4914-
4915- QValueList<DVBDiSEqCInput>::iterator it;
4916- for (it = dvbinput.begin(); it != dvbinput.end(); ++it)
4917- ret += (*it).input;
4918 #else
4919 (void) device;
4920- (void) diseqc_type;
4921 ret += QObject::tr("ERROR, Compile with DVB support to query inputs");
4922 #endif
4923
4924@@ -668,66 +658,6 @@
4925 return ret;
4926 }
4927
4928-QValueList<DVBDiSEqCInput>
4929-CardUtil::fillDVBInputsDiSEqC(int dvb_diseqc_type)
4930-{
4931- QValueList<DVBDiSEqCInput> list;
4932-
4933- QString stxt = "DiSEqC Switch Input %1";
4934- QString mtxt = "DiSEqC v1.2 Motor Position %1";
4935- QString itxt = "DiSEqC v1.3 Input %1";
4936- QString l21txt = "SW21 Input %1";
4937- QString l64txt = "SW64 Input %1";
4938-
4939- switch (dvb_diseqc_type)
4940- {
4941- case DISEQC_MINI_2:
4942- case DISEQC_SWITCH_2_1_0:
4943- case DISEQC_SWITCH_2_1_1:
4944- for (uint i = 0; i < 2; ++i)
4945- list.append(DVBDiSEqCInput(
4946- stxt.arg(i+1), QString::number(i), ""));
4947- break;
4948- case DISEQC_SWITCH_4_1_0:
4949- case DISEQC_SWITCH_4_1_1:
4950- for (uint i = 0; i < 4; ++i)
4951- list.append(DVBDiSEqCInput(
4952- stxt.arg(i+1), QString::number(i), ""));
4953- break;
4954- case DISEQC_POSITIONER_1_2:
4955- for (uint i = 1; i < 50; ++i)
4956- list.append(DVBDiSEqCInput(
4957- mtxt.arg(i), "", QString::number(i)));
4958- break;
4959- case DISEQC_POSITIONER_X:
4960- for (uint i = 1; i < 20; ++i)
4961- list.append(DVBDiSEqCInput(
4962- itxt.arg(i), "", QString::number(i)));
4963- break;
4964- case DISEQC_POSITIONER_1_2_SWITCH_2:
4965- for (uint i = 0; i < 10; ++i)
4966- list.append(DVBDiSEqCInput(
4967- stxt.arg(i+1,2), QString::number(i), ""));
4968- break;
4969- case DISEQC_SW21:
4970- for (uint i = 0; i < 2; ++i)
4971- list.append(DVBDiSEqCInput(
4972- l21txt.arg(i+1,2), QString::number(i), ""));
4973- break;
4974- case DISEQC_SW64:
4975- for (uint i = 0; i < 3; ++i)
4976- list.append(DVBDiSEqCInput(
4977- l64txt.arg(i+1,2), QString::number(i), ""));
4978- break;
4979- case DISEQC_SINGLE:
4980- default:
4981- list.append(DVBDiSEqCInput(
4982- QString("DVBInput"), QString(""), QString("")));
4983- }
4984-
4985- return list;
4986-}
4987-
4988 QString CardUtil::GetDeviceLabel(uint cardid,
4989 QString cardtype,
4990 QString videodevice)
4991@@ -818,7 +748,7 @@
4992 QStringList::iterator it = inputs.begin();
4993 for (; it != inputs.end(); ++it)
4994 {
4995- CardInput* cardinput = new CardInput(false);
4996+ CardInput* cardinput = new CardInput(false, cardid);
4997 cardinput->loadByInput(rcardid, (*it));
4998 cardinput->SetChildCardID((parentid) ? cardid : 0);
4999 inputLabels.push_back(
5000@@ -827,24 +757,41 @@
5001 cardInputs.push_back(cardinput);
5002 }
5003
5004+#ifdef USING_DVB
5005 if ("DVB" == cardtype)
5006 {
5007- QValueList<DVBDiSEqCInput> dvbinputs;
5008- int diseq_type = GetDISEqCType(cardid);
5009- dvbinputs = fillDVBInputsDiSEqC(diseq_type);
5010- QValueList<DVBDiSEqCInput>::iterator it;
5011- for (it = dvbinputs.begin(); it != dvbinputs.end(); ++it)
5012+ InputNames list;
5013+ bool needs_conf = DTVDeviceNeedsConfiguration(rcardid);
5014+ if(needs_conf)
5015+ list = configuredDVBInputs(rcardid);
5016+ else
5017+ list[0] = "DVBInput";
5018+
5019+ InputNames::iterator it;
5020+ for (it = list.begin(); it != list.end(); ++it)
5021 {
5022- CardInput* cardinput = new CardInput(true);
5023- cardinput->loadByInput(rcardid, (*it).input);
5024- cardinput->fillDiseqcSettingsInput((*it).position,(*it).port);
5025- cardinput->SetChildCardID((parentid) ? cardid : 0);
5026+ CardInput* cardinput = new CardInput(true, rcardid);
5027+ cardinput->loadByInput(rcardid, it.data());
5028+ cardinput->SetChildCardID(parentid ? cardid : 0);
5029 inputLabels.push_back(
5030 dev_label + QString(" (%1) -> %2")
5031- .arg((*it).input).arg(cardinput->getSourceName()));
5032+ .arg(it.data()).arg(cardinput->getSourceName()));
5033 cardInputs.push_back(cardinput);
5034 }
5035+
5036+ // plus add one "new" input
5037+ if(needs_conf)
5038+ {
5039+ CardInput* newcard = new CardInput(true, rcardid);
5040+ QString newname = QString("DVBInput #%1").arg(list.size()+1);
5041+ newcard->loadByInput(rcardid, newname);
5042+ newcard->SetChildCardID((parentid) ? cardid : 0);
5043+ inputLabels.push_back(
5044+ dev_label + QString(" New Input"));
5045+ cardInputs.push_back(newcard);
5046+ }
5047 }
5048+#endif // USING_DVB
5049
5050 if (parentid)
5051 return;
5052@@ -872,6 +819,17 @@
5053 if (!cardid)
5054 return true;
5055
5056+#ifdef USING_DVB
5057+ // delete device tree
5058+ DVBDevTree tree;
5059+ tree.Load(cardid);
5060+ if(tree.Root() != NULL)
5061+ {
5062+ tree.SetRoot(NULL);
5063+ tree.Store(cardid);
5064+ }
5065+#endif
5066+
5067 // delete any children
5068 MSqlQuery query(MSqlQuery::InitCon());
5069 query.prepare(
5070Index: libs/libmythtv/videosource.cpp
5071===================================================================
5072--- libs/libmythtv/videosource.cpp (revision 10186)
5073+++ libs/libmythtv/videosource.cpp (working copy)
5074@@ -33,6 +33,7 @@
5075
5076 #ifdef USING_DVB
5077 #include <linux/dvb/frontend.h>
5078+#include "dvbdevtree_cfg.h"
5079 #endif
5080
5081 #if defined(CONFIG_VIDEO4LINUX)
5082@@ -45,12 +46,6 @@
5083 RecorderOptions(CaptureCard& parent);
5084 };
5085
5086-class DVBDiSEqCConfigurationWizard: public ConfigurationWizard
5087-{
5088- public:
5089- DVBDiSEqCConfigurationWizard(CaptureCard &parent);
5090-};
5091-
5092 QString VSSetting::whereClause(MSqlBindings& bindings)
5093 {
5094 QString sourceidTag(":WHERESOURCEID");
5095@@ -785,42 +780,6 @@
5096 };
5097 };
5098
5099-class DVBDiSEqCType: public ComboBoxSetting, public CCSetting
5100-{
5101- public:
5102- DVBDiSEqCType(const CaptureCard& parent)
5103- : CCSetting(parent, "dvb_diseqc_type")
5104- {
5105- setLabel(QObject::tr("DiSEqC Input Type: (DVB-S)"));
5106- addSelection(QObject::tr("Single LNB / Input"),
5107- QString::number(DISEQC_SINGLE));
5108- addSelection(QObject::tr("Tone Switch aka Mini DiSEqC (2-Way)"),
5109- QString::number(DISEQC_MINI_2));
5110- addSelection(QObject::tr("DiSEqC v1.0 Switch (2-Way)"),
5111- QString::number(DISEQC_SWITCH_2_1_0));
5112- addSelection(QObject::tr("DiSEqC v1.1 Switch (2-Way)"),
5113- QString::number(DISEQC_SWITCH_2_1_1));
5114- addSelection(QObject::tr("DiSEqC v1.0 Switch (4-Way)"),
5115- QString::number(DISEQC_SWITCH_4_1_0));
5116- addSelection(QObject::tr("DiSEqC v1.1 Switch (4-Way)"),
5117- QString::number(DISEQC_SWITCH_4_1_1));
5118- addSelection(QObject::tr("DiSEqC v1.2 Positioner"),
5119- QString::number(DISEQC_POSITIONER_1_2));
5120- addSelection(QObject::tr("DiSEqC v1.3 Positioner (Goto X)"),
5121- QString::number(DISEQC_POSITIONER_X));
5122- addSelection(QObject::tr("DiSEqC v1.1 or 2.1 (10-way method2)"),
5123- QString::number(DISEQC_POSITIONER_1_2_SWITCH_2));
5124- addSelection(QObject::tr("SW21 Switch (2-Way)"),
5125- QString::number(DISEQC_SW21));
5126- addSelection(QObject::tr("SW64 Switch (3-Way)"),
5127- QString::number(DISEQC_SW64));
5128- setHelpText(QObject::tr("Select the input type for DVB-S cards. "
5129- "Leave as Single LNB/Input for DVB-C or DVB-T. "
5130- "The inputs are mapped from Input Connections option "
5131- "on the main menu"));
5132- };
5133-};
5134-
5135 class DVBTuningDelay: public SpinBoxSetting, public CCSetting
5136 {
5137 public:
5138@@ -1296,8 +1255,21 @@
5139 }
5140 }
5141
5142+void CaptureCard::save()
5143+{
5144+ ConfigurationWizard::save();
5145+#ifdef USING_DVB
5146+ tree.Store(getCardID());
5147+ DVBDev trees;
5148+ trees.InvalidateTrees();
5149+#endif
5150+}
5151+
5152 void CaptureCard::loadByID(int cardid)
5153 {
5154+#ifdef USING_DVB
5155+ tree.Load(cardid);
5156+#endif
5157 id->setValue(cardid);
5158 load();
5159 }
5160@@ -1431,75 +1403,6 @@
5161 };
5162 };
5163
5164-class LNBLofSwitch: public LineEditSetting, public CISetting {
5165- public:
5166- LNBLofSwitch(const CardInput& parent):
5167- CISetting(parent, "lnb_lof_switch") {
5168- setLabel(QObject::tr("LNB LOF Switch"));
5169- setValue("11700000");
5170- setHelpText(QObject::tr("This defines at what frequency (in Hz) "
5171- "the LNB will do a switch from high to low setting, "
5172- "and vice versa."));
5173- };
5174-};
5175-
5176-class LNBLofHi: public LineEditSetting, public CISetting {
5177- public:
5178- LNBLofHi(const CardInput& parent):
5179- CISetting(parent, "lnb_lof_hi") {
5180- setLabel(QObject::tr("LNB LOF High"));
5181- setValue("10600000");
5182- setHelpText(QObject::tr("This defines the offset (in Hz) the "
5183- "frequency coming from the LNB will be in high "
5184- "setting."));
5185- };
5186-};
5187-
5188-class LNBLofLo: public LineEditSetting, public CISetting {
5189- public:
5190- LNBLofLo(const CardInput& parent):
5191- CISetting(parent, "lnb_lof_lo") {
5192- setLabel(QObject::tr("LNB LOF Low"));
5193- setValue("9750000");
5194- setHelpText(QObject::tr("This defines the offset (in Hz) the "
5195- "frequency coming from the LNB will be in low "
5196- "setting."));
5197- };
5198-};
5199-
5200-class DiSEqCPos: public LineEditSetting, public CISetting
5201-{
5202- public:
5203- DiSEqCPos(const CardInput& parent)
5204- : CISetting(parent, "diseqc_pos")
5205- {
5206- setLabel(QObject::tr("DiSEqC Satellite Location"));
5207- setValue("0.0");
5208- setHelpText(QObject::tr("The longitude of the satellite "
5209- "you are aiming at. For western hemisphere use "
5210- "a negative value. Value is in decimal."));
5211-// setVisible(false);
5212- };
5213-// void fillSelections(const QString& pos) {
5214-// setValue(pos);
5215-// };
5216-};
5217-
5218-
5219-class DiSEqCPort: public LabelSetting, public CISetting
5220-{
5221- public:
5222- DiSEqCPort(const CardInput& parent)
5223- : CISetting(parent, "diseqc_port")
5224- {
5225- setVisible(false);
5226- };
5227- void fillSelections(const QString& port) {
5228- setValue(port);
5229- };
5230-};
5231-
5232-
5233 class FreeToAir: public CheckBoxSetting, public CISetting {
5234 public:
5235 FreeToAir(const CardInput& parent):
5236@@ -1614,26 +1517,6 @@
5237 };
5238 };
5239
5240-class DVBLNBChooser: public ComboBoxSetting {
5241- public:
5242- DVBLNBChooser()
5243- {
5244- setLabel("LNB Settings: (DVB-S)");
5245- addSelection("Universal - 2");
5246- addSelection("DBS");
5247- addSelection("Universal - 1");
5248- addSelection("Custom");
5249- setHelpText(
5250- QObject::tr("Select the LNB Settings for DVB-S cards.") + " " +
5251- QObject::tr("For DVB-C and DVB-T you don't need to "
5252- "set these values."));
5253- };
5254- void save() {};
5255- void load() {};
5256-
5257-private:
5258-};
5259-
5260 class DishNetEIT: public CheckBoxSetting, public CISetting
5261 {
5262 public:
5263@@ -1650,7 +1533,7 @@
5264 };
5265 };
5266
5267-CardInput::CardInput(bool isDVBcard)
5268+CardInput::CardInput(bool isDVBcard, int _cardid)
5269 {
5270 addChild(id = new ID());
5271
5272@@ -1672,6 +1555,31 @@
5273 group->addChild(new PresetTuner(*this));
5274 }
5275
5276+#ifdef USING_DVB
5277+ if (isDVBcard)
5278+ {
5279+ ConfigurationGroup *dvbgroup =
5280+ new HorizontalConfigurationGroup();
5281+ dvbgroup->setLabel(QObject::tr("DVB options"));
5282+
5283+ ConfigurationGroup *chgroup =
5284+ new VerticalConfigurationGroup(false, false, true, true);
5285+
5286+ TransButtonSetting *diseqc = new TransButtonSetting();
5287+ diseqc->setLabel(tr("DVB-S"));
5288+ diseqc->setHelpText(tr("Input and satellite settings."));
5289+ diseqc->setVisible(DTVDeviceNeedsConfiguration(_cardid));
5290+ dvbgroup->addChild(diseqc);
5291+ connect(diseqc, SIGNAL(pressed()), SLOT(diseqcConfig()));
5292+
5293+ chgroup->addChild(new FreeToAir(*this));
5294+ chgroup->addChild(new RadioServices(*this));
5295+ chgroup->addChild(new DishNetEIT(*this));
5296+ dvbgroup->addChild(chgroup);
5297+ group->addChild(dvbgroup);
5298+ }
5299+#endif
5300+
5301 TransButtonSetting *scan = new TransButtonSetting();
5302 scan->setLabel(tr("Scan for channels"));
5303 scan->setHelpText(
5304@@ -1696,25 +1604,6 @@
5305
5306 addChild(group);
5307
5308-#ifdef USING_DVB
5309- if (isDVBcard)
5310- {
5311- ConfigurationGroup *dvbgroup =
5312- new VerticalConfigurationGroup(false, false, true, true);
5313-
5314- dvbgroup->addChild(diseqcpos = new DiSEqCPos(*this));
5315- dvbgroup->addChild(diseqcport = new DiSEqCPort(*this));
5316- dvbgroup->addChild(lnblofswitch = new LNBLofSwitch(*this));
5317- dvbgroup->addChild(lnblofhi = new LNBLofHi(*this));
5318- dvbgroup->addChild(lnbloflo = new LNBLofLo(*this));
5319-
5320- dvbgroup->addChild(new FreeToAir(*this));
5321- dvbgroup->addChild(new RadioServices(*this));
5322- dvbgroup->addChild(new DishNetEIT(*this));
5323- addChild(dvbgroup);
5324- }
5325-#endif
5326-
5327 childid = new ChildID(*this);
5328 addChild(childid);
5329
5330@@ -1778,6 +1667,14 @@
5331 }
5332 }
5333
5334+void CardInput::diseqcConfig(void)
5335+{
5336+#ifdef USING_DVB
5337+ DTVDeviceConfigWizard wizard(settings, cardid->getValue().toUInt());
5338+ wizard.exec();
5339+#endif // USING_DVB
5340+}
5341+
5342 QString CISetting::whereClause(MSqlBindings& bindings)
5343 {
5344 QString cardinputidTag(":WHERECARDINPUTID");
5345@@ -1806,6 +1703,9 @@
5346 void CardInput::loadByID(int inputid)
5347 {
5348 id->setValue(inputid);
5349+#ifdef USING_DVB
5350+ settings.Load(inputid);
5351+#endif
5352 load();
5353 }
5354
5355@@ -1828,32 +1728,6 @@
5356 cardid->setValue(QString::number(_cardid));
5357 inputname->setValue(_inputname);
5358 }
5359-
5360- if (CardUtil::IsDVB(_cardid, _inputname))
5361- {
5362- QString subtype = CardUtil::ProbeSubTypeName(_cardid, _inputname);
5363- CardUtil::CARD_TYPES dvbType = CardUtil::toCardType(subtype);
5364-
5365- if ("QPSK" == subtype)
5366- {
5367- //Check for DiSEqC type
5368- diseqcpos->setVisible(true);
5369- lnblofswitch->setVisible(true);
5370- lnbloflo->setVisible(true);
5371- lnblofhi->setVisible(true);
5372-
5373- DISEQC_TYPES dt = CardUtil::GetDISEqCType(_cardid);
5374- bool pos = (dt == DISEQC_POSITIONER_X);
5375- diseqcpos->setEnabled(pos);
5376- }
5377- else if (dvbType > CardUtil::ERROR_PROBE)
5378- {
5379- diseqcpos->setVisible(false);
5380- lnblofswitch->setVisible(false);
5381- lnbloflo->setVisible(false);
5382- lnblofhi->setVisible(false);
5383- }
5384- }
5385 }
5386
5387 void CardInput::save()
5388@@ -1870,17 +1744,12 @@
5389 else
5390 {
5391 ConfigurationWizard::save();
5392+#ifdef USING_DVB
5393+ settings.Store(getInputID());
5394+#endif
5395 }
5396 }
5397
5398-void CardInput::fillDiseqcSettingsInput(QString _pos, QString _port)
5399-{
5400- if (_port != "")
5401- diseqcport->setValue(_port);
5402- if (_pos != "")
5403- diseqcpos->setValue(_pos);
5404-}
5405-
5406 int CISetting::getInputID(void) const
5407 {
5408 return parent.getInputID();
5409@@ -2140,6 +2009,7 @@
5410
5411 void CardInputEditor::load()
5412 {
5413+ cardinputs.clear();
5414 clearSelections();
5415
5416 // We do this manually because we want custom labels. If
5417@@ -2327,23 +2197,12 @@
5418
5419 last_device = device;
5420 QStringList inputs =
5421- CardUtil::probeInputs(device, last_cardtype, last_diseqct);
5422+ CardUtil::probeInputs(device, last_cardtype);
5423
5424 for (QStringList::iterator i = inputs.begin(); i != inputs.end(); ++i)
5425 addSelection(*i);
5426 }
5427
5428-void TunerCardInput::diseqcType(const QString &diseqcType)
5429-{
5430- bool ok;
5431- int tmp = diseqcType.toInt(&ok);
5432- if (ok)
5433- {
5434- last_diseqct = tmp;
5435- fillSelections(last_device);
5436- }
5437-}
5438-
5439 DVBConfigurationGroup::DVBConfigurationGroup(CaptureCard& a_parent) :
5440 ConfigurationGroup(false, true, false, false),
5441 VerticalConfigurationGroup(false, true, false, false),
5442@@ -2370,10 +2229,6 @@
5443 addChild(new DVBAudioDevice(parent));
5444 addChild(new DVBVbiDevice(parent));
5445
5446- TransButtonSetting *buttonDiSEqC = new TransButtonSetting();
5447- buttonDiSEqC->setLabel(tr("DiSEqC"));
5448- buttonDiSEqC->setHelpText(tr("Input and satellite settings."));
5449-
5450 buttonAnalog = new TransButtonSetting();
5451 buttonAnalog->setLabel(tr("Analog Options"));
5452 buttonAnalog->setVisible(false);
5453@@ -2385,9 +2240,12 @@
5454 "but the DVB drivers do not yet allow us to "
5455 "detect this problem."));
5456
5457+ TransButtonSetting *buttonDiSEqC = new TransButtonSetting();
5458+ buttonDiSEqC->setLabel(tr("DVB-S"));
5459+ buttonDiSEqC->setHelpText(tr("Input and satellite settings."));
5460+
5461 TransButtonSetting *buttonRecOpt = new TransButtonSetting();
5462 buttonRecOpt->setLabel(tr("Recording Options"));
5463- buttonDiSEqC->setHelpText(tr("Various additional settings."));
5464
5465 HorizontalConfigurationGroup *advcfg =
5466 new HorizontalConfigurationGroup(false, false, true, true);
5467@@ -2396,10 +2254,6 @@
5468 advcfg->addChild(buttonRecOpt);
5469 addChild(advcfg);
5470
5471- DVBDiSEqCType *diseqctype = new DVBDiSEqCType(parent);
5472- addChild(diseqctype);
5473- diseqctype->setVisible(false);
5474-
5475 TunerCardInput *defaultinput = new TunerCardInput(parent, "0", "DVB");
5476 addChild(defaultinput);
5477 defaultinput->setVisible(false);
5478@@ -2418,10 +2272,7 @@
5479 &parent, SLOT( analogPanel()));
5480 connect(buttonRecOpt, SIGNAL(pressed()),
5481 &parent, SLOT( recorderOptionsPanel()));
5482- connect(diseqctype, SIGNAL(valueChanged(const QString&)),
5483- defaultinput, SLOT( diseqcType (const QString&)));
5484
5485- defaultinput->diseqcType(diseqctype->getValue());
5486 cardnum->setValue(0);
5487 }
5488
5489@@ -2466,11 +2317,13 @@
5490
5491 void CaptureCard::DiSEqCPanel()
5492 {
5493+#ifdef USING_DVB
5494 reload();
5495
5496- DVBDiSEqCConfigurationWizard diseqcWiz(*this);
5497+ DTVDeviceTreeWizard diseqcWiz(tree);
5498 diseqcWiz.exec();
5499 load();
5500+#endif // USING_DVB
5501 }
5502
5503 RecorderOptions::RecorderOptions(CaptureCard& parent)
5504@@ -2485,46 +2338,3 @@
5505
5506 addChild(rec);
5507 }
5508-
5509-static GlobalLineEdit *DiSEqCLatitude()
5510-{
5511- GlobalLineEdit *gc = new GlobalLineEdit("latitude");
5512- gc->setLabel("Latitude");
5513- gc->setHelpText(
5514- QObject::tr("The Cartesian latitude for your location.") + " " +
5515- QObject::tr("Use negative numbers for southern "
5516- "and western coordinates."));
5517- return gc;
5518-}
5519-
5520-static GlobalLineEdit *DiSEqCLongitude()
5521-{
5522- GlobalLineEdit *gc = new GlobalLineEdit("longitude");
5523- gc->setLabel("Longitude");
5524- gc->setHelpText(
5525- QObject::tr("The Cartesian longitude for your location.") + " " +
5526- QObject::tr("Use negative numbers for southern "
5527- "and western coordinates."));
5528- return gc;
5529-}
5530-
5531-DVBDiSEqCConfigurationWizard::DVBDiSEqCConfigurationWizard(CaptureCard &parent)
5532-{
5533- VerticalConfigurationGroup* rec = new VerticalConfigurationGroup(false);
5534- rec->setLabel(QObject::tr("DiSEqC Options"));
5535- rec->setUseLabel(false);
5536-
5537- DVBDiSEqCType *diseqctype = new DVBDiSEqCType(parent);
5538- TunerCardInput *defaultinput = new TunerCardInput(parent);
5539-
5540- rec->addChild(diseqctype);
5541- rec->addChild(defaultinput);
5542- rec->addChild(DiSEqCLatitude());
5543- rec->addChild(DiSEqCLongitude());
5544- addChild(rec);
5545-
5546- connect(diseqctype, SIGNAL(valueChanged(const QString&)),
5547- defaultinput, SLOT( diseqcType( const QString&)));
5548-
5549- defaultinput->diseqcType(diseqctype->getValue());
5550-}
5551Index: libs/libmythtv/dvbdiseqc.h
5552===================================================================
5553--- libs/libmythtv/dvbdiseqc.h (revision 10186)
5554+++ libs/libmythtv/dvbdiseqc.h (working copy)
5555@@ -1,120 +0,0 @@
5556-/*
5557- * Copyright (C) Kenneth Aafloy 2003
5558- *
5559- * Copyright notice is in dvbdiseqc.cpp of the MythTV project.
5560- */
5561-
5562-#ifndef DVBDISEQC_H
5563-#define DVBDISEQC_H
5564-
5565-#include "pthread.h"
5566-#include "qsqldatabase.h"
5567-#include "tv_rec.h"
5568-#include "dvbtypes.h"
5569-#include <linux/dvb/frontend.h>
5570-
5571-#define DISEQC_SHORT_WAIT 15*1000
5572-#define DISEQC_LONG_WAIT 100*1000
5573-
5574-class DVBDiSEqC
5575-{
5576-public:
5577- DVBDiSEqC(int cardnum, int fd_frontend);
5578- ~DVBDiSEqC();
5579-
5580- bool Set(DVBTuning& tuning, bool reset, bool& havetuned);
5581- bool DiseqcReset();
5582-
5583-private:
5584- int cardnum;
5585- int fd_frontend;
5586- DVBTuning prev_tuning;
5587- int repeat;
5588-
5589-
5590- bool SendDiSEqCMessage(DVBTuning& tuning, dvb_diseqc_master_cmd &cmd);
5591- bool SendDiSEqCMessage(dvb_diseqc_master_cmd &cmd);
5592-
5593- bool ToneVoltageLnb(DVBTuning& tuning, bool reset, bool& havetuned);
5594- bool ToneSwitch(DVBTuning& tuning, bool reset, bool& havetuned);
5595- bool LegacyDishSwitch(DVBTuning& tuning, bool reset, bool& havetuned);
5596- bool Diseqc1xSwitch(DVBTuning& tuning, bool reset, bool& havetuned,
5597- uint ports);
5598- bool PositionerGoto(DVBTuning& tuning, bool reset, bool& havetuned);
5599- bool PositionerStore(DVBTuning& tuning);
5600- bool PositionerStopMovement();
5601- bool PositionerStoreEastLimit();
5602- bool PositionerStoreWestLimit();
5603- bool PositionerDisableLimits();
5604- bool PositionerDriveEast(int timestep);
5605- bool PositionerDriveWest(int timestep);
5606- bool PositionerGotoAngular(DVBTuning& tuning, bool reset,
5607- bool& havetuned);
5608-
5609- // Still need to be written
5610- bool Positioner_Status();
5611-
5612- enum diseqc_cmd_bytes {
5613- FRAME = 0x0,
5614- ADDRESS = 0x1,
5615- COMMAND = 0x2,
5616- DATA_1 = 0x3,
5617- DATA_2 = 0x4,
5618- DATA_3 = 0x5
5619- };
5620-
5621- enum diseqc_frame_byte {
5622- CMD_FIRST = 0xe0,
5623- CMD_REPEAT = 0xe1,
5624- CMD_REPLY_FIRST = 0xe2,
5625- CMD_REPLY_REPEAT = 0xe3,
5626- REPLY_OK = 0xe4,
5627- REPLY_NOSUPPORT = 0xe5,
5628- REPLY_CRCERR_RPT = 0xe6,
5629- REPLY_CMDERR_RPT = 0xe7
5630- };
5631-
5632- enum diseqc_address {
5633- MASTER_TO_ALL = 0x00,
5634- MASTER_TO_LSS = 0x10,
5635- MASTER_TO_LNB = 0x11,
5636- MASTER_TO_SWITCH = 0x14,
5637- MASTER_TO_POSITIONER = 0x31
5638- };
5639-
5640-
5641- enum diseqc_commands {
5642- RESET = 0x00,
5643- CLR_RESET = 0x01,
5644- STANDBY = 0x02,
5645- POWERON = 0x03,
5646- SET_LO = 0x20,
5647- SET_VR = 0x21,
5648- SET_POS_A = 0x22,
5649- SET_SO_A = 0x23,
5650- SET_HI = 0x24,
5651- SET_HL = 0x25,
5652- SET_POS_B = 0x26,
5653- SET_SO_B = 0x27,
5654- WRITE_N0 = 0x38,
5655- WRITE_N1 = 0x39,
5656- WRITE_N2 = 0x3A,
5657- WRITE_N3 = 0x3B,
5658- READ_LNB_LOF_LO = 0x52,
5659- READ_LNB_LOF_HI = 0x53,
5660-
5661- HALT = 0x60,
5662- LIMITS_OFF = 0x63,
5663- POS_STAT = 0x64,
5664- LIMIT_E = 0x66,
5665- LIMIT_W = 0x67,
5666- DRIVE_E = 0x68,
5667- DRIVE_W = 0x69,
5668- STORE = 0x6A,
5669- GOTO = 0x6B,
5670- GOTO_ANGULAR = 0x6E
5671- };
5672-
5673-};
5674-
5675-#endif // DVBDISEQC_H
5676Index: libs/libmythtv/dvbsignalmonitor.cpp
5677===================================================================
5678--- libs/libmythtv/dvbsignalmonitor.cpp (revision 10186)
5679+++ libs/libmythtv/dvbsignalmonitor.cpp (working copy)
5680@@ -19,6 +19,7 @@
5681
5682 #include "dvbchannel.h"
5683 #include "dvbrecorder.h"
5684+#include "dvbdevtree.h"
5685
5686 #undef DBG_SM
5687 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \
5688@@ -54,8 +55,11 @@
5689 65535, false, 0, 65535, 0),
5690 uncorrectedBlocks(tr("Uncorrected Blocks"), "ucb",
5691 65535, false, 0, 65535, 0),
5692+ rotorPosition (tr("Rotor Progress"), "pos",
5693+ 100, true, 0, 100, 0),
5694 useSectionReader(false),
5695- dtvMonitorRunning(false)
5696+ dtvMonitorRunning(false),
5697+ is_rotor_done(true)
5698 {
5699 // These two values should probably come from the database...
5700 int wait = 3000; // timeout when waiting on signal
5701@@ -151,6 +155,8 @@
5702 list<<bitErrorRate.GetName()<<bitErrorRate.GetStatus();
5703 if (HasFlags(kDVBSigMon_WaitForUB))
5704 list<<uncorrectedBlocks.GetName()<<uncorrectedBlocks.GetStatus();
5705+ if (HasFlags(kDVBSigMon_WaitForPos))
5706+ list<<rotorPosition.GetName()<<rotorPosition.GetStatus();
5707 statusLock.unlock();
5708 return list;
5709 }
5710@@ -332,6 +338,7 @@
5711 FD_SET (dvr_fd, &fd_select_set);
5712 while (dtvMonitorRunning && GetStreamData())
5713 {
5714+ RetuneMonitor();
5715 UpdateFiltersFromStreamData();
5716
5717 // timeout gets reset by select, so we need to create new one
5718@@ -391,6 +398,7 @@
5719
5720 while (dtvMonitorRunning && GetStreamData())
5721 {
5722+ RetuneMonitor();
5723 UpdateFiltersFromStreamData();
5724
5725 bool readSomething = false;
5726@@ -479,6 +487,56 @@
5727 return supports_ts;
5728 }
5729
5730+void DVBSignalMonitor::RetuneMonitor(void)
5731+{
5732+ DVBChannel* dvbchan = dynamic_cast<DVBChannel*>(channel);
5733+ int fd_frontend = dvbchan->GetFd();
5734+
5735+ // Get lock status
5736+ bool is_locked = true;
5737+ fe_status_t status;
5738+ if(ioctl(fd_frontend, FE_READ_STATUS, &status) != -1)
5739+ {
5740+ is_locked = (status & FE_HAS_LOCK);
5741+ signalLock.SetValue(is_locked ? 1 : 0);
5742+ }
5743+
5744+ // Rotor position
5745+ const DVBDevRotor* rotor = dvbchan->GetRotor();
5746+ if(rotor)
5747+ {
5748+ if(rotor->IsPositionKnown())
5749+ {
5750+ double progress = rotor->Progress();
5751+ if(progress >= 1.0 && !is_rotor_done)
5752+ {
5753+ DBG_SM("UpdateValues", "Retuning for rotor completion");
5754+ dvbchan->Retune();
5755+ is_rotor_done = true;
5756+ }
5757+ else if(progress < 1.0)
5758+ {
5759+ if(is_rotor_done)
5760+ DBG_SM("UpdateValues", "Rotor is moving");
5761+ is_rotor_done = false;
5762+ }
5763+
5764+ if (HasFlags(kDVBSigMon_WaitForPos))
5765+ rotorPosition.SetValue((int)(progress * 100));
5766+ }
5767+ }
5768+ else if (HasFlags(kDVBSigMon_WaitForPos))
5769+ rotorPosition.SetValue(100);
5770+
5771+ // Periodically retune if card can't recover
5772+ if(!dvbchan->CanRecover() && !is_locked &&
5773+ dvbchan->ElapsedSinceTune() > RETUNE_TIMEOUT)
5774+ {
5775+ DBG_SM("UpdateValues", "Retuning for lock loss");
5776+ dvbchan->Retune();
5777+ }
5778+}
5779+
5780 void DVBSignalMonitor::RunTableMonitor(void)
5781 {
5782 dtvMonitorRunning = true;
5783@@ -515,6 +573,8 @@
5784 return;
5785 }
5786
5787+ RetuneMonitor();
5788+
5789 bool wasLocked = false, isLocked = false;
5790 // We use uint16_t for sig & snr because this is correct for DVB API 4.0,
5791 // and works better than the correct int16_t for the 3.x API
5792@@ -569,6 +629,7 @@
5793 // Start table monitoring if we are waiting on any table
5794 // and we have a lock.
5795 if (isLocked && GetStreamData() &&
5796+ (!HasFlags(kDVBSigMon_WaitForPos) || rotorPosition.IsGood()) &&
5797 HasAnyFlag(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT |
5798 kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT |
5799 kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT))
5800@@ -605,6 +666,8 @@
5801 EMIT(StatusBitErrorRate, bitErrorRate);
5802 if (HasFlags(kDVBSigMon_WaitForUB))
5803 EMIT(StatusUncorrectedBlocks, uncorrectedBlocks);
5804+ if (HasFlags(kDVBSigMon_WaitForPos))
5805+ EMIT(StatusRotorPosition, rotorPosition);
5806 }
5807
5808 #undef EMIT
5809Index: libs/libmythtv/dvbdiseqc.cpp
5810===================================================================
5811--- libs/libmythtv/dvbdiseqc.cpp (revision 10186)
5812+++ libs/libmythtv/dvbdiseqc.cpp (working copy)
5813@@ -1,785 +0,0 @@
5814-/*
5815- * Class DVBDiSEqC
5816- *
5817- * Copyright (C) Kenneth Aafloy 2003
5818- *
5819- * Description:
5820- *
5821- * Author(s):
5822- * Taylor Jacob (rtjacob at earthlink.net)
5823- * - Finished Implimenting Petri's DiSEqC 1.0 - 1.1 code
5824- * - DiSEqC 1.2 Positioner control
5825- * Petri Nykanen
5826- * - DiSEqC 1.0 - 1.1.
5827- * Kenneth Aafloy (ke-aa at frisurf.no)
5828- * - Initial framework.
5829- *
5830- * This program is free software; you can redistribute it and/or modify
5831- * it under the terms of the GNU General Public License as published by
5832- * the Free Software Foundation; either version 2 of the License, or
5833- * (at your option) any later version.
5834- *
5835- * This program is distributed in the hope that it will be useful,
5836- * but WITHOUT ANY WARRANTY; without even the implied warranty of
5837- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5838- * GNU General Public License for more details.
5839- *
5840- * You should have received a copy of the GNU General Public License
5841- * along with this program; if not, write to the Free Software
5842- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5843- */
5844-
5845-#include <iostream>
5846-#include <cmath>
5847-
5848-#include "pthread.h"
5849-#include "qsqldatabase.h"
5850-
5851-#include "mythcontext.h"
5852-#include "tv_rec.h"
5853-#include "cardutil.h"
5854-
5855-#include "dvbtypes.h"
5856-#include "dvbdiseqc.h"
5857-
5858-#define TO_RADS (M_PI / 180.0)
5859-#define TO_DEC (180.0 / M_PI)
5860-
5861-#define LOC QString("DiSEqC(%1): ").arg(cardnum)
5862-#define LOC_ERR QString("DiSEqC(%1) Error: ").arg(cardnum)
5863-
5864-DVBDiSEqC::DVBDiSEqC(int _cardnum, int _fd_frontend):
5865- cardnum(_cardnum), fd_frontend(_fd_frontend)
5866-{
5867-
5868- // Number of repeats for DiSEqC 1.1 devices
5869- repeat = 1;
5870-}
5871-
5872-DVBDiSEqC::~DVBDiSEqC()
5873-{
5874-}
5875-
5876-bool DVBDiSEqC::Set(DVBTuning& tuning, bool reset, bool& havetuned)
5877-{
5878- switch (tuning.diseqc_type)
5879- {
5880- case DISEQC_MINI_2:
5881- if (!ToneSwitch(tuning, reset, havetuned))
5882- return false;
5883- // fall through
5884- case DISEQC_SINGLE:
5885- if (!ToneVoltageLnb(tuning, reset, havetuned))
5886- return false;
5887- break;
5888- case DISEQC_SWITCH_2_1_0: // 2 Way v1.0
5889- case DISEQC_SWITCH_2_1_1: // 2 Way v1.1
5890- if (!Diseqc1xSwitch(tuning, reset, havetuned, 2))
5891- return false;
5892- break;
5893- case DISEQC_SWITCH_4_1_0: // 4 Way v1.0
5894- case DISEQC_SWITCH_4_1_1: // 4 Way v1.1
5895- if (!Diseqc1xSwitch(tuning, reset, havetuned, 4))
5896- return false;
5897- break;
5898- case DISEQC_POSITIONER_1_2: // 1.2 Positioner (HH Motor)
5899- if (!PositionerGoto(tuning,reset,havetuned))
5900- return false;
5901- break;
5902- case DISEQC_POSITIONER_X: // 1.3 Positioner (HH Motor with USALS)
5903- if (!PositionerGotoAngular(tuning,reset,havetuned))
5904- return false;
5905- break;
5906- case DISEQC_POSITIONER_1_2_SWITCH_2: // 10 Way v1.1 or v2.1
5907- if (!Diseqc1xSwitch(tuning, reset, havetuned, 10))
5908- return false;
5909- break;
5910- case DISEQC_SW21: // Dish Network legacy switch SW21
5911- case DISEQC_SW64: // Dish Network legacy switch SW64
5912- if (!LegacyDishSwitch(tuning, reset, havetuned))
5913- return false;
5914- break;
5915-
5916- default:
5917- VERBOSE(VB_IMPORTANT, LOC_ERR + "Unsupported DiSEqC type("
5918- <<tuning.diseqc_type<<")");
5919- }
5920-
5921- return true;
5922-}
5923-
5924-bool DVBDiSEqC::LegacyDishSwitch(DVBTuning &tuning, bool reset,
5925- bool &havetuned)
5926-{
5927- VERBOSE(VB_CHANNEL, LOC + "Legacy Dish Switch: " +
5928- QString("Port %1").arg(tuning.diseqc_port));
5929-
5930- if (reset ||
5931- (prev_tuning.diseqc_port != tuning.diseqc_port ||
5932- prev_tuning.tone != tuning.tone ||
5933- prev_tuning.voltage != tuning.voltage))
5934- {
5935- uint8_t cmd = 0x00;
5936-
5937- if (DISEQC_SW21 == tuning.diseqc_type)
5938- cmd = (tuning.diseqc_port) ? 0x66 : 0x34;
5939- else if (DISEQC_SW64 == tuning.diseqc_type)
5940- {
5941- if (tuning.diseqc_port == 0)
5942- cmd = (tuning.voltage == SEC_VOLTAGE_13) ? 0x39 : 0x1A;
5943- else if (tuning.diseqc_port == 1)
5944- cmd = (tuning.voltage == SEC_VOLTAGE_13) ? 0x4B : 0x5C;
5945- else
5946- cmd = (tuning.voltage == SEC_VOLTAGE_13) ? 0x0D : 0x2E;
5947- }
5948-
5949- if (tuning.voltage == SEC_VOLTAGE_18)
5950- cmd |= 0x80;
5951-
5952-#ifdef FE_DISHNETWORK_SEND_LEGACY_CMD
5953- if (ioctl(fd_frontend, FE_DISHNETWORK_SEND_LEGACY_CMD, cmd) <0)
5954- {
5955- VERBOSE(VB_IMPORTANT, LOC_ERR + "Legacy Dish Switch: "
5956- "Sending init command failed." + ENO);
5957- return false;
5958- }
5959-#else
5960- VERBOSE(VB_IMPORTANT, LOC_ERR + "Legacy Dish Switch: " +
5961- "Linux kernel does not support this switch.");
5962-#endif
5963-
5964- usleep(DISEQC_SHORT_WAIT);
5965-
5966- prev_tuning.diseqc_port = tuning.diseqc_port;
5967- prev_tuning.tone = tuning.tone;
5968- prev_tuning.voltage = tuning.voltage;
5969- havetuned = true;
5970- }
5971- return true;
5972-}
5973-
5974-/*****************************************************************************
5975- Backward Compatible Methods
5976- ****************************************************************************/
5977-
5978-bool DVBDiSEqC::ToneVoltageLnb(DVBTuning& tuning, bool reset, bool& havetuned)
5979-{
5980- VERBOSE(VB_CHANNEL, LOC + QString("Setting LNB: %1 %2")
5981- .arg(tuning.tone==SEC_TONE_ON?"Tone ON":"Tone OFF")
5982- .arg(tuning.voltage==SEC_VOLTAGE_13?"13V":"18V"));
5983-
5984- if (prev_tuning.tone != tuning.tone || reset)
5985- {
5986- if (ioctl(fd_frontend, FE_SET_TONE, tuning.tone) < 0)
5987- {
5988- VERBOSE(VB_IMPORTANT, LOC_ERR +
5989- "Setting Tone mode failed." + ENO);
5990- return false;
5991- }
5992-
5993- prev_tuning.tone = tuning.tone;
5994- }
5995-
5996- usleep(DISEQC_SHORT_WAIT);
5997-
5998- if (prev_tuning.voltage != tuning.voltage || reset)
5999- {
6000- if (ioctl(fd_frontend, FE_SET_VOLTAGE, tuning.voltage) < 0)
6001- {
6002- VERBOSE(VB_IMPORTANT, LOC_ERR +
6003- "Setting Polarization failed." + ENO);
6004- return false;
6005- }
6006-
6007- prev_tuning.voltage = tuning.voltage;
6008- }
6009-
6010- havetuned |= ((prev_tuning.voltage == tuning.voltage) &&
6011- (prev_tuning.tone == tuning.tone));
6012-
6013- return true;
6014-}
6015-
6016-bool DVBDiSEqC::ToneSwitch(DVBTuning& tuning, bool reset, bool& havetuned)
6017-{
6018- VERBOSE(VB_CHANNEL, LOC + QString("Tone Switch - Port %1/2")
6019- .arg(tuning.diseqc_port));
6020-
6021- if (prev_tuning.diseqc_port != tuning.diseqc_port || reset)
6022- {
6023- if (tuning.diseqc_port > 2)
6024- VERBOSE(VB_IMPORTANT, LOC_ERR +
6025- "Tone Switches only support two ports.");
6026-
6027- if (ioctl(fd_frontend, FE_DISEQC_SEND_BURST,
6028- (tuning.diseqc_port == 1 ? SEC_MINI_A : SEC_MINI_B )) < 0)
6029- {
6030- VERBOSE(VB_IMPORTANT, LOC_ERR +
6031- "Setting Tone Switch failed." + ENO);
6032- return false;
6033- }
6034-
6035- prev_tuning.diseqc_port = tuning.diseqc_port;
6036- }
6037-
6038- havetuned |= (prev_tuning.diseqc_port == tuning.diseqc_port);
6039-
6040- return true;
6041-}
6042-
6043-/*****************************************************************************
6044- Diseqc 1.x Compatible Methods
6045- ****************************************************************************/
6046-
6047-bool DVBDiSEqC::SendDiSEqCMessage(DVBTuning& tuning, dvb_diseqc_master_cmd &cmd)
6048-{
6049- // Turn off tone burst
6050- if (ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF) == -1)
6051- {
6052- VERBOSE(VB_IMPORTANT, LOC_ERR + "FE_SET_TONE failed" + ENO);
6053- return false;
6054- }
6055-
6056-/*
6057- Old version of the code set the voltage to 13V everytime.
6058- After looking at the EutelSat specs I saw no reason that
6059- this was done. I have tested this with my DiSEqC switch
6060- and all is fine.
6061-*/
6062-
6063- if (ioctl(fd_frontend, FE_SET_VOLTAGE, tuning.voltage) == -1)
6064- {
6065- VERBOSE(VB_IMPORTANT, LOC_ERR + "FE_SET_VOLTAGE failed" + ENO);
6066- return false;
6067- }
6068-
6069- usleep(DISEQC_SHORT_WAIT);
6070-
6071- VERBOSE(VB_CHANNEL, LOC + QString("Sending 1.0 Command: %1 %2 %3 %4")
6072- .arg(cmd.msg[0], 2, 16)
6073- .arg(cmd.msg[1], 2, 16)
6074- .arg(cmd.msg[2], 2, 16)
6075- .arg(cmd.msg[3], 2, 16));
6076-
6077- if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1)
6078- {
6079- VERBOSE(VB_IMPORTANT, LOC_ERR +
6080- "FE_DISEQC_SEND_MASTER_CMD failed" + ENO);
6081- return false;
6082- }
6083-
6084- usleep(DISEQC_SHORT_WAIT);
6085-
6086- // Check to see if its a 1.1 or 1.2 device.
6087- // If so repeat the message repeats times.
6088- if ((tuning.diseqc_type == DISEQC_SWITCH_2_1_1) ||
6089- (tuning.diseqc_type == DISEQC_SWITCH_4_1_1) ||
6090- (tuning.diseqc_type == DISEQC_POSITIONER_1_2) ||
6091- (tuning.diseqc_type == DISEQC_POSITIONER_X))
6092- {
6093-
6094- int repeats = repeat;
6095- while (repeats--)
6096- {
6097-
6098- if (tuning.diseqc_type == DISEQC_POSITIONER_X)
6099- {
6100- VERBOSE(VB_CHANNEL, LOC +
6101- QString("Sending 1.3 Repeat Command: %1 %2 %3 %4 %5")
6102- .arg(cmd.msg[0],2,16)
6103- .arg(cmd.msg[1],2,16)
6104- .arg(cmd.msg[2],2,16)
6105- .arg(cmd.msg[3],2,16)
6106- .arg(cmd.msg[4],2,16));
6107- }
6108- else
6109- {
6110- VERBOSE(VB_CHANNEL, LOC +
6111- QString("Sending 1.1/1.2 Repeat Command: %1 %2 %3 %4")
6112- .arg(cmd.msg[0],2,16)
6113- .arg(cmd.msg[1],2,16)
6114- .arg(cmd.msg[2],2,16)
6115- .arg(cmd.msg[3],2,16));
6116- }
6117-
6118- cmd.msg[0] = CMD_REPEAT;
6119- if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1)
6120- {
6121- VERBOSE(VB_IMPORTANT, LOC_ERR +
6122- "FE_DISEQC_SEND_MASTER_CMD failed" + ENO);
6123- return false;
6124- }
6125- usleep(DISEQC_SHORT_WAIT);
6126-
6127- cmd.msg[0] = CMD_FIRST;
6128- if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1)
6129- {
6130- VERBOSE(VB_IMPORTANT, LOC_ERR +
6131- "FE_DISEQC_SEND_MASTER_CMD failed" + ENO);
6132- return false;
6133- }
6134- usleep(DISEQC_SHORT_WAIT);
6135- }
6136- }
6137-
6138- if (ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A ) == -1)
6139- {
6140- VERBOSE(VB_IMPORTANT, LOC_ERR +
6141- "FE_DISEQC_SEND_BURST failed" + ENO);
6142- return false;
6143- }
6144-
6145- usleep(DISEQC_SHORT_WAIT);
6146-
6147- if (ioctl(fd_frontend, FE_SET_TONE, tuning.tone) == -1)
6148- {
6149- VERBOSE(VB_IMPORTANT, LOC_ERR + "FE_SET_TONE failed" + ENO);
6150- return false;
6151- }
6152-
6153- return true;
6154-}
6155-
6156-
6157-bool DVBDiSEqC::SendDiSEqCMessage(dvb_diseqc_master_cmd &cmd)
6158-{
6159- // Turn off tone burst
6160- if (ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF) == -1)
6161- {
6162- VERBOSE(VB_IMPORTANT, LOC_ERR + "FE_SET_TONE failed" + ENO);
6163- return false;
6164- }
6165-
6166- usleep(DISEQC_SHORT_WAIT);
6167-
6168- VERBOSE(VB_CHANNEL, LOC + QString("Sending 1.0 Command: %1 %2 %3 %4")
6169- .arg(cmd.msg[0], 2, 16)
6170- .arg(cmd.msg[1], 2, 16)
6171- .arg(cmd.msg[2], 2, 16)
6172- .arg(cmd.msg[3], 2, 16));
6173-
6174- if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1)
6175- {
6176- VERBOSE(VB_IMPORTANT, LOC_ERR +
6177- "FE_DISEQC_SEND_MASTER_CMD failed" + ENO);
6178- return false;
6179- }
6180-
6181- usleep(DISEQC_SHORT_WAIT);
6182-
6183- int repeats = repeat;
6184- while (repeats--)
6185- {
6186- VERBOSE(VB_CHANNEL, LOC +
6187- QString("Sending 1.1/1.2/1.3 Repeat Command: %1 %2 %3 %4")
6188- .arg(cmd.msg[0], 2, 16)
6189- .arg(cmd.msg[1], 2, 16)
6190- .arg(cmd.msg[2], 2, 16)
6191- .arg(cmd.msg[3], 2, 16));
6192-
6193- cmd.msg[0] = CMD_REPEAT;
6194- if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1)
6195- {
6196- VERBOSE(VB_IMPORTANT, LOC_ERR +
6197- "FE_DISEQC_SEND_MASTER_CMD failed" + ENO);
6198- return false;
6199- }
6200- usleep(DISEQC_SHORT_WAIT);
6201-
6202- cmd.msg[0] = CMD_FIRST;
6203- if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1)
6204- {
6205- VERBOSE(VB_IMPORTANT, LOC_ERR +
6206- "FE_DISEQC_SEND_MASTER_CMD failed" + ENO);
6207- return false;
6208- }
6209- usleep(DISEQC_SHORT_WAIT);
6210- }
6211-
6212- if (ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A ) == -1)
6213- {
6214- VERBOSE(VB_IMPORTANT, LOC_ERR + "FE_DISEQC_SEND_BURST failed" + ENO);
6215- return false;
6216- }
6217-
6218- return true;
6219-}
6220-
6221-bool DVBDiSEqC::Diseqc1xSwitch(DVBTuning& tuning, bool reset,
6222- bool& havetuned, uint ports)
6223-{
6224- if (reset)
6225- {
6226- if (!DiseqcReset())
6227- {
6228- VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");
6229- return false;
6230- }
6231- }
6232-
6233- VERBOSE(VB_CHANNEL, LOC +
6234- QString("1.1 Switch (%1 ports) - Port %2 - %3 %4")
6235- .arg(ports)
6236- .arg(tuning.diseqc_port)
6237- .arg(tuning.tone==SEC_TONE_ON?"Tone ON":"Tone OFF")
6238- .arg(tuning.voltage==SEC_VOLTAGE_13?"13V":"18V"));
6239-
6240- if ((prev_tuning.diseqc_port != tuning.diseqc_port ||
6241- prev_tuning.tone != tuning.tone ||
6242- prev_tuning.voltage != tuning.voltage ) || reset)
6243- {
6244- dvb_diseqc_master_cmd cmd =
6245- {{CMD_FIRST, MASTER_TO_LSS, WRITE_N1, 0xf0, 0x00, 0x00}, 4};
6246-
6247- if (tuning.diseqc_port >= ports )
6248- {
6249- VERBOSE(VB_IMPORTANT, LOC_ERR + "Unsupported switch");
6250- return false;
6251- }
6252-
6253- switch (ports)
6254- {
6255- case 10:
6256- cmd.msg[COMMAND] = WRITE_N1;
6257- cmd.msg[DATA_1] = 0xF0 | (tuning.diseqc_port & 0x0F);
6258- break;
6259- case 4:
6260- case 2:
6261- cmd.msg[COMMAND] = WRITE_N0;
6262- cmd.msg[DATA_1] =
6263- 0xF0 |
6264- (((tuning.diseqc_port) * 4) & 0x0F) |
6265- ((tuning.voltage == SEC_VOLTAGE_18) ? 2 : 0) |
6266- ((tuning.tone == SEC_TONE_ON) ? 1 : 0);
6267- break;
6268- default:
6269- VERBOSE(VB_IMPORTANT, LOC_ERR +
6270- "Unsupported number of ports for DiSEqC 1.1 Switch");
6271- }
6272-
6273- if (!SendDiSEqCMessage(tuning,cmd))
6274- {
6275- VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");
6276- return false;
6277- }
6278-
6279- prev_tuning.diseqc_port = tuning.diseqc_port;
6280- prev_tuning.tone = tuning.tone;
6281- prev_tuning.voltage = tuning.voltage;
6282- havetuned = true;
6283-
6284- }
6285-
6286- havetuned |=
6287- (prev_tuning.diseqc_port == tuning.diseqc_port) &&
6288- (prev_tuning.voltage == tuning.voltage) &&
6289- (prev_tuning.tone == tuning.tone);
6290-
6291- return true;
6292-}
6293-
6294-bool DVBDiSEqC::DiseqcReset()
6295-{
6296- struct dvb_diseqc_master_cmd reset_cmd =
6297- {{CMD_FIRST, MASTER_TO_LSS, RESET, 0x00, 0x00}, 3};
6298-
6299- struct dvb_diseqc_master_cmd init_cmd =
6300- {{CMD_FIRST, MASTER_TO_LSS, POWERON, 0x00, 0x00}, 3};
6301-
6302- if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &init_cmd) <0)
6303- {
6304- VERBOSE(VB_IMPORTANT, LOC_ERR +
6305- "Setup: Sending init command failed." + ENO);
6306- return false;
6307- }
6308- usleep(DISEQC_LONG_WAIT);
6309-
6310- if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &reset_cmd) <0)
6311- {
6312- VERBOSE(VB_IMPORTANT, LOC_ERR +
6313- "Setup: Sending reset command failed." + ENO);
6314- return false;
6315- }
6316- usleep(DISEQC_LONG_WAIT);
6317-
6318- if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &init_cmd) <0)
6319- {
6320- VERBOSE(VB_IMPORTANT, LOC_ERR +
6321- "Setup: Sending init command failed." + ENO);
6322- return false;
6323- }
6324- usleep(DISEQC_LONG_WAIT);
6325-
6326- return true;
6327-}
6328-
6329-/*****************************************************************************
6330- Positioner Control
6331- *****************************************************************************/
6332-
6333-bool DVBDiSEqC::PositionerDriveEast(int timestep)
6334-{
6335- if (!DiseqcReset())
6336- {
6337- VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");
6338- return false;
6339- }
6340-
6341- dvb_diseqc_master_cmd cmd =
6342- {{CMD_FIRST, MASTER_TO_POSITIONER, DRIVE_E, timestep ,0x00,0x00}, 4};
6343-
6344- if (!SendDiSEqCMessage(cmd))
6345- {
6346- VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");
6347- return false;
6348- }
6349-
6350- return true;
6351-}
6352-
6353-bool DVBDiSEqC::PositionerDriveWest(int timestep)
6354-{
6355- if (!DiseqcReset())
6356- {
6357- VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");
6358- return false;
6359- }
6360-
6361- dvb_diseqc_master_cmd cmd =
6362- {{CMD_FIRST, MASTER_TO_POSITIONER, DRIVE_W, timestep ,0x00,0x00}, 4};
6363-
6364- if (!SendDiSEqCMessage(cmd))
6365- {
6366- VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");
6367- return false;
6368- }
6369-
6370- return true;
6371-}
6372-
6373-bool DVBDiSEqC::PositionerGoto(DVBTuning& tuning, bool reset, bool& havetuned)
6374-{
6375- // A reset seems to be required for my positioner to work consistently
6376- VERBOSE(VB_CHANNEL, LOC + QString("1.2 Motor - Goto Stored Position %1")
6377- .arg(tuning.diseqc_port));
6378-
6379- if ((prev_tuning.diseqc_port != tuning.diseqc_port ||
6380- prev_tuning.tone != tuning.tone ||
6381- prev_tuning.voltage != tuning.voltage) || reset)
6382- {
6383- if (!DiseqcReset())
6384- {
6385- VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");
6386- return false;
6387- }
6388-
6389- dvb_diseqc_master_cmd cmd =
6390- {{CMD_FIRST, MASTER_TO_POSITIONER, GOTO, tuning.diseqc_port,
6391- 0x00, 0x00}, 4};
6392-
6393- if (!SendDiSEqCMessage(tuning,cmd))
6394- {
6395- VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");
6396- return false;
6397- }
6398-
6399- prev_tuning.diseqc_port = tuning.diseqc_port;
6400- prev_tuning.tone = tuning.tone;
6401- prev_tuning.voltage = tuning.voltage;
6402- }
6403-
6404- havetuned |=
6405- (prev_tuning.diseqc_port == tuning.diseqc_port) &&
6406- (prev_tuning.voltage == tuning.voltage) &&
6407- (prev_tuning.tone == tuning.tone);
6408-
6409- return true;
6410-}
6411-
6412-bool DVBDiSEqC::PositionerStore(DVBTuning& tuning)
6413-{
6414- if (!DiseqcReset())
6415- {
6416- VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");
6417- return false;
6418- }
6419-
6420- VERBOSE(VB_CHANNEL, LOC + QString("1.2 Motor - Store Stored Position %1")
6421- .arg(tuning.diseqc_port));
6422-
6423- dvb_diseqc_master_cmd cmd =
6424- {{CMD_FIRST, MASTER_TO_POSITIONER, STORE, tuning.diseqc_port , 0x00,
6425- 0x00}, 4};
6426-
6427- if (!SendDiSEqCMessage(cmd))
6428- {
6429- VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");
6430- return false;
6431- }
6432-
6433- return true;
6434-}
6435-
6436-bool DVBDiSEqC::PositionerStoreEastLimit()
6437-{
6438- if (!DiseqcReset())
6439- {
6440- VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");
6441- return false;
6442- }
6443-
6444- dvb_diseqc_master_cmd cmd =
6445- {{CMD_FIRST, MASTER_TO_POSITIONER, LIMIT_E, 0x00,0x00,0x00}, 3};
6446-
6447- if (!SendDiSEqCMessage(cmd))
6448- {
6449- VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");
6450- return false;
6451- }
6452-
6453- return true;
6454-}
6455-
6456-bool DVBDiSEqC::PositionerStoreWestLimit()
6457-{
6458- if (!DiseqcReset())
6459- {
6460- VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");
6461- return false;
6462- }
6463-
6464- dvb_diseqc_master_cmd cmd =
6465- {{CMD_FIRST, MASTER_TO_POSITIONER, LIMIT_W, 0x00,0x00,0x00}, 3};
6466-
6467- if (!SendDiSEqCMessage(cmd))
6468- {
6469- VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");
6470- return false;
6471- }
6472-
6473- return true;
6474-}
6475-
6476-bool DVBDiSEqC::PositionerStopMovement()
6477-{
6478- if (!DiseqcReset())
6479- {
6480- VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");
6481- return false;
6482- }
6483-
6484- dvb_diseqc_master_cmd cmd =
6485- {{CMD_FIRST, MASTER_TO_POSITIONER, HALT, 0x00,0x00,0x00}, 3};
6486-
6487- if (!SendDiSEqCMessage(cmd))
6488- {
6489- VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");
6490- return false;
6491- }
6492- return true;
6493-
6494-}
6495-
6496-bool DVBDiSEqC::Positioner_Status()
6497-{
6498- // Not sure if this function is possible without being DiSEqC >= v2
6499- // Someone with a DVB card that supports v2 cards will need to help me out
6500- // here
6501- return false;
6502-}
6503-
6504-bool DVBDiSEqC::PositionerDisableLimits()
6505-{
6506- if (!DiseqcReset())
6507- {
6508- VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");
6509- return false;
6510- }
6511-
6512- dvb_diseqc_master_cmd cmd =
6513- {{CMD_FIRST, MASTER_TO_POSITIONER, LIMITS_OFF, 0x00,0x00,0x00}, 3};
6514-
6515- if (!SendDiSEqCMessage(cmd))
6516- {
6517- VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");
6518- return false;
6519- }
6520-
6521- return true;
6522-}
6523-
6524-/*****************************************************************************
6525- Diseqc v1.3 (Goto X)
6526- ****************************************************************************/
6527-
6528-bool DVBDiSEqC::PositionerGotoAngular(DVBTuning& tuning, bool reset,
6529- bool& havetuned)
6530-{
6531- // TODO: Send information here to FE saying motor is moving and
6532- // to expect a longer than average tuning delay
6533- if (prev_tuning.diseqc_pos != tuning.diseqc_pos)
6534- VERBOSE(VB_CHANNEL, LOC + "DiSEqC Motor Moving");
6535-
6536- if (!DiseqcReset())
6537- {
6538- VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");
6539- return false;
6540- }
6541-
6542- VERBOSE(VB_CHANNEL, LOC + QString("1.3 Motor - Goto Angular Position %1")
6543- .arg(tuning.diseqc_pos));
6544-
6545- // Equation lifted from VDR rotor plugin by
6546- // Thomas Bergwinkl <Thomas.Bergwinkl@t-online.de>
6547-
6548- // Earth Station Latitude and Longitude in radians
6549- double P = gContext->GetSetting("Latitude", "").toFloat() * TO_RADS;
6550- double Ue = gContext->GetSetting("Longitude", "").toFloat() * TO_RADS;
6551-
6552- // Satellite Longitude in radians
6553- double Us = tuning.diseqc_pos * TO_RADS;
6554-
6555- double az = M_PI + atan( tan(Us - Ue) / sin(P) );
6556- double x = acos( cos(Us - Ue) * cos(P) );
6557- double el = atan( (cos(x) - 0.1513) / sin(x) );
6558- double tmp_a = -cos(el) * sin(az);
6559- double tmp_b = (sin(el) * cos(P)) - (cos(el) * sin(P) * cos(az));
6560- double azimuth = atan(tmp_a / tmp_b) * TO_DEC;
6561-
6562- // Bytes sent to motor
6563- // cmd1 high nibble is 1110b/0xE0 for east or 1101b/0xD0 for west
6564- // cmd1 low nibble is angle / 16
6565- // cmd2 high nibble is angle % 16
6566- // cmd2 low nibble is (angle * 16) % 16
6567- uint az16 = (unsigned int) (abs(azimuth) * 16.0);
6568- uint cmd1 = ((azimuth > 0.0) ? 0xE0 : 0xD0) | ((az16 >> 8) & 0x0f);
6569- uint cmd2 = (az16 & 0xff);
6570-
6571- dvb_diseqc_master_cmd cmd =
6572- {{CMD_FIRST, MASTER_TO_POSITIONER, GOTO_ANGULAR, cmd1, cmd2, 0x00}, 5};
6573-
6574- if ((prev_tuning.diseqc_port != tuning.diseqc_port ||
6575- prev_tuning.tone != tuning.tone ||
6576- prev_tuning.diseqc_pos != tuning.diseqc_pos ||
6577- prev_tuning.voltage != tuning.voltage ) || reset)
6578- {
6579- if (!SendDiSEqCMessage(tuning, cmd))
6580- {
6581- VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");
6582- return false;
6583- }
6584-
6585- prev_tuning.diseqc_port = tuning.diseqc_port;
6586- prev_tuning.diseqc_pos = tuning.diseqc_pos;
6587- prev_tuning.tone = tuning.tone;
6588- prev_tuning.voltage = tuning.voltage;
6589- }
6590-
6591- havetuned |=
6592- (prev_tuning.diseqc_port == tuning.diseqc_port) &&
6593- (prev_tuning.diseqc_pos == tuning.diseqc_pos) &&
6594- (prev_tuning.voltage == tuning.voltage) &&
6595- (prev_tuning.tone == tuning.tone);
6596-
6597- return true;
6598-}
6599Index: libs/libmyth/settings.cpp
6600===================================================================
6601--- libs/libmyth/settings.cpp (revision 10186)
6602+++ libs/libmyth/settings.cpp (working copy)
6603@@ -1161,8 +1161,8 @@
6604 this, SIGNAL(deleteButtonPressed(int)));
6605 connect(this, SIGNAL(valueChanged(const QString&)),
6606 widget, SLOT(setCurrentItem(const QString&)));
6607- connect(widget, SIGNAL(highlighted(const QString&)),
6608- this, SLOT(setValueByLabel(const QString&)));
6609+ connect(widget, SIGNAL(highlighted(int)),
6610+ this, SLOT(setValueByIndex(int)));
6611
6612 if (cg)
6613 connect(widget, SIGNAL(changeHelpText(QString)), cg,
6614@@ -1181,13 +1181,8 @@
6615 widget->setSelectionMode(selectionMode);
6616 }
6617
6618-void ListBoxSetting::setValueByLabel(const QString& label) {
6619- for(unsigned i = 0 ; i < labels.size() ; ++i)
6620- if (labels[i] == label) {
6621- setValue(values[i]);
6622- return;
6623- }
6624- cerr << "BUG: ListBoxSetting::setValueByLabel called for unknown label " << label << endl;
6625+void ListBoxSetting::setValueByIndex(int index) {
6626+ setValue(values[index]);
6627 }
6628
6629 void ImageSelectSetting::addImageSelection(const QString& label,
6630Index: libs/libmyth/settings.h
6631===================================================================
6632--- libs/libmyth/settings.h (revision 10186)
6633+++ libs/libmyth/settings.h (working copy)
6634@@ -468,7 +468,7 @@
6635 void deleteButtonPressed(int);
6636
6637 protected slots:
6638- void setValueByLabel(const QString& label);
6639+ void setValueByIndex(int index);
6640 void addSelection(const QString& label,
6641 QString value=QString::null,
6642 bool select=false) {