MythTV  0.27pre
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
diseqcsettings.cpp
Go to the documentation of this file.
1 /*
2  * \file dvbdevtree_cfg.cpp
3  * \brief DVB-S Device Tree Configuration Classes.
4  * \author Copyright (C) 2006, Yeasah Pell
5  */
6 
7 // Std C headers
8 #include <cmath>
9 
10 // MythTV headers
11 #include "mythdbcon.h"
12 #include "mythlogging.h"
13 #include "diseqcsettings.h"
14 
15 /* Lat/Long items relocated from videosource.cpp */
16 
18 {
19  GlobalLineEdit *gc = new GlobalLineEdit("latitude");
20  gc->setLabel("Latitude");
21  gc->setHelpText(
22  DeviceTree::tr("The Cartesian latitude for your location. "
23  "Use negative numbers for southern "
24  "and western coordinates."));
25  return gc;
26 }
27 
29 {
30  GlobalLineEdit *gc = new GlobalLineEdit("longitude");
31  gc->setLabel("Longitude");
32  gc->setHelpText(
33  DeviceTree::tr("The Cartesian longitude for your location. "
34  "Use negative numbers for southern "
35  "and western coordinates."));
36  return gc;
37 }
38 
40 
42 {
43  public:
45  ComboBoxSetting(this), m_device(device)
46  {
47  setLabel(DeviceTree::tr("Device Type"));
48  addSelection(DeviceTree::tr("Switch"),
49  QString::number((uint) DiSEqCDevDevice::kTypeSwitch));
50  addSelection(DeviceTree::tr("Rotor"),
51  QString::number((uint) DiSEqCDevDevice::kTypeRotor));
52  addSelection(DeviceTree::tr("LNB"),
53  QString::number((uint) DiSEqCDevDevice::kTypeLNB));
54  }
55 
56  virtual void Load(void)
57  {
58  QString tmp = QString::number((uint) m_device.GetDeviceType());
59  setValue(getValueIndex(tmp));
60  }
61 
62  virtual void Save(void)
63  {
65  (DiSEqCDevDevice::dvbdev_t) getValue().toUInt());
66  }
67 
68  virtual void Save(QString /*destination*/) { }
69 
70  private:
72 };
73 
75 
77 {
78  public:
80  LineEditSetting(this), m_device(device)
81  {
82  setLabel(DeviceTree::tr("Description"));
83  QString help = DeviceTree::tr(
84  "Optional descriptive name for this device, to "
85  "make it easier to configure settings later.");
86  setHelpText(help);
87  }
88 
89  virtual void Load(void)
90  {
92  }
93 
94  virtual void Save(void)
95  {
97  }
98 
99  virtual void Save(QString /*destination*/) { }
100 
101  private:
103 };
104 
105 
107 
109 {
110  public:
112  SpinBoxSetting(this, 0, 5, 1), m_device(device)
113  {
114  setLabel(DeviceTree::tr("Repeat Count"));
115  QString help = DeviceTree::tr(
116  "Number of times to repeat DiSEqC commands sent to this device. "
117  "Larger values may help with less reliable devices.");
118  setHelpText(help);
119  }
120 
121  virtual void Load(void)
122  {
124  }
125 
126  virtual void Save(void)
127  {
128  m_device.SetRepeatCount(getValue().toUInt());
129  }
130 
131  virtual void Save(QString /*destination*/) { }
132 
133  private:
135 };
136 
138 
140 {
141  public:
143  ComboBoxSetting(this), m_switch(switch_dev)
144  {
145  setLabel(DeviceTree::tr("Switch Type"));
146  setHelpText(DeviceTree::tr("Select the type of switch from the list."));
147 
148  addSelection(DeviceTree::tr("Tone"),
149  QString::number((uint) DiSEqCDevSwitch::kTypeTone));
150  addSelection(DeviceTree::tr("Voltage"),
151  QString::number((uint) DiSEqCDevSwitch::kTypeVoltage));
152  addSelection(DeviceTree::tr("Mini DiSEqC"),
153  QString::number((uint) DiSEqCDevSwitch::kTypeMiniDiSEqC));
154  addSelection(DeviceTree::tr("DiSEqC"),
155  QString::number((uint)
157  addSelection(DeviceTree::tr("DiSEqC (Uncommitted)"),
158  QString::number((uint)
160  addSelection(DeviceTree::tr("Legacy SW21"),
161  QString::number((uint) DiSEqCDevSwitch::kTypeLegacySW21));
162  addSelection(DeviceTree::tr("Legacy SW42"),
163  QString::number((uint) DiSEqCDevSwitch::kTypeLegacySW42));
164  addSelection(DeviceTree::tr("Legacy SW64"),
165  QString::number((uint) DiSEqCDevSwitch::kTypeLegacySW64));
166  }
167 
168  virtual void Load(void)
169  {
170  setValue(getValueIndex(QString::number((uint) m_switch.GetType())));
171  }
172 
173  virtual void Save(void)
174  {
176  getValue().toUInt());
177  }
178 
179  virtual void Save(QString /*destination*/) { }
180 
181  private:
183 };
184 
186 
188 {
189  public:
191  LineEditSetting(this), m_switch(switch_dev)
192  {
193  setLabel(DeviceTree::tr("Address of switch"));
194  setHelpText(DeviceTree::tr("The DiSEqC address of the switch."));
195  }
196 
197  virtual void Load(void)
198  {
199  setValue(QString("0x%1").arg(m_switch.GetAddress(), 0, 16));
200  }
201 
202  virtual void Save(void)
203  {
204  m_switch.SetAddress(getValue().toUInt(0, 16));
205  }
206  virtual void Save(QString /*destination*/) { Save(); }
207 
208  private:
210 };
211 
213 
215 {
216  public:
218  LineEditSetting(this), m_switch(switch_dev)
219  {
220  setLabel(DeviceTree::tr("Number of ports"));
221  setHelpText(DeviceTree::tr("The number of ports this switch has."));
222  }
223 
224  virtual void Load(void)
225  {
226  setValue(QString::number(m_switch.GetNumPorts()));
227  }
228 
229  virtual void Save(void)
230  {
231  m_switch.SetNumPorts(getValue().toUInt());
232  }
233 
234  virtual void Save(QString /*destination*/) { }
235 
236  private:
238 };
239 
241 
243 {
244  ConfigurationGroup *group =
245  new VerticalConfigurationGroup(false, false);
246  group->setLabel(DeviceTree::tr("Switch Configuration"));
247 
248  group->addChild(new DeviceDescrSetting(switch_dev));
249  group->addChild(new DeviceRepeatSetting(switch_dev));
250  m_type = new SwitchTypeSetting(switch_dev);
251  group->addChild(m_type);
252  m_address = new SwitchAddressSetting(switch_dev);
253  group->addChild(m_address);
254  m_ports = new SwitchPortsSetting(switch_dev);
255  group->addChild(m_ports);
256 
257  connect(m_type, SIGNAL(valueChanged(const QString&)),
258  this, SLOT( update(void)));
259 
260  addChild(group);
261 }
262 
264 {
265  switch ((DiSEqCDevSwitch::dvbdev_switch_t) m_type->getValue().toUInt())
266  {
272  m_address->setValue(QString("0x10"));
273  m_address->setEnabled(false);
274  m_ports->setValue("2");
275  m_ports->setEnabled(false);
276  break;
278  m_address->setValue(QString("0x10"));
279  m_address->setEnabled(false);
280  m_ports->setValue("3");
281  m_ports->setEnabled(false);
282  break;
285  m_address->setEnabled(true);
286  m_ports->setEnabled(true);
287  break;
288  }
289 }
290 
292 
294 {
295  public:
297  ComboBoxSetting(this), m_rotor(rotor)
298  {
299  setLabel(DeviceTree::tr("Rotor Type"));
300  setHelpText(DeviceTree::tr("Select the type of rotor from the list."));
301  addSelection(DeviceTree::tr("DiSEqC 1.2"),
302  QString::number((uint) DiSEqCDevRotor::kTypeDiSEqC_1_2));
303  addSelection(DeviceTree::tr("DiSEqC 1.3 (GotoX/USALS)"),
304  QString::number((uint) DiSEqCDevRotor::kTypeDiSEqC_1_3));
305  }
306 
307  virtual void Load(void)
308  {
309  setValue(getValueIndex(QString::number((uint)m_rotor.GetType())));
310  }
311 
312  virtual void Save(void)
313  {
315  }
316 
317  virtual void Save(QString /*destination*/) { }
318 
319  private:
321 };
322 
324 
326 {
327  public:
329  LineEditSetting(this), m_rotor(rotor)
330  {
331  setLabel(DeviceTree::tr("Rotor Low Speed (deg/sec)"));
332  QString help = DeviceTree::tr(
333  "To allow the approximate monitoring of rotor movement, enter "
334  "the rated angular speed of the rotor when powered at 13V.");
335  setHelpText(help);
336  }
337 
338  virtual void Load(void)
339  {
340  setValue(QString::number(m_rotor.GetLoSpeed()));
341  }
342 
343  virtual void Save(void)
344  {
345  m_rotor.SetLoSpeed(getValue().toDouble());
346  }
347 
348  virtual void Save(QString /*destination*/) { }
349 
350  private:
352 };
353 
355 
357 {
358  public:
360  LineEditSetting(this), m_rotor(rotor)
361  {
362  setLabel(DeviceTree::tr("Rotor High Speed (deg/sec)"));
363  QString help = DeviceTree::tr(
364  "To allow the approximate monitoring of rotor movement, enter "
365  "the rated angular speed of the rotor when powered at 18V.");
366  setHelpText(help);
367  }
368 
369  virtual void Load(void)
370  {
371  setValue(QString::number(m_rotor.GetHiSpeed()));
372  }
373 
374  virtual void Save(void)
375  {
376  m_rotor.SetHiSpeed(getValue().toDouble());
377  }
378 
379  virtual void Save(QString /*destination*/) { }
380 
381  private:
383 };
384 
386 
387 static QString AngleToString(double angle)
388 {
389  QString str = QString::null;
390  if (angle >= 0.0)
391  str = QString::number(angle) +
392  DeviceTree::tr("E", "Eastern Hemisphere");
393  else /* if (angle < 0.0) */
394  str = QString::number(-angle) +
395  DeviceTree::tr("W", "Western Hemisphere");
396  return str;
397 }
398 
399 static double AngleToEdit(double angle, QString &hemi)
400 {
401  if (angle > 0.0)
402  {
403  hemi = "E";
404  return angle;
405  }
406 
407  hemi = "W";
408  return -angle;
409 }
410 
411 static double AngleToFloat(const QString &angle, bool translated = true)
412 {
413  if (angle.length() < 2)
414  return 0.0;
415 
416  double pos;
417  QChar postfix = angle.at(angle.length() - 1);
418  if (postfix.isLetter())
419  {
420  pos = angle.left(angle.length() - 1).toDouble();
421  if ((translated &&
422  (postfix.toUpper() ==
423  DeviceTree::tr("W", "Western Hemisphere")[0])) ||
424  (!translated && (postfix.toUpper() == 'W')))
425  {
426  pos = -pos;
427  }
428  }
429  else
430  pos = angle.toDouble();
431 
432  return pos;
433 }
434 
436  ListBoxSetting(this), m_rotor(rotor)
437 {
438  connect(this, SIGNAL(editButtonPressed(int)), SLOT(edit(void)));
439  connect(this, SIGNAL(deleteButtonPressed(int)), SLOT(del(void)));
440  connect(this, SIGNAL(accepted(int)), SLOT(edit(void)));
441 }
442 
444 {
446  PopulateList();
447 }
448 
450 {
452 }
453 
455 {
456  uint id = getValue().toUInt();
457 
458  QString angle;
461  DeviceTree::tr("Position Index %1").arg(id),
462  DeviceTree::tr("Orbital Position"), angle))
463  {
464  m_posmap[id] = AngleToFloat(angle);
465  PopulateList();
466  }
467 }
468 
470 {
471  uint id = getValue().toUInt();
472  m_posmap.erase(m_posmap.find(id));
473  PopulateList();
474 }
475 
477 {
478  int old_sel = getValueIndex(getValue());
479  clearSelections();
480  uint num_pos = 64;
481  for (uint pos = 1; pos < num_pos; pos++)
482  {
483  uint_to_dbl_t::const_iterator it = m_posmap.find(pos);
484  QString posval = DeviceTree::tr("None");
485  if (it != m_posmap.end())
486  posval = AngleToString(*it);
487 
488  addSelection(DeviceTree::tr("Position #%1 (%2)").arg(pos).arg(posval),
489  QString::number(pos));
490  }
491  setCurrentItem(old_sel);
492 }
493 
495 
497 {
498  public:
500  {
501  setLabel(DeviceTree::tr("Rotor Position Map"));
502  addChild(new RotorPosMap(rotor));
503  }
504 
505  virtual DialogCode exec(void)
506  {
508  return kDialogCodeRejected;
509  }
510  virtual DialogCode exec(bool /*saveOnExec*/, bool /*doLoad*/)
511  { return exec(); }
512 };
513 
515 
516 RotorConfig::RotorConfig(DiSEqCDevRotor &rotor) : m_rotor(rotor)
517 {
518  ConfigurationGroup *group =
519  new VerticalConfigurationGroup(false, false);
520  group->setLabel(DeviceTree::tr("Rotor Configuration"));
521 
522  group->addChild(new DeviceDescrSetting(rotor));
523  group->addChild(new DeviceRepeatSetting(rotor));
524 
525  ConfigurationGroup *tgroup =
526  new HorizontalConfigurationGroup(false, false, true, true);
527 
528  RotorTypeSetting *rtype = new RotorTypeSetting(rotor);
529  connect(rtype, SIGNAL(valueChanged(const QString&)),
530  this, SLOT( SetType( const QString&)));
531  tgroup->addChild(rtype);
532 
533  m_pos = new TransButtonSetting();
534  m_pos->setLabel(DeviceTree::tr("Positions"));
535  m_pos->setHelpText(DeviceTree::tr("Rotor position setup."));
537  connect(m_pos, SIGNAL(pressed(void)),
538  this, SLOT( RunRotorPositionsDialog(void)));
539  tgroup->addChild(m_pos);
540 
541  group->addChild(tgroup);
542  group->addChild(new RotorLoSpeedSetting(rotor));
543  group->addChild(new RotorHiSpeedSetting(rotor));
544  group->addChild(DiSEqCLatitude());
545  group->addChild(DiSEqCLongitude());
546 
547  addChild(group);
548 }
549 
550 void RotorConfig::SetType(const QString &type)
551 {
553  rtype = (DiSEqCDevRotor::dvbdev_rotor_t) type.toUInt();
555 }
556 
558 {
560  config.exec();
561  config.Save();
562 }
563 
565 
567 {
568  public:
569  lnb_preset(const QString &_name, DiSEqCDevLNB::dvbdev_lnb_t _type,
570  uint _lof_sw = 0, uint _lof_lo = 0,
571  uint _lof_hi = 0, bool _pol_inv = false) :
572  name(_name), type(_type),
573  lof_sw(_lof_sw), lof_lo(_lof_lo),
574  lof_hi(_lof_hi), pol_inv(_pol_inv) {}
575 
576  public:
577  QString name;
582  bool pol_inv;
583 };
584 
586 {
587  /* description, type, LOF switch, LOF low, LOF high, inverted polarity */
588  lnb_preset(DeviceTree::tr("Universal (Europe)"),
590  11700000, 9750000, 10600000),
591  lnb_preset(DeviceTree::tr("Single (Europe)"),
593  lnb_preset(DeviceTree::tr("Circular (N. America)"),
594  DiSEqCDevLNB::kTypeVoltageControl, 0, 11250000),
595  lnb_preset(DeviceTree::tr("Linear (N. America)"),
596  DiSEqCDevLNB::kTypeVoltageControl, 0, 10750000),
597  lnb_preset(DeviceTree::tr("C Band"),
599  lnb_preset(DeviceTree::tr("DishPro Bandstacked"),
600  DiSEqCDevLNB::kTypeBandstacked, 0, 11250000, 14350000),
602 };
603 
604 static uint FindPreset(const DiSEqCDevLNB &lnb)
605 {
606  uint i;
607  for (i = 0; !lnb_presets[i].name.isEmpty(); i++)
608  {
609  if (lnb_presets[i].type == lnb.GetType() &&
610  lnb_presets[i].lof_sw == lnb.GetLOFSwitch() &&
611  lnb_presets[i].lof_lo == lnb.GetLOFLow() &&
612  lnb_presets[i].lof_hi == lnb.GetLOFHigh() &&
613  lnb_presets[i].pol_inv== lnb.IsPolarityInverted())
614  {
615  break;
616  }
617  }
618  return i;
619 }
620 
622 {
623  public:
625  {
626  setLabel(DeviceTree::tr("LNB Preset"));
627  QString help = DeviceTree::tr(
628  "Select the LNB preset from the list, or choose "
629  "'Custom' and set the advanced settings below.");
630  setHelpText(help);
631 
632  uint i = 0;
633  for (; !lnb_presets[i].name.isEmpty(); i++)
634  addSelection(lnb_presets[i].name, QString::number(i));
635  addSelection(DeviceTree::tr("Custom"), QString::number(i));
636  }
637 
638  virtual void Load(void)
639  {
641  }
642 
643  virtual void Save(void)
644  {
645  }
646 
647  virtual void Save(QString /*destination*/)
648  {
649  }
650 
651  private:
653 };
654 
656 
657 class LNBTypeSetting : public ComboBoxSetting, public Storage
658 {
659  public:
661  {
662  setLabel(DeviceTree::tr("LNB Type"));
663  setHelpText(DeviceTree::tr("Select the type of LNB from the list."));
664  addSelection(DeviceTree::tr("Legacy (Fixed)"),
665  QString::number((uint) DiSEqCDevLNB::kTypeFixed));
666  addSelection(DeviceTree::tr("Standard (Voltage)"),
667  QString::number((uint) DiSEqCDevLNB::
668  kTypeVoltageControl));
669  addSelection(DeviceTree::tr("Universal (Voltage & Tone)"),
670  QString::number((uint) DiSEqCDevLNB::
671  kTypeVoltageAndToneControl));
672  addSelection(DeviceTree::tr("Bandstacked"),
673  QString::number((uint) DiSEqCDevLNB::kTypeBandstacked));
674  }
675 
676  virtual void Load(void)
677  {
678  setValue(getValueIndex(QString::number((uint) m_lnb.GetType())));
679  }
680 
681  virtual void Save(void)
682  {
684  }
685 
686  virtual void Save(QString /*destination*/) { }
687 
688  private:
690 };
691 
693 
695 {
696  public:
698  {
699  setLabel(DeviceTree::tr("LNB LOF Switch (MHz)"));
700  QString help = DeviceTree::tr(
701  "This defines at what frequency the LNB will do a "
702  "switch from high to low setting, and vice versa.");
703  setHelpText(help);
704  }
705 
706  virtual void Load(void)
707  {
708  setValue(QString::number(m_lnb.GetLOFSwitch() / 1000));
709  }
710 
711  virtual void Save(void)
712  {
713  m_lnb.SetLOFSwitch(getValue().toUInt() * 1000);
714  }
715 
716  virtual void Save(QString /*destination*/) { }
717 
718  private:
720 };
721 
723 
725 {
726  public:
728  {
729  setLabel(DeviceTree::tr("LNB LOF Low (MHz)"));
730  QString help = DeviceTree::tr(
731  "This defines the offset the frequency coming "
732  "from the LNB will be in low setting. For bandstacked "
733  "LNBs this is the vertical/right polarization band.");
734  setHelpText(help);
735  }
736 
737  virtual void Load(void)
738  {
739  setValue(QString::number(m_lnb.GetLOFLow() / 1000));
740  }
741 
742  virtual void Save(void)
743  {
744  m_lnb.SetLOFLow(getValue().toUInt() * 1000);
745  }
746 
747  virtual void Save(QString /*destination*/) { }
748 
749  private:
751 };
752 
754 
756 {
757  public:
759  {
760  setLabel(DeviceTree::tr("LNB LOF High (MHz)"));
761  QString help = DeviceTree::tr(
762  "This defines the offset the frequency coming from "
763  "the LNB will be in high setting. For bandstacked "
764  "LNBs this is the horizontal/left polarization band.");
765  setHelpText(help);
766  }
767 
768  virtual void Load(void)
769  {
770  setValue(QString::number(m_lnb.GetLOFHigh() / 1000));
771  }
772 
773  virtual void Save(void)
774  {
775  m_lnb.SetLOFHigh(getValue().toUInt() * 1000);
776  }
777 
778  virtual void Save(QString /*destination*/) { }
779 
780  private:
782 };
783 
785 {
786  public:
788  CheckBoxSetting(this), m_lnb(lnb)
789  {
790  setLabel(DeviceTree::tr("LNB Reversed"));
791  QString help = DeviceTree::tr(
792  "This defines whether the signal reaching the LNB "
793  "is reversed from normal polarization. This happens "
794  "to circular signals bouncing twice on a toroidal "
795  "dish.");
796  setHelpText(help);
797  }
798 
799  virtual void Load(void)
800  {
802  }
803 
804  virtual void Save(void)
805  {
807  }
808 
809  virtual void Save(QString /*destination*/) { }
810 
811  private:
813 };
814 
816 
818 {
819  ConfigurationGroup *group =
820  new VerticalConfigurationGroup(false, false);
821  group->setLabel(DeviceTree::tr("LNB Configuration"));
822 
823  group->addChild(new DeviceDescrSetting(lnb));
824  LNBPresetSetting *preset = new LNBPresetSetting(lnb);
825  group->addChild(preset);
826  m_type = new LNBTypeSetting(lnb);
827  group->addChild(m_type);
829  group->addChild(m_lof_switch);
830  m_lof_lo = new LNBLOFLowSetting(lnb);
831  group->addChild(m_lof_lo);
832  m_lof_hi = new LNBLOFHighSetting(lnb);
833  group->addChild(m_lof_hi);
835  group->addChild(m_pol_inv);
836  connect(m_type, SIGNAL(valueChanged(const QString&)),
837  this, SLOT( UpdateType( void)));
838  connect(preset, SIGNAL(valueChanged(const QString&)),
839  this, SLOT( SetPreset( const QString&)));
840  addChild(group);
841 }
842 
843 void LNBConfig::SetPreset(const QString &value)
844 {
845  uint index = value.toUInt();
846  if (index >= (sizeof(lnb_presets) / sizeof(lnb_preset)))
847  return;
848 
849  lnb_preset &preset = lnb_presets[index];
850  if (preset.name.isEmpty())
851  {
852  m_type->setEnabled(true);
853  UpdateType();
854  }
855  else
856  {
858  QString::number((uint)preset.type)));
859  m_lof_switch->setValue(QString::number(preset.lof_sw / 1000));
860  m_lof_lo->setValue(QString::number(preset.lof_lo / 1000));
861  m_lof_hi->setValue(QString::number(preset.lof_hi / 1000));
862  m_pol_inv->setValue(preset.pol_inv);
863  m_type->setEnabled(false);
864  m_lof_switch->setEnabled(false);
865  m_lof_hi->setEnabled(false);
866  m_lof_lo->setEnabled(false);
867  m_pol_inv->setEnabled(false);
868  }
869 }
870 
872 {
873  if (!m_type->isEnabled())
874  return;
875 
876  switch ((DiSEqCDevLNB::dvbdev_lnb_t) m_type->getValue().toUInt())
877  {
880  m_lof_switch->setEnabled(false);
881  m_lof_hi->setEnabled(false);
882  m_lof_lo->setEnabled(true);
883  m_pol_inv->setEnabled(true);
884  break;
886  m_lof_switch->setEnabled(true);
887  m_lof_hi->setEnabled(true);
888  m_lof_lo->setEnabled(true);
889  m_pol_inv->setEnabled(true);
890  break;
892  m_lof_switch->setEnabled(false);
893  m_lof_hi->setEnabled(true);
894  m_lof_lo->setEnabled(true);
895  m_pol_inv->setEnabled(true);
896  break;
897  }
898 }
899 
901 
903  ListBoxSetting(this), m_tree(tree)
904 {
905  connect(this, SIGNAL(editButtonPressed(int)), SLOT(edit(void)));
906  connect(this, SIGNAL(deleteButtonPressed(int)), SLOT(del(void)));
907  connect(this, SIGNAL(accepted(int)), SLOT(edit(void)));
908 }
909 
911 {
912  PopulateTree();
913 }
914 
916 {
917 }
918 
920 {
921  DiSEqCDevDevice *dev = m_tree.FindDevice(nodeid);
922  if (!dev)
923  {
924  LOG(VB_GENERAL, LOG_ERR, QString("DeviceTree::EditNodeDialog(%1) "
925  "-- device not found").arg(nodeid));
926  return false;
927  }
928 
929  bool changed = false;
930  switch (dev->GetDeviceType())
931  {
933  {
934  DiSEqCDevSwitch *sw = dynamic_cast<DiSEqCDevSwitch*>(dev);
935  if (sw)
936  {
937  SwitchConfig config(*sw);
938  changed = (config.exec() == MythDialog::Accepted);
939  }
940  }
941  break;
942 
944  {
945  DiSEqCDevRotor *rotor = dynamic_cast<DiSEqCDevRotor*>(dev);
946  if (rotor)
947  {
948  RotorConfig config(*rotor);
949  changed = (config.exec() == MythDialog::Accepted);
950  }
951  }
952  break;
953 
955  {
956  DiSEqCDevLNB *lnb = dynamic_cast<DiSEqCDevLNB*>(dev);
957  if (lnb)
958  {
959  LNBConfig config(*lnb);
960  changed = (config.exec() == MythDialog::Accepted);
961  }
962  }
963  break;
964 
965  default:
966  break;
967  }
968 
969  if (changed)
970  PopulateTree();
971 
972  return changed;
973 }
974 
976 {
977  MythPopupBox *popup = new MythPopupBox(GetMythMainWindow(), "");
978  popup->addLabel(tr("Select Type of Device"));
979 
980  MythListBox *list = new MythListBox(popup);
981  list->insertItem(tr("Switch"));
982  list->insertItem(tr("Rotor"));
983  list->insertItem(tr("LNB"));
984  list->setCurrentRow(0, QItemSelectionModel::Select);
985 
986  popup->addWidget(list);
987  connect(list, SIGNAL(accepted(int)),
988  popup, SLOT( AcceptItem(int)));
989  list->setFocus();
990 
991  DialogCode res = popup->ExecPopup();
992  type = (DiSEqCDevDevice::dvbdev_t)(list->currentRow());
993 
994  popup->hide();
995  popup->deleteLater();
996 
997  return kDialogCodeRejected != res;
998 }
999 
1001 {
1003  if (!RunTypeDialog(type))
1004  return;
1005 
1007  if (dev)
1008  {
1009  m_tree.SetRoot(dev);
1010 
1011  if (!EditNodeDialog(dev->GetDeviceID()))
1012  m_tree.SetRoot(NULL);
1013 
1014  PopulateTree();
1015  }
1016 }
1017 
1018 void DeviceTree::CreateNewNodeDialog(uint parentid, uint child_num)
1019 {
1020  DiSEqCDevDevice *parent = m_tree.FindDevice(parentid);
1021  if (!parent)
1022  return;
1023 
1025  if (RunTypeDialog(type))
1026  {
1028  if (!dev)
1029  return;
1030 
1031  if (parent->SetChild(child_num, dev))
1032  {
1033  if (!EditNodeDialog(dev->GetDeviceID()))
1034  parent->SetChild(child_num, NULL);
1035  PopulateTree();
1036  }
1037  else
1038  {
1039  delete dev;
1040  }
1041  }
1042 }
1043 
1045 {
1046  QString id = getValue();
1047  if (id.indexOf(':') == -1)
1048  {
1049  EditNodeDialog(id.toUInt());
1050  }
1051  else
1052  {
1053  QStringList vals = id.split(':');
1054  if (vals[0].isEmpty())
1056  else
1057  CreateNewNodeDialog(vals[0].toUInt(), vals[1].toUInt());
1058  }
1059  setFocus();
1060 }
1061 
1063 {
1064  QString id = getValue();
1065 
1066  if (id.indexOf(':') == -1)
1067  {
1068  uint nodeid = id.toUInt();
1069  DiSEqCDevDevice *dev = m_tree.FindDevice(nodeid);
1070  if (dev)
1071  {
1072  DiSEqCDevDevice *parent = dev->GetParent();
1073  if (parent)
1074  parent->SetChild(dev->GetOrdinal(), NULL);
1075  else
1076  m_tree.SetRoot(NULL);
1077 
1078  PopulateTree();
1079  }
1080  }
1081 
1082  setFocus();
1083 }
1084 
1086 {
1087  int old_sel = getValueIndex(getValue());
1088  clearSelections();
1090  setCurrentItem(old_sel);
1091 }
1092 
1094  DiSEqCDevDevice *parent,
1095  uint childnum,
1096  uint depth)
1097 {
1098  QString indent;
1099  indent.fill(' ', 8 * depth);
1100 
1101  if (node)
1102  {
1103  QString id = QString::number(node->GetDeviceID());
1104  addSelection(indent + node->GetDescription(), id);
1105  uint num_ch = node->GetChildCount();
1106  for (uint ch = 0; ch < num_ch; ch++)
1107  PopulateTree(node->GetChild(ch), node, ch, depth+1);
1108  }
1109  else
1110  {
1111  QString id;
1112  if (parent)
1113  id = QString::number(parent->GetDeviceID());
1114  id += ":" + QString::number(childnum);
1115 
1116  addSelection(indent + "(Unconnected)", id);
1117  }
1118 }
1119 
1121 
1123 {
1124  setLabel(DeviceTree::tr("DiSEqC Device Tree"));
1125  addChild(new DeviceTree(tree));
1126 }
1127 
1129 {
1131  return kDialogCodeRejected;
1132 }
1133 
1135 
1136 class SwitchSetting : public ComboBoxSetting, public Storage
1137 {
1138  public:
1140  : ComboBoxSetting(this), m_node(node), m_settings(settings)
1141  {
1142  setLabel(node.GetDescription());
1143  setHelpText(DeviceTree::tr("Choose a port to use for this switch."));
1144 
1145  uint num_children = node.GetChildCount();
1146  for (uint ch = 0; ch < num_children; ch++)
1147  {
1148  QString val = QString("%1").arg(ch);
1149  QString descr = DeviceTree::tr("Port %1").arg(ch+1);
1150  DiSEqCDevDevice *child = node.GetChild(ch);
1151  if (child)
1152  descr += QString(" (%2)").arg(child->GetDescription());
1153  addSelection(descr, val);
1154  }
1155  }
1156 
1157  virtual void Load(void)
1158  {
1159  double value = m_settings.GetValue(m_node.GetDeviceID());
1160  setValue((uint)value);
1161  }
1162 
1163  virtual void Save(void)
1164  {
1165  m_settings.SetValue(m_node.GetDeviceID(), getValue().toDouble());
1166  }
1167 
1168  virtual void Save(QString /*destination*/) {}
1169 
1170  private:
1173 };
1174 
1176 
1177 class RotorSetting : public ComboBoxSetting, public Storage
1178 {
1179  public:
1181  : ComboBoxSetting(this), m_node(node), m_settings(settings)
1182  {
1183  setLabel(node.GetDescription());
1184  setHelpText(DeviceTree::tr("Choose a satellite position."));
1185 
1186  DiSEqCDevRotor *rotor = dynamic_cast<DiSEqCDevRotor*>(&m_node);
1187  if (rotor)
1188  m_posmap = rotor->GetPosMap();
1189  }
1190 
1191  virtual void Load(void)
1192  {
1193  clearSelections();
1194 
1195  uint_to_dbl_t::const_iterator it;
1196  for (it = m_posmap.begin(); it != m_posmap.end(); ++it)
1197  addSelection(AngleToString(*it), QString::number(*it));
1198 
1199  double angle = m_settings.GetValue(m_node.GetDeviceID());
1200  setValue(getValueIndex(QString::number(angle)));
1201  }
1202 
1203  virtual void Save(void)
1204  {
1205  m_settings.SetValue(m_node.GetDeviceID(), getValue().toDouble());
1206  }
1207 
1208  virtual void Save(QString /*destination*/) { }
1209 
1210  private:
1214 };
1215 
1217 
1219 {
1220  public:
1225  m_node(node), m_settings(settings)
1226  {
1227  QString help =
1228  DeviceTree::tr(
1229  "Locates the satellite you wish to point to "
1230  "with the longitude along the Clarke Belt of "
1231  "the satellite [-180..180] and its hemisphere.");
1232 
1233  numeric->setLabel(DeviceTree::tr("Longitude (degrees)"));
1234  numeric->setHelpText(help);
1235  hemisphere->setLabel(DeviceTree::tr("Hemisphere"));
1236  hemisphere->addSelection(DeviceTree::tr("Eastern"), "E", false);
1237  hemisphere->addSelection(DeviceTree::tr("Western"), "W", true);
1238  hemisphere->setHelpText(help);
1239 
1240  addChild(numeric);
1242  }
1243 
1244  virtual void Load(void)
1245  {
1246  double val = m_settings.GetValue(m_node.GetDeviceID());
1247  QString hemi = QString::null;
1248  double eval = AngleToEdit(val, hemi);
1249  numeric->setValue(QString::number(eval));
1251  }
1252 
1253  virtual void Save(void)
1254  {
1255  QString val = QString::number(numeric->getValue().toDouble());
1256  val += hemisphere->getValue();
1258  }
1259 
1260  virtual void Save(QString /*destination*/) { }
1261 
1262  private:
1267 };
1268 
1270 
1272  DiSEqCDevSettings &settings, uint cardid, bool switches_enabled) :
1274  m_settings(settings), m_switches_enabled(switches_enabled)
1275 {
1276  setLabel(DeviceTree::tr("DTV Device Configuration"));
1277 
1278  // load
1279  m_tree.Load(cardid);
1280 
1281  // initial UI setup
1282  AddNodes(this, QString::null, m_tree.Root());
1283 }
1284 
1286 {
1287 }
1288 
1290  ConfigurationGroup *group, const QString &trigger, DiSEqCDevDevice *node)
1291 {
1292  if (!node)
1293  return;
1294 
1295  Setting *setting = NULL;
1296  switch (node->GetDeviceType())
1297  {
1299  setting = new SwitchSetting(*node, m_settings);
1300  setting->setEnabled(m_switches_enabled);
1301  break;
1303  {
1304  DiSEqCDevRotor *rotor = dynamic_cast<DiSEqCDevRotor*>(node);
1305  if (rotor && (rotor->GetType() == DiSEqCDevRotor::kTypeDiSEqC_1_2))
1306  setting = new RotorSetting(*node, m_settings);
1307  else
1308  setting = new USALSRotorSetting(*node, m_settings);
1309  break;
1310  }
1311  default:
1312  break;
1313  }
1314 
1315  if (!setting)
1316  {
1317  AddChild(group, trigger, new TransLabelSetting());
1318  return;
1319  }
1320 
1321  m_devs[node->GetDeviceID()] = setting;
1322 
1323  uint num_ch = node->GetChildCount();
1325  {
1326  bool useframe = (node != m_tree.Root());
1327  bool zerospace = !useframe;
1329  false, useframe, true, true, false, false, true, zerospace);
1330 
1331  cgrp->addChild(setting);
1332  cgrp->setTrigger(setting);
1333 
1334  for (uint i = 0; i < num_ch; i++)
1335  AddNodes(cgrp, QString::number(i), node->GetChild(i));
1336 
1337  AddChild(group, trigger, cgrp);
1338  return;
1339  }
1340 
1341  if (!num_ch)
1342  {
1343  AddChild(group, trigger, setting);
1344  return;
1345  }
1346 
1348  new VerticalConfigurationGroup(false, false, true, true);
1349 
1350  AddChild(cgrp, QString::null, setting);
1351  for (uint i = 0; i < num_ch; i++)
1352  AddNodes(cgrp, QString::null, node->GetChild(i));
1353 
1354  AddChild(group, trigger, cgrp);
1355 }
1356 
1358  ConfigurationGroup *group, const QString &trigger, Setting *setting)
1359 {
1361  dynamic_cast<TriggeredConfigurationGroup*>(group);
1362 
1363  if (grp && !trigger.isEmpty())
1364  grp->addTarget(trigger, setting);
1365  else
1366  group->addChild(setting);
1367 }
1368 
1370 
1372 {
1385 };
1386 
1387 // import old diseqc configuration into tree
1389 {
1390  MSqlQuery cquery(MSqlQuery::InitCon());
1391  cquery.prepare(
1392  "SELECT cardid, dvb_diseqc_type "
1393  "FROM capturecard"
1394  "WHERE dvb_diseqc_type IS NOT NULL AND "
1395  " diseqcid IS NULL");
1396 
1397  // iterate through cards
1398  if (!cquery.exec())
1399  return false;
1400 
1401  MSqlQuery iquery(MSqlQuery::InitCon());
1402  iquery.prepare(
1403  "SELECT cardinputid, diseqc_port, diseqc_pos, "
1404  " lnb_lof_switch, lnb_lof_hi, lnb_lof_lo "
1405  "FROM cardinput "
1406  "WHERE cardinput.cardid = :CARDID");
1407 
1408  while (cquery.next())
1409  {
1410  uint cardid = cquery.value(0).toUInt();
1411  OLD_DISEQC_TYPES type = (OLD_DISEQC_TYPES) cquery.value(1).toUInt();
1412 
1413  DiSEqCDevTree tree;
1414  DiSEqCDevDevice *root = NULL;
1415  uint add_lnbs = 0;
1416  DiSEqCDevLNB::dvbdev_lnb_t lnb_type =
1418 
1419  // create root of tree
1420  switch (type)
1421  {
1422  case DISEQC_SINGLE:
1423  {
1424  // single LNB
1427  break;
1428  }
1429 
1430  case DISEQC_MINI_2:
1431  {
1432  // tone switch + 2 LNBs
1435  DiSEqCDevSwitch *sw = dynamic_cast<DiSEqCDevSwitch*>(root);
1436  if (sw)
1437  {
1439  sw->SetNumPorts(2);
1440  add_lnbs = 2;
1441  }
1442  break;
1443  }
1444 
1445  case DISEQC_SWITCH_2_1_0:
1446  case DISEQC_SWITCH_2_1_1:
1447  {
1448  // 2 port diseqc + 2 LNBs
1451  DiSEqCDevSwitch *sw = dynamic_cast<DiSEqCDevSwitch*>(root);
1452  if (sw)
1453  {
1455  sw->SetAddress(0x10);
1456  sw->SetNumPorts(2);
1457  add_lnbs = 2;
1458  }
1459  break;
1460  }
1461 
1462  case DISEQC_SWITCH_4_1_0:
1463  case DISEQC_SWITCH_4_1_1:
1464  {
1465  // 4 port diseqc + 4 LNBs
1468  DiSEqCDevSwitch *sw = dynamic_cast<DiSEqCDevSwitch*>(root);
1469  if (sw)
1470  {
1472  sw->SetAddress(0x10);
1473  sw->SetNumPorts(4);
1474  add_lnbs = 4;
1475  }
1476  break;
1477  }
1478 
1479  case DISEQC_POSITIONER_1_2:
1480  {
1481  // non-usals positioner + LNB
1484  DiSEqCDevRotor *rotor = dynamic_cast<DiSEqCDevRotor*>(root);
1485  if (rotor)
1486  {
1488  add_lnbs = 1;
1489  }
1490  break;
1491  }
1492 
1493  case DISEQC_POSITIONER_X:
1494  {
1495  // usals positioner + LNB (diseqc_pos)
1498  DiSEqCDevRotor *rotor = dynamic_cast<DiSEqCDevRotor*>(root);
1499  if (rotor)
1500  {
1502  add_lnbs = 1;
1503  }
1504  break;
1505  }
1506 
1508  {
1509  // 10 port uncommitted switch + 10 LNBs
1512  DiSEqCDevSwitch *sw = dynamic_cast<DiSEqCDevSwitch*>(root);
1513  if (sw)
1514  {
1516  sw->SetNumPorts(10);
1517  add_lnbs = 10;
1518  }
1519  break;
1520  }
1521 
1522  case DISEQC_SW21:
1523  {
1524  // legacy SW21 + 2 fixed lnbs
1527  DiSEqCDevSwitch *sw = dynamic_cast<DiSEqCDevSwitch*>(root);
1528  if (sw)
1529  {
1531  sw->SetNumPorts(2);
1532  add_lnbs = 2;
1533  lnb_type = DiSEqCDevLNB::kTypeFixed;
1534  }
1535  break;
1536  }
1537 
1538  case DISEQC_SW64:
1539  {
1540  // legacy SW64 + 3 fixed lnbs
1543  DiSEqCDevSwitch *sw = dynamic_cast<DiSEqCDevSwitch*>(root);
1544  if (sw)
1545  {
1547  sw->SetNumPorts(3);
1548  add_lnbs = 3;
1549  lnb_type = DiSEqCDevLNB::kTypeFixed;
1550  }
1551  break;
1552  }
1553 
1554  default:
1555  {
1556  LOG(VB_GENERAL, LOG_ERR, "Unknown DiSEqC device type " +
1557  QString("%1 ignoring card %2").arg(type).arg(cardid));
1558  break;
1559  }
1560  }
1561 
1562  if (!root)
1563  continue;
1564 
1565  tree.SetRoot(root);
1566 
1567  // create LNBs
1568  for (uint i = 0; i < add_lnbs; i++)
1569  {
1570  DiSEqCDevLNB *lnb = dynamic_cast<DiSEqCDevLNB*>
1572  tree, DiSEqCDevDevice::kTypeLNB));
1573  if (lnb)
1574  {
1575  lnb->SetType(lnb_type);
1576  lnb->SetDescription(QString("LNB #%1").arg(i+1));
1577  if (!root->SetChild(i, lnb))
1578  delete lnb;
1579  }
1580  }
1581 
1582  // save the tree to get real device ids
1583  tree.Store(cardid);
1584 
1585  // iterate inputs
1586  DiSEqCDevSettings set;
1587  iquery.bindValue(":CARDID", cardid);
1588 
1589  if (!iquery.exec())
1590  return false;
1591 
1592  while (iquery.next())
1593  {
1594  uint inputid = iquery.value(0).toUInt();
1595  uint port = iquery.value(1).toUInt();
1596  double pos = iquery.value(2).toDouble();
1597  DiSEqCDevLNB *lnb = NULL;
1598 
1599  // configure LNB and settings
1600  switch (type)
1601  {
1602  case DISEQC_SINGLE:
1603  lnb = dynamic_cast<DiSEqCDevLNB*>(root);
1604  break;
1605 
1606  case DISEQC_MINI_2:
1607  case DISEQC_SWITCH_2_1_0:
1608  case DISEQC_SWITCH_2_1_1:
1609  case DISEQC_SWITCH_4_1_0:
1610  case DISEQC_SWITCH_4_1_1:
1611  case DISEQC_SW21:
1612  case DISEQC_SW64:
1614  lnb = dynamic_cast<DiSEqCDevLNB*>(root->GetChild(port));
1615  set.SetValue(root->GetDeviceID(), port);
1616  break;
1617 
1618  case DISEQC_POSITIONER_1_2:
1619  case DISEQC_POSITIONER_X:
1620  lnb = dynamic_cast<DiSEqCDevLNB*>(root->GetChild(0));
1621  set.SetValue(root->GetDeviceID(), pos);
1622  break;
1623 
1624  default:
1625  break;
1626  }
1627 
1628  // configure lnb
1629  if (lnb)
1630  {
1631  lnb->SetLOFSwitch(iquery.value(3).toUInt());
1632  lnb->SetLOFHigh(iquery.value(4).toUInt());
1633  lnb->SetLOFLow(iquery.value(5).toUInt());
1634  }
1635 
1636  // save settings
1637  set.Store(inputid);
1638  }
1639 
1640  // save any LNB changes
1641  tree.Store(cardid);
1642 
1643  // invalidate cached devices
1644  DiSEqCDev trees;
1645  trees.InvalidateTrees();
1646  }
1647 
1648  return true;
1649 }