diff --git a/data/Makefile.am b/data/Makefile.am index ffce4ceb4..5f4751b23 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -5,7 +5,7 @@ SUBDIRS += lcd endif configdir = $(CONFIGDIR) -config_DATA = cables.xml satellites.xml encoding.conf tobackup.conf providermap.xml settingsupdate.conf +config_DATA = cables.xml satellites.xml encoding.conf tobackup.conf providermap.xml settingsupdate.conf terrestrial.xml install-data-hook: $(INSTALL) -d $(DESTDIR)/$(CONFIGDIR)/zapit diff --git a/data/locale/deutsch.locale b/data/locale/deutsch.locale index 66ba3a800..fb1065324 100644 --- a/data/locale/deutsch.locale +++ b/data/locale/deutsch.locale @@ -1784,6 +1784,7 @@ scants.abort_body Scanvorgang wirklich abbrechen? scants.abort_header breche Scan ab... scants.actcable Kabelnetz: scants.actsatellite Satellit: +scants.actterrestrial Terrestrisch: scants.bouquet Bouquets scants.bouquet_create neu erstellen scants.bouquet_erase löschen @@ -1878,6 +1879,7 @@ stringinput.clear Alles löschen subtitles.charset Zeichensatz subtitles.head Untertitel subtitles.stop Untertitel aus +terrestrialsetup.provider DVB-T Region timer.eventrecord.msg Die Sendung wurde zur Aufnahme vorgemerkt. timer.eventrecord.title Aufnahme vormerken timer.eventtimed.msg Die Sendung wurde vorgemerkt. diff --git a/data/locale/english.locale b/data/locale/english.locale index 39820b4fc..5d9b82545 100644 --- a/data/locale/english.locale +++ b/data/locale/english.locale @@ -1784,6 +1784,7 @@ scants.abort_body Should the search really be aborted? scants.abort_header Abortion of channel scan scants.actcable Cable: scants.actsatellite Satellite: +scants.actterrestrial Terrestrial: scants.bouquet Bouquet scants.bouquet_create create new scants.bouquet_erase erase old @@ -1878,6 +1879,7 @@ stringinput.clear clear all subtitles.charset Charset subtitles.head Subtitles subtitles.stop Stop subtitles +terrestrialsetup.provider Terrestrial Provider timer.eventrecord.msg The event is scheduled for recording.\nTo edit the schedule open the timer list. timer.eventrecord.title Schedule Record timer.eventtimed.msg The event is scheduled.\nThe box will power on and \nswitch to this channel at the given time. diff --git a/data/mk_terrestrial_xml.pl b/data/mk_terrestrial_xml.pl new file mode 100755 index 000000000..e008f25ec --- /dev/null +++ b/data/mk_terrestrial_xml.pl @@ -0,0 +1,92 @@ +#!/usr/bin/perl -w +# +# create a terrestrial.xml for neutrino from the data installed by the +# dvb utils +# the behaviour is similar to the "scan" program form the dvb utils. +# +# Released under the GPL V2 or later +# (C) 2009-2012 Stefan Seyfried + +use strict; +my $srcdir = "/usr/share/dvb/dvb-t"; + +# can be given as "de-*" +my $scanfile = shift; +$scanfile = "auto-Default" unless (defined $scanfile); + +my @sourcefiles = glob($srcdir . "/" . $scanfile); +my ($sourcefile, $basename, $line, $k); +my ($freq, $bw, $cr_hp, $cr_lp, $mod, $tmode, $gint, $hier); + +# from /usr/include/linux/dvb/frontend.h +# inversion is not used in the scan files +my %INV = ("INVERSION_OFF" => 0, "INVERSION_ON" => 1, "INVERSION_AUTO" => 2); +my %CODE_RATE = ("NONE" => 0, "1/2" => 1, "2/3" => 2, "3/4" => 3, "4/5" => 4, + "5/6" => 5, "6/7" => 6, "7/8" => 7, "8/9" => 8, "AUTO" => 9); +my %MODULATION = ("QPSK" => 0, "QAM16" => 1, "QAM32" => 2, "QAM64" => 3, + "QAM128" => 4, "QAM256" => 5, "AUTO" => 6); +my %T_MODE = ("2k" => 0, "8k" => 1, "AUTO" => 2); +my %BWIDTH = ("8MHz" => 0, "7MHz" => 1, "6MHz" => 2, "AUTO" => 3); +my %GINTERVAL = ("1/32" => 0, "1/16" => 1, "1/8" => 2, "1/4" => 3, "AUTO" => 4); +my %HIERARCHY = ("NONE" => 0, "1" => 1, "2" => 2, "4" => 3, "AUTO" => 4); + + +# print the header +print("\n"); +print("\n\n"); +print("\n"); +# +# explain the parameters +print("\n\n"); +# header ends... + +print("\n"); +foreach $sourcefile (@sourcefiles) +{ + open(FILE, "< $sourcefile") or die "can't open $sourcefile: $!\n"; + $basename = $sourcefile; + $basename =~ s#^.*/##; + print("\t\n"); + while ($line = ) + { # T 184500000 7MHz 3/4 NONE QAM16 8k 1/4 NONE + next unless ($line =~ m/^T\s+(\d+)\s+(\dMHz)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/); + $freq = $1; $bw = $2; $cr_hp = $3; $cr_lp = $4; $mod = $5; $tmode = $6; $gint = $7; $hier = $8; + unless (defined($CODE_RATE{$cr_hp})) { warn "$basename: illegal cr_hp: $cr_hp, using AUTO\n"; $cr_hp="AUTO" }; + unless (defined($CODE_RATE{$cr_lp})) { warn "$basename: illegal cr_lp: $cr_lp, using AUTO\n"; $cr_lp="AUTO" }; + unless (defined($MODULATION{$mod})) { die "$basename: illegal mod: $mod\n" }; # no errors in those (yet). + unless (defined($T_MODE{$tmode})) { die "$basename: illegal tmode: $tmode\n" }; + unless (defined($GINTERVAL{$gint})) { die "$basename: illegal gint: $gint\n" }; + unless (defined($HIERARCHY{$hier})) { die "$basename: illegal hier: $hier\n" }; + unless (defined($BWIDTH{$bw})) { die "$basename: illegal bw: $bw\n" }; + if ($cr_hp eq "NONE") { $cr_hp="AUTO" }; # same as scan.c + if ($cr_lp eq "NONE") { $cr_lp="AUTO" }; # same as scan.c + printf("\t\t\n", + $freq / 1000, $BWIDTH{$bw}, $MODULATION{$mod}, + $T_MODE{$tmode}, $CODE_RATE{$cr_hp}, $CODE_RATE{$cr_lp}, + $GINTERVAL{$gint}, $HIERARCHY{$hier}); + } + print("\t\n"); +} +print("\n"); diff --git a/data/terrestrial.xml b/data/terrestrial.xml new file mode 100644 index 000000000..6c03dd07e --- /dev/null +++ b/data/terrestrial.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/gui/scan.cpp b/src/gui/scan.cpp index f553be1a4..4725abf55 100644 --- a/src/gui/scan.cpp +++ b/src/gui/scan.cpp @@ -221,6 +221,18 @@ int CScanTs::exec(CMenuTarget* /*parent*/, const std::string & actionKey) TP.feparams.dvb_feparams.u.qpsk.symbol_rate = atoi(scansettings.sat_TP_rate.c_str()); TP.feparams.dvb_feparams.u.qpsk.fec_inner = (fe_code_rate_t) scansettings.sat_TP_fec; TP.polarization = scansettings.sat_TP_pol; + } else if (deltype == FE_OFDM) { + /* DVB-T. TODO: proper menu and parameter setup, not all "AUTO" */ + if (TP.feparams.dvb_feparams.frequency < 300000) + TP.feparams.dvb_feparams.u.ofdm.bandwidth = BANDWIDTH_7_MHZ; + else + TP.feparams.dvb_feparams.u.ofdm.bandwidth = BANDWIDTH_8_MHZ; + TP.feparams.dvb_feparams.u.ofdm.code_rate_HP = FEC_AUTO; + TP.feparams.dvb_feparams.u.ofdm.code_rate_LP = FEC_AUTO; + TP.feparams.dvb_feparams.u.ofdm.constellation = QAM_AUTO; + TP.feparams.dvb_feparams.u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; + TP.feparams.dvb_feparams.u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; + TP.feparams.dvb_feparams.u.ofdm.hierarchy_information = HIERARCHY_AUTO; } else { TP.feparams.dvb_feparams.frequency = atoi(scansettings.cable_TP_freq.c_str()); TP.feparams.dvb_feparams.u.qam.symbol_rate = atoi(scansettings.cable_TP_rate.c_str()); diff --git a/src/gui/scan_setup.cpp b/src/gui/scan_setup.cpp index a00bfde8e..c84e5c8e8 100644 --- a/src/gui/scan_setup.cpp +++ b/src/gui/scan_setup.cpp @@ -476,6 +476,36 @@ int CScanSetup::showScanMenu() settings->addItem(fcableScan); settings->addItem(GenericMenuSeparatorLine); } + if (CFEManager::getInstance()->haveTerr()) { + r_system = DVB_T; + // tune timeout, "Setup tuner" is not shown for only one non-sat tuner + if (CFEManager::getInstance()->getFrontendCount() <= 1) { + CMenuOptionNumberChooser * nc = new CMenuOptionNumberChooser(LOCALE_EXTRA_ZAPIT_FE_TIMEOUT, (int *)&zapitCfg.feTimeout, true, 6, 100); + nc->setHint("", LOCALE_MENU_HINT_SCAN_FETIMEOUT); + settings->addItem(nc); + } + + //auto scan + char autoscan[64]; + std::string s_capt_part = g_Locale->getText(LOCALE_TERRESTRIALSETUP_PROVIDER); + snprintf(autoscan, 64, g_Locale->getText(LOCALE_SATSETUP_AUTO_SCAN), s_capt_part.c_str()); + bool have_other = ! CFEManager::getInstance()->terrOnly(); + + /* FIXME leak, satSelect added to both auto and manual scan, so one of them cannot be deleted */ + CMenuWidget * autoScan = new CMenuWidget(LOCALE_SERVICEMENU_SCANTS, NEUTRINO_ICON_SETTINGS, w, MN_WIDGET_ID_SCAN_AUTO_SCAN); + addScanMenuAutoScan(autoScan); + mf = new CMenuDForwarder(autoscan, true, NULL, autoScan, "", have_other ? CRCInput::RC_nokey : CRCInput::RC_green, have_other ? NULL : NEUTRINO_ICON_BUTTON_GREEN); + mf->setHint("", LOCALE_MENU_HINT_SCAN_AUTO); + settings->addItem(mf); + + //manual scan + CMenuWidget * manualScan = new CMenuWidget(LOCALE_SATSETUP_MANUAL_SCAN, NEUTRINO_ICON_SETTINGS, w, MN_WIDGET_ID_SCAN_MANUAL_SCAN); + addScanMenuManualScan(manualScan); + mf = new CMenuForwarder(LOCALE_SATSETUP_MANUAL_SCAN, true, NULL, manualScan, "", have_other ? CRCInput::RC_nokey : CRCInput::RC_yellow, have_other ? NULL : NEUTRINO_ICON_BUTTON_YELLOW); + mf->setHint("", LOCALE_MENU_HINT_SCAN_MANUAL); + settings->addItem(mf); + settings->addItem(GenericMenuSeparatorLine); + } //service select mode mc = new CMenuOptionChooser(LOCALE_ZAPIT_SCANTYPE, (int *)&scansettings.scanType, SCANTS_ZAPIT_SCANTYPE, SCANTS_ZAPIT_SCANTYPE_COUNT, true, NULL, CRCInput::convertDigitToKey(shortcut++), "", true); mc->setHint("", LOCALE_MENU_HINT_SCAN_SCANTYPE); @@ -1266,7 +1296,6 @@ int CScanSetup::addScanOptionsItems(CMenuWidget *options_menu, const int &shortc printf("[neutrino] CScanSetup call %s...\n", __FUNCTION__); int shortCut = shortcut; - CMenuOptionChooser *fec = NULL; CMenuOptionChooser *mod_pol = NULL; CMenuForwarder *Freq = NULL; @@ -1293,13 +1322,19 @@ int CScanSetup::addScanOptionsItems(CMenuWidget *options_menu, const int &shortc Rate->setHint("", LOCALE_MENU_HINT_SCAN_RATE); mod_pol = new CMenuOptionChooser(LOCALE_EXTRA_TP_MOD, (int *)&scansettings.cable_TP_mod, SATSETUP_SCANTP_MOD, SATSETUP_SCANTP_MOD_COUNT, true, NULL, CRCInput::convertDigitToKey(shortCut++)); mod_pol->setHint("", LOCALE_MENU_HINT_SCAN_MOD); + } else if (r_system == DVB_T) { + CStringInput *freq = new CStringInput(LOCALE_EXTRA_TP_FREQ, &scansettings.terr_TP_freq, 6, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, "0123456789"); + Freq = new CMenuDForwarder(LOCALE_EXTRA_TP_FREQ, true, scansettings.terr_TP_freq, freq, "", CRCInput::convertDigitToKey(shortCut++)); + Freq->setHint("", LOCALE_MENU_HINT_SCAN_FREQ); } options_menu->addItem(Freq); - options_menu->addItem(Rate); - if (r_system == DVB_S) + if (Rate) + options_menu->addItem(Rate); + if (fec) options_menu->addItem(fec); - options_menu->addItem(mod_pol); + if (mod_pol) + options_menu->addItem(mod_pol); return shortCut; } diff --git a/src/neutrino.cpp b/src/neutrino.cpp index 51ae3a1d5..81aa36f4d 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -1891,12 +1891,20 @@ TIMER_START(); cpuFreq = new cCpuFreqManager(); cpuFreq->SetCpuFreq(g_settings.cpufreq * 1000 * 1000); - - g_info.delivery_system = CFEManager::getInstance()->getLiveFE()->getInfo()->type == FE_QPSK ? DVB_S : DVB_C; -#if HAVE_TRIPLEDRAGON - /* only SAT-hd1 before rev 8 has fan, rev 1 is TD (compat hack) */ - g_info.has_fan = (cs_get_revision() > 1 && cs_get_revision() < 8 && g_info.delivery_system == DVB_S); -#else + switch (CFEManager::getInstance()->getLiveFE()->getInfo()->type) { + case FE_QPSK: + g_info.delivery_system = DVB_S; + break; + case FE_OFDM: + g_info.delivery_system = DVB_T; + break; + case FE_QAM: + default: + g_info.delivery_system = DVB_C; + break; + } +#if HAVE_COOL_HARDWARE + /* only SAT-hd1 before rev 8 has fan */ g_info.has_fan = (cs_get_revision() < 8 && g_info.delivery_system == DVB_S); #endif dprintf(DEBUG_NORMAL, "g_info.has_fan: %d\n", g_info.has_fan); diff --git a/src/system/locals.h b/src/system/locals.h index 258375c28..85f153220 100644 --- a/src/system/locals.h +++ b/src/system/locals.h @@ -1811,6 +1811,7 @@ typedef enum LOCALE_SCANTS_ABORT_HEADER, LOCALE_SCANTS_ACTCABLE, LOCALE_SCANTS_ACTSATELLITE, + LOCALE_SCANTS_ACTTERRESTRIAL, LOCALE_SCANTS_BOUQUET, LOCALE_SCANTS_BOUQUET_CREATE, LOCALE_SCANTS_BOUQUET_ERASE, @@ -1905,6 +1906,7 @@ typedef enum LOCALE_SUBTITLES_CHARSET, LOCALE_SUBTITLES_HEAD, LOCALE_SUBTITLES_STOP, + LOCALE_TERRESTRIALSETUP_PROVIDER, LOCALE_TIMER_EVENTRECORD_MSG, LOCALE_TIMER_EVENTRECORD_TITLE, LOCALE_TIMER_EVENTTIMED_MSG, diff --git a/src/system/locals_intern.h b/src/system/locals_intern.h index 32306cb70..69ac38b0e 100644 --- a/src/system/locals_intern.h +++ b/src/system/locals_intern.h @@ -1811,6 +1811,7 @@ const char * locale_real_names[] = "scants.abort_header", "scants.actcable", "scants.actsatellite", + "scants.actterrestrial", "scants.bouquet", "scants.bouquet_create", "scants.bouquet_erase", @@ -1905,6 +1906,7 @@ const char * locale_real_names[] = "subtitles.charset", "subtitles.head", "subtitles.stop", + "terrestrialsetup.provider", "timer.eventrecord.msg", "timer.eventrecord.title", "timer.eventtimed.msg", diff --git a/src/zapit/include/zapit/scan.h b/src/zapit/include/zapit/scan.h index 938dab62b..3b6046e45 100644 --- a/src/zapit/include/zapit/scan.h +++ b/src/zapit/include/zapit/scan.h @@ -61,7 +61,6 @@ class CServiceScan : public OpenThreads::Thread private: bool started; bool running; - bool cable; bool abort_scan; scan_type_t scan_mode; int flags; diff --git a/src/zapit/include/zapit/settings.h b/src/zapit/include/zapit/settings.h index c70c58fd2..7be89bc9f 100644 --- a/src/zapit/include/zapit/settings.h +++ b/src/zapit/include/zapit/settings.h @@ -47,6 +47,7 @@ #define CABLES_XML CONFIGDIR "/cables.xml" #define SATELLITES_XML CONFIGDIR "/satellites.xml" +#define TERRESTRIAL_XML CONFIGDIR "/terrestrial.xml" #define AUDIO_DEVICE "/dev/dvb/adapter0/audio0" #define DEMUX_DEVICE "/dev/dvb/adapter0/demux0" diff --git a/src/zapit/src/frontend.cpp b/src/zapit/src/frontend.cpp index 40d8e6947..24a75dd58 100644 --- a/src/zapit/src/frontend.cpp +++ b/src/zapit/src/frontend.cpp @@ -51,17 +51,27 @@ extern int zapit_debug; #define FREQUENCY 1 #define MODULATION 2 #define INVERSION 3 +// common to S/S2/C #define SYMBOL_RATE 4 #define DELIVERY_SYSTEM 5 #define INNER_FEC 6 // DVB-S/S2 specific #define PILOTS 7 #define ROLLOFF 8 +// DVB-T specific +#define BANDWIDTH 4 +#define CODE_RATE_HP 6 +#define CODE_RATE_LP 7 +#define TRANSMISSION_MODE 8 +#define GUARD_INTERVAL 9 +#define HIERARCHY 10 + #define FE_COMMON_PROPS 2 #define FE_DVBS_PROPS 6 #define FE_DVBS2_PROPS 8 #define FE_DVBC_PROPS 6 +#define FE_DVBT_PROPS 10 /* stolen from dvb.c from vlc */ static const struct dtv_property dvbs_cmdargs[] = { @@ -99,6 +109,21 @@ static const struct dtv_property dvbc_cmdargs[] = { { DTV_TUNE, {}, { 0 }, 0}, }; +static const struct dtv_property dvbt_cmdargs[] = { + { DTV_CLEAR, {0,0,0}, { 0 } ,0}, + { DTV_FREQUENCY, {}, { 0 } ,0}, + { DTV_MODULATION, {}, { QAM_AUTO } ,0}, + { DTV_INVERSION, {}, { INVERSION_AUTO } ,0}, + { DTV_BANDWIDTH_HZ, {}, { 8000000 } ,0}, + { DTV_DELIVERY_SYSTEM, {}, { SYS_DVBT } ,0}, + { DTV_CODE_RATE_HP, {}, { FEC_AUTO } ,0}, + { DTV_CODE_RATE_LP, {}, { FEC_AUTO } ,0}, + { DTV_TRANSMISSION_MODE,{}, { TRANSMISSION_MODE_AUTO}, 0}, + { DTV_GUARD_INTERVAL, {}, { GUARD_INTERVAL_AUTO}, 0}, + { DTV_HIERARCHY, {}, { HIERARCHY_AUTO }, 0}, + { DTV_TUNE, {}, { 0 }, 0}, +}; + #define diff(x,y) (max(x,y) - min(x,y)) @@ -500,7 +525,8 @@ void CFrontend::getDelSys(int f, int m, char *&fec, char *&sys, char *&mod) void CFrontend::getDelSys(uint8_t type, int f, int m, char *&fec, char *&sys, char *&mod) { - if (type == FE_QPSK) { + switch (type) { + case FE_QPSK: if (f < FEC_S2_QPSK_1_2) { sys = (char *)"DVB"; mod = (char *)"QPSK"; @@ -511,7 +537,9 @@ void CFrontend::getDelSys(uint8_t type, int f, int m, char *&fec, char *&sys, ch sys = (char *)"DVB-S2"; mod = (char *)"8PSK"; } - } else if (type == FE_QAM) { + break; + case FE_QAM: + case FE_OFDM: sys = (char *)"DVB"; switch (m) { case QAM_16: @@ -529,11 +557,23 @@ void CFrontend::getDelSys(uint8_t type, int f, int m, char *&fec, char *&sys, ch case QAM_256: mod = (char *)"QAM_256"; break; + case QPSK: + if (type == FE_OFDM) { + mod = (char *)"QPSK"; + break; + } + /* fallthrouh for FE_QAM... */ case QAM_AUTO: default: mod = (char *)"QAM_AUTO"; break; } + break; + default: + printf("[frontend] unknown type %d!\n", type); + sys = (char *)"UNKNOWN"; + mod = (char *)"UNKNOWN"; + break; } switch (f) { @@ -614,6 +654,11 @@ bool CFrontend::buildProperties(const FrontendParameters *feparams, struct dtv_p modulation = feparams->dvb_feparams.u.qam.modulation; delsys = SYS_DVBC_ANNEX_AC; break; + case FE_OFDM: + fec_inner = FEC_AUTO; /* dummy, for next switch statement */ + modulation = feparams->dvb_feparams.u.ofdm.constellation; + delsys = SYS_DVBT; + break; default: printf("frontend: unknown frontend type, exiting\n"); return 0; @@ -712,6 +757,36 @@ bool CFrontend::buildProperties(const FrontendParameters *feparams, struct dtv_p cmdseq.props[INNER_FEC].u.data = fec_inner; nrOfProps = FE_DVBC_PROPS; break; + case FE_OFDM: + memcpy(cmdseq.props, dvbt_cmdargs, sizeof(dvbt_cmdargs)); + nrOfProps = FE_DVBT_PROPS; + cmdseq.props[FREQUENCY].u.data = feparams->dvb_feparams.frequency; + cmdseq.props[MODULATION].u.data = modulation; + cmdseq.props[INVERSION].u.data = feparams->dvb_feparams.inversion; + cmdseq.props[CODE_RATE_HP].u.data = feparams->dvb_feparams.u.ofdm.code_rate_HP; + cmdseq.props[CODE_RATE_LP].u.data = feparams->dvb_feparams.u.ofdm.code_rate_LP; + cmdseq.props[TRANSMISSION_MODE].u.data = feparams->dvb_feparams.u.ofdm.transmission_mode; + cmdseq.props[GUARD_INTERVAL].u.data = feparams->dvb_feparams.u.ofdm.guard_interval; + cmdseq.props[HIERARCHY].u.data = feparams->dvb_feparams.u.ofdm.hierarchy_information; + switch (feparams->dvb_feparams.u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + cmdseq.props[BANDWIDTH].u.data = 6000000; + break; + case BANDWIDTH_7_MHZ: + cmdseq.props[BANDWIDTH].u.data = 7000000; + break; + case BANDWIDTH_8_MHZ: + cmdseq.props[BANDWIDTH].u.data = 8000000; + break; + default: + printf("[fe%d] unknown bandwidth for OFDM %d\n", + fenumber, feparams->dvb_feparams.u.ofdm.bandwidth); + /* fallthrough */ + case BANDWIDTH_AUTO: + cmdseq.props[BANDWIDTH].u.data = 0; + break; + } + break; default: printf("frontend: unknown frontend type, exiting\n"); return false; @@ -731,7 +806,7 @@ bool CFrontend::buildProperties(const FrontendParameters *feparams, struct dtv_p int CFrontend::setFrontend(const FrontendParameters *feparams, bool nowait) { - struct dtv_property cmdargs[FE_COMMON_PROPS + FE_DVBS2_PROPS]; // WARNING: increase when needed more space + struct dtv_property cmdargs[FE_COMMON_PROPS + FE_DVBT_PROPS]; // WARNING: increase when needed more space struct dtv_properties cmdseq; cmdseq.num = FE_COMMON_PROPS; @@ -1096,10 +1171,10 @@ int CFrontend::setParameters(TP_params *TP, bool nowait) memcpy(&feparams, &TP->feparams, sizeof(feparams)); freq = (int) feparams.dvb_feparams.frequency; char * f, *s, *m; + bool high_band; - if (info.type == FE_QPSK) { - bool high_band; - + switch (info.type) { + case FE_QPSK: if (freq < lnbSwitch) { high_band = false; freq_offset = lnbOffsetLow; @@ -1111,10 +1186,30 @@ int CFrontend::setParameters(TP_params *TP, bool nowait) feparams.dvb_feparams.frequency = abs(freq - freq_offset); setSec(TP->diseqc, TP->polarization, high_band); getDelSys(feparams.dvb_feparams.u.qpsk.fec_inner, dvbs_get_modulation(feparams.dvb_feparams.u.qpsk.fec_inner), f, s, m); - } else if (info.type == FE_QAM) { + break; + case FE_QAM: if (freq < 1000*1000) feparams.dvb_feparams.frequency = freq * 1000; - getDelSys(feparams.dvb_feparams.u.qam.fec_inner, feparams.dvb_feparams.u.qam.modulation, f, s, m); + getDelSys(feparams.dvb_feparams.u.qam.fec_inner,feparams.dvb_feparams.u.qam.modulation, f, s, m); +#if 0 + switch (TP->feparams.dvb_feparams.inversion) { + case INVERSION_OFF: + TP->feparams.dvb_feparams.inversion = INVERSION_ON; + break; + case INVERSION_ON: + default: + TP->feparams.dvb_feparams.inversion = INVERSION_OFF; + break; + } +#endif + case FE_OFDM: + if (freq < 1000*1000) + feparams.dvb_feparams.frequency = freq * 1000; + getDelSys(feparams.dvb_feparams.u.ofdm.code_rate_HP,feparams.dvb_feparams.u.ofdm.constellation, f, s, m); + break; + default: + printf("[fe%d] unknown type %d\n", fenumber, info.type); + break; } printf("[fe%d] tune to %d %s %s %s %s srate %d (tuner %d offset %d timeout %d)\n", fenumber, freq, s, m, f, diff --git a/src/zapit/src/getservices.cpp b/src/zapit/src/getservices.cpp index 30b087724..a4b2fed4d 100644 --- a/src/zapit/src/getservices.cpp +++ b/src/zapit/src/getservices.cpp @@ -70,11 +70,12 @@ bool CServiceManager::ParseScanXml(fe_type_t delsys) case FE_QPSK: scanInputParser = parseXmlFile(SATELLITES_XML); break; - case FE_QAM: scanInputParser = parseXmlFile(CABLES_XML); break; - + case FE_OFDM: + scanInputParser = parseXmlFile(TERRESTRIAL_XML); + break; default: WARN("Unknown type %d", frontendType); return false; @@ -330,14 +331,17 @@ void CServiceManager::ParseTransponders(xmlNodePtr node, t_satellite_position sa feparams.dvb_feparams.frequency = xmlGetNumericAttribute(node, "frq", 0); feparams.dvb_feparams.inversion = (fe_spectral_inversion) xmlGetNumericAttribute(node, "inv", 0); - if(delsys == FE_QAM) { + switch (delsys) { + case FE_OFDM: + case FE_QAM: feparams.dvb_feparams.u.qam.symbol_rate = xmlGetNumericAttribute(node, "sr", 0); feparams.dvb_feparams.u.qam.fec_inner = (fe_code_rate_t) xmlGetNumericAttribute(node, "fec", 0); feparams.dvb_feparams.u.qam.modulation = (fe_modulation_t) xmlGetNumericAttribute(node, "mod", 0); if (feparams.dvb_feparams.frequency > 1000*1000) feparams.dvb_feparams.frequency = feparams.dvb_feparams.frequency/1000; //transponderlist was read from tuxbox - } else { + break; + default: feparams.dvb_feparams.u.qpsk.fec_inner = (fe_code_rate_t) xmlGetNumericAttribute(node, "fec", 0); feparams.dvb_feparams.u.qpsk.symbol_rate = xmlGetNumericAttribute(node, "sr", 0); @@ -351,7 +355,7 @@ void CServiceManager::ParseTransponders(xmlNodePtr node, t_satellite_position sa else feparams.dvb_feparams.frequency = (int) 1000 * (int) round ((double) feparams.dvb_feparams.frequency / (double) 1000); } - freq_id_t freq = CREATE_FREQ_ID(feparams.dvb_feparams.frequency, delsys == FE_QAM); + freq_id_t freq = CREATE_FREQ_ID(feparams.dvb_feparams.frequency, delsys != FE_QPSK); transponder_id_t tid = CREATE_TRANSPONDER_ID64(freq, satellitePosition,original_network_id,transport_stream_id); transponder t(delsys, tid, feparams, polarization); @@ -476,6 +480,11 @@ void CServiceManager::FindTransponder(xmlNodePtr search) char * name = xmlGetAttribute(search, "name"); satellitePosition = GetSatellitePosition(name); } + else if (!strcmp(xmlGetName(search), "terrestrial")) { + delsys = FE_OFDM; + char * name = xmlGetAttribute(search, "name"); + satellitePosition = GetSatellitePosition(name); + } else if ((strcmp(xmlGetName(search), "sat"))) { search = search->xmlNextNode; continue; @@ -527,7 +536,28 @@ void CServiceManager::ParseSatTransponders(fe_type_t fType, xmlNodePtr search, t feparams.dvb_feparams.u.qpsk.fec_inner = (fe_code_rate_t) xml_fec; feparams.dvb_feparams.frequency = (int) 1000 * (int) round ((double) feparams.dvb_feparams.frequency / (double) 1000); } - freq_id_t freq = CREATE_FREQ_ID(feparams.dvb_feparams.frequency, fType == FE_QAM); + else if (fType == FE_OFDM) { + feparams.dvb_feparams.u.ofdm.bandwidth = (fe_bandwidth_t) + xmlGetNumericAttribute(tps, "bandwidth", 0); + feparams.dvb_feparams.u.ofdm.constellation = (fe_modulation_t) + xmlGetNumericAttribute(tps, "constellation", 0); + feparams.dvb_feparams.u.ofdm.transmission_mode = (fe_transmit_mode_t) + xmlGetNumericAttribute(tps, "transmission_mode", 0); + feparams.dvb_feparams.u.ofdm.code_rate_HP = (fe_code_rate_t) + xmlGetNumericAttribute(tps, "code_rate_HP", 0); + feparams.dvb_feparams.u.ofdm.code_rate_LP = (fe_code_rate_t) + xmlGetNumericAttribute(tps, "code_rate_LP", 0); + feparams.dvb_feparams.u.ofdm.guard_interval = (fe_guard_interval_t) + xmlGetNumericAttribute(tps, "guard_interval", 0); + feparams.dvb_feparams.u.ofdm.hierarchy_information = (fe_hierarchy_t) + xmlGetNumericAttribute(tps, "hierarchy", 0); + if (feparams.dvb_feparams.frequency > 1000*1000) + feparams.dvb_feparams.frequency /= 1000; // old transponder list + } + else /* we'll probably crash sooner or later, so write to STDERR... */ + fprintf(stderr, "[getservices] %s: unknown frontend type %d!\n", __func__, fType); + + freq_id_t freq = CREATE_FREQ_ID(feparams.dvb_feparams.frequency, fType != FE_QPSK); polarization &= 7; transponder_id_t tid = CREATE_TRANSPONDER_ID64(freq, satellitePosition, fake_nid, fake_tid); @@ -675,6 +705,7 @@ bool CServiceManager::LoadServices(bool only_current) satcleared = 1; } #endif + TIMER_START(); allchans.clear(); transponders.clear(); @@ -694,6 +725,10 @@ bool CServiceManager::LoadServices(bool only_current) INFO("Loading cables..."); LoadScanXml(FE_QAM); } + if (CFEManager::getInstance()->haveTerr()) { + INFO("Loading terrestrial..."); + LoadScanXml(FE_OFDM); + } parser = parseXmlFile(SERVICES_XML); if (parser != NULL) { @@ -704,6 +739,11 @@ bool CServiceManager::LoadServices(bool only_current) if (!(strcmp(xmlGetName(search), "sat"))) { position = xmlGetSignedNumericAttribute(search, "position", 10); InitSatPosition(position, name, false, FE_QPSK); + } else if (!(strcmp(xmlGetName(search), "terrestrial"))) { + position = GetSatellitePosition(name); + if (!position) + position = (0x0EFF & fake_pos++); + InitSatPosition(position, name, false, FE_OFDM); } else { position = GetSatellitePosition(name); if (!position) @@ -783,7 +823,9 @@ void CServiceManager::WriteSatHeader(FILE * fd, sat_config_t &config) case FE_QAM: /* cable */ fprintf(fd, "\t\n", config.name.c_str(), config.position); break; - case FE_OFDM: + case FE_OFDM: /* terrestrial */ + fprintf(fd, "\t\n", config.name.c_str(), config.position); + break; default: break; } @@ -853,6 +895,9 @@ void CServiceManager::SaveServices(bool tocopy, bool if_changed, bool no_deleted case FE_QAM: fprintf(fd, "\t\n"); break; + case FE_OFDM: + fprintf(fd, "\t\n"); + break; default: break; } @@ -977,6 +1022,8 @@ bool CServiceManager::SaveCurrentServices(transponder_id_t tpid) footer = ""; break; case FE_OFDM: + sprintf(satstr, "\t<%s name=\"%s\"\n", "terrestrial", spos_it->second.name.c_str()); + break; default: break; } diff --git a/src/zapit/src/scan.cpp b/src/zapit/src/scan.cpp index c6ba501b1..cd09fe827 100644 --- a/src/zapit/src/scan.cpp +++ b/src/zapit/src/scan.cpp @@ -270,7 +270,7 @@ _repeat: } } - freq_id_t freq = CREATE_FREQ_ID(tI->second.feparams.dvb_feparams.frequency, cable); + freq_id_t freq = CREATE_FREQ_ID(tI->second.feparams.dvb_feparams.frequency, frontendType != FE_QPSK); CNit nit(satellitePosition, freq, cable_nid); if(flags & SCAN_NIT) @@ -480,7 +480,6 @@ bool CServiceScan::SetFrontend(t_satellite_position satellitePosition) frontend = fe; CFEManager::getInstance()->setLiveFE(frontend); frontendType = frontend->getInfo()->type; - cable = (frontend->getInfo()->type == FE_QAM);//FIXME return true; } @@ -594,9 +593,10 @@ bool CServiceScan::ScanTransponder() printf("[scan] NIT %s, fta only: %s, satellites %s\n", flags & SCAN_NIT ? "yes" : "no", flags & SCAN_FTA ? "yes" : "no", scanProviders.size() == 1 ? "single" : "multi"); - freq_id_t freq = CREATE_FREQ_ID(TP->feparams.dvb_feparams.frequency, cable); + freq_id_t freq = CREATE_FREQ_ID(TP->feparams.dvb_feparams.frequency, frontendType != FE_QPSK); fake_tid++; fake_nid++; + transponder_id_t tid = CREATE_TRANSPONDER_ID64(freq, satellitePosition, fake_nid, fake_tid); transponder t(frontendType, tid, TP->feparams, TP->polarization); t.dump("[scan]"); @@ -639,7 +639,7 @@ bool CServiceScan::ReplaceTransponderParams(freq_id_t freq, t_satellite_position bool ret = false; for (transponder_list_t::iterator tI = transponders.begin(); tI != transponders.end(); ++tI) { if (tI->second.satellitePosition == satellitePosition) { - freq_id_t newfreq = CREATE_FREQ_ID(tI->second.feparams.dvb_feparams.frequency, cable); + freq_id_t newfreq = CREATE_FREQ_ID(tI->second.feparams.dvb_feparams.frequency, frontendType != FE_QPSK); if (freq == newfreq) { memcpy(&tI->second.feparams, feparams, sizeof(struct dvb_frontend_parameters)); tI->second.polarization = polarization; @@ -655,7 +655,7 @@ bool CServiceScan::ReplaceTransponderParams(freq_id_t freq, t_satellite_position void CServiceScan::SendTransponderInfo(transponder &t) { uint32_t actual_freq = t.feparams.dvb_feparams.frequency; - if (!cable) + if (frontendType == FE_QAM) actual_freq /= 1000; CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_REPORT_FREQUENCY, &actual_freq,sizeof(actual_freq)); @@ -663,7 +663,7 @@ void CServiceScan::SendTransponderInfo(transponder &t) CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_PROVIDER, (void *) " ", 2); CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_SERVICENAME, (void *) " ", 2); - if (!cable) { + if (frontendType == FE_QPSK) { uint32_t actual_polarisation = ((t.feparams.dvb_feparams.u.qpsk.symbol_rate/1000) << 16) | (t.feparams.dvb_feparams.u.qpsk.fec_inner << 8) | (uint)t.polarization; CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_REPORT_FREQUENCYP, &actual_polarisation,sizeof(actual_polarisation)); } diff --git a/src/zapit/src/transponder.cpp b/src/zapit/src/transponder.cpp index 291ec09c8..0a1a8f231 100644 --- a/src/zapit/src/transponder.cpp +++ b/src/zapit/src/transponder.cpp @@ -53,13 +53,20 @@ transponder::transponder() bool transponder::operator==(const transponder& t) const { - return ( + if (type != FE_OFDM) + return ( (satellitePosition == t.satellitePosition) && //(transport_stream_id == t.transport_stream_id) && //(original_network_id == t.original_network_id) && ((polarization & 1) == (t.polarization & 1)) && (abs((int) feparams.dvb_feparams.frequency - (int)t.feparams.dvb_feparams.frequency) <= 3000) ); + return ((satellitePosition == t.satellitePosition) && + //(transport_stream_id == t.transport_stream_id) && + //(original_network_id == t.original_network_id) && + ((polarization & 1) == (t.polarization & 1)) && + (abs((int) feparams.dvb_feparams.frequency - (int)t.feparams.dvb_feparams.frequency) <= 100) + ); } bool transponder::compare(const transponder& t) const @@ -77,13 +84,23 @@ bool transponder::compare(const transponder& t) const (dvb_feparams1->u.qam.modulation == dvb_feparams2->u.qam.modulation || dvb_feparams1->u.qam.modulation == QAM_AUTO || dvb_feparams2->u.qam.modulation == QAM_AUTO) ); - } else { + } else if (type == FE_QPSK) { ret = ( (t == (*this)) && (dvb_feparams1->u.qpsk.symbol_rate == dvb_feparams2->u.qpsk.symbol_rate) && (dvb_feparams1->u.qpsk.fec_inner == dvb_feparams2->u.qpsk.fec_inner || dvb_feparams1->u.qpsk.fec_inner == FEC_AUTO || dvb_feparams2->u.qpsk.fec_inner == FEC_AUTO) ); + } else if (type == FE_OFDM) { + ret = ( (t == (*this)) && + (dvb_feparams1->u.ofdm.bandwidth == dvb_feparams2->u.ofdm.bandwidth) && + (dvb_feparams1->u.ofdm.code_rate_HP == dvb_feparams2->u.ofdm.code_rate_HP || + dvb_feparams1->u.ofdm.code_rate_HP == FEC_AUTO || dvb_feparams2->u.ofdm.code_rate_HP == FEC_AUTO) && + (dvb_feparams1->u.ofdm.code_rate_LP == dvb_feparams2->u.ofdm.code_rate_LP || + dvb_feparams1->u.ofdm.code_rate_LP == FEC_AUTO || dvb_feparams2->u.ofdm.code_rate_LP == FEC_AUTO) && + (dvb_feparams1->u.ofdm.constellation == dvb_feparams2->u.ofdm.constellation || + dvb_feparams1->u.ofdm.constellation == QAM_AUTO || dvb_feparams2->u.ofdm.constellation == QAM_AUTO) + ); } return ret; } @@ -99,12 +116,20 @@ void transponder::dumpServiceXml(FILE * fd) dvb_feparams->u.qam.symbol_rate, dvb_feparams->u.qam.fec_inner, dvb_feparams->u.qam.modulation); - } else { + } else if (type == FE_QPSK) { fprintf(fd, "\t\t\n", transport_stream_id, original_network_id, dvb_feparams->frequency, dvb_feparams->inversion, dvb_feparams->u.qpsk.symbol_rate, dvb_feparams->u.qpsk.fec_inner, polarization); + } else if (type == FE_OFDM) { + fprintf(fd, "\t\t\n", + transport_stream_id, original_network_id, + dvb_feparams->frequency, dvb_feparams->inversion, + dvb_feparams->u.ofdm.bandwidth, dvb_feparams->u.ofdm.code_rate_HP, + dvb_feparams->u.ofdm.code_rate_LP, dvb_feparams->u.ofdm.constellation, + dvb_feparams->u.ofdm.transmission_mode, dvb_feparams->u.ofdm.guard_interval, + dvb_feparams->u.ofdm.hierarchy_information); } } @@ -116,10 +141,14 @@ void transponder::dump(std::string label) printf("%s tp-id %016" PRIx64 " freq %d rate %d fec %d mod %d\n", label.c_str(), transponder_id, dvb_feparams->frequency, dvb_feparams->u.qam.symbol_rate, dvb_feparams->u.qam.fec_inner, dvb_feparams->u.qam.modulation); - else + else if (type == FE_QPSK) printf("%s tp-id %016" PRIx64 " freq %d rate %d fec %d pol %d\n", label.c_str(), transponder_id, dvb_feparams->frequency, dvb_feparams->u.qpsk.symbol_rate, dvb_feparams->u.qpsk.fec_inner, polarization); + else if (type == FE_OFDM) + printf("%s tp-id %016llx freq %d bw %d coderate %d\n", label.c_str(), + transponder_id, dvb_feparams->frequency, dvb_feparams->u.ofdm.bandwidth, + dvb_feparams->u.ofdm.code_rate_HP); } #if 0 //never used @@ -144,8 +173,10 @@ char transponder::pol(unsigned char p) std::string transponder::description() { char buf[128] = {0}; - char * f, *s, *m; + char *f, *s, *m, *f2; struct dvb_frontend_parameters *dvb_feparams = &feparams.dvb_feparams; + const char *bw[4] = { "8MHz", "7MHz", "6MHz", "auto" }; + int b; switch(deltype) { case FE_QPSK: @@ -157,7 +188,15 @@ std::string transponder::description() snprintf(buf, sizeof(buf), "%d %d %s %s %s ", dvb_feparams->frequency/1000, dvb_feparams->u.qam.symbol_rate/1000, f, s, m); break; case FE_OFDM: + CFrontend::getDelSys(type, dvb_feparams->u.ofdm.code_rate_HP, dvb_feparams->u.ofdm.constellation, f, s, m); + CFrontend::getDelSys(type, dvb_feparams->u.ofdm.code_rate_LP, dvb_feparams->u.ofdm.constellation, f2, s, m); + b = dvb_feparams->u.ofdm.bandwidth; + if (b > 3) + b = 3; + snprintf(buf, sizeof(buf), "%d %s %s %s %s ", dvb_feparams->frequency, bw[b], f, f2, m); + break; case FE_ATSC: + snprintf(buf, sizeof(buf), "ATSC not yet supported "); break; } return std::string(buf);