[gnome-dvb-daemon/gst-1.0] Change to gstreamer 1.4.0 API and DVBv5 channel list
- From: Sebastian Polsterl <sebp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-dvb-daemon/gst-1.0] Change to gstreamer 1.4.0 API and DVBv5 channel list
- Date: Sun, 20 Jul 2014 22:53:26 +0000 (UTC)
commit 2ee187997dad1b96d6177ec656416ae2a606c37a
Author: Stefan Ringel <linuxtv stefanringel de>
Date: Sun May 11 11:13:02 2014 +0200
Change to gstreamer 1.4.0 API and DVBv5 channel list
Requires vala 0.26 beside gstreamer 1.4.0
https://bugzilla.gnome.org/show_bug.cgi?id=725230
Makefile.am | 22 +-
client/gnomedvb/DBusWrapper.py | 12 +-
client/gnomedvb/DVBModel.py | 27 +-
client/gnomedvb/Device.py | 16 +-
client/gnomedvb/__init__.py | 6 +
client/gnomedvb/ui/preferences/DeviceGroupsView.py | 3 +-
client/gnomedvb/ui/preferences/Preferences.py | 2 +-
client/gnomedvb/ui/wizard/SetupWizard.py | 2 +-
client/gnomedvb/ui/wizard/__init__.py | 15 +-
client/gnomedvb/ui/wizard/pages/AdaptersPage.py | 45 ++-
client/gnomedvb/ui/wizard/pages/ChannelScanPage.py | 4 +-
.../ui/wizard/pages/InitialTuningDataPage.py | 49 +-
client/gnomedvb/ui/wizard/pages/SetupDevicePage.py | 2 +-
configure.ac | 16 +-
src/Cable/CableChannel.vala | 60 --
src/Cable/CableScanner.vala | 142 -----
src/Channel.vala | 28 +-
src/ChannelFactory.vala | 78 +--
src/ChannelList.vala | 22 +-
src/Device.vala | 275 +++++++---
src/DeviceGroup.vala | 141 ++---
src/EPGScanner.vala | 323 ++++++++---
src/Event.vala | 31 +-
src/Main.vala | 45 +-
src/Manager.vala | 495 ++++++++--------
src/MpegTsEnums.vala | 504 +++++++++++-----
src/Parameter.vala | 48 ++
src/Parameters/DvbCEuropeParameter.vala | 106 ++++
src/Parameters/DvbSParameter.vala | 134 ++++
src/Parameters/DvbTParameter.vala | 146 +++++
src/Recorder.vala | 9 +-
src/Satellite/SatelliteChannel.vala | 56 --
src/Satellite/SatelliteScanner.vala | 174 ------
src/ScannedItem.vala | 86 ---
src/Scanner.vala | 636 +++++++++++---------
src/Settings.vala | 39 --
src/Terrestrial/TerrestrialChannel.vala | 78 ---
src/Terrestrial/TerrestrialScanner.vala | 224 -------
src/database/ConfigStore.vala | 5 +-
src/database/sqlite/SqliteConfigTimersStore.vala | 143 +++--
src/database/sqlite/SqliteEPGStore.vala | 2 +-
src/dbus/IDBusDeviceGroup.vala | 2 +-
src/dbus/IDBusManager.vala | 18 +-
src/io/ChannelListReader.vala | 332 +++--------
src/io/ChannelListWriter.vala | 192 +++----
src/io/ScanningListReader.vala | 104 ++++
src/rtsp/MediaFactory.vala | 136 ++---
src/rtsp/Server.vala | 1 -
48 files changed, 2574 insertions(+), 2462 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index ea60bf4..1e59008 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
ACLOCAL_AMFLAGS = -I m4
-NULL =
+NULL =
SUBDIRS = \
client \
@@ -11,12 +11,9 @@ SUBDIRS = \
bin_PROGRAMS = gnome-dvb-daemon
gnome_dvb_daemon_SOURCES = \
- src/Cable/CableChannel.vala \
- src/Cable/CableScanner.vala \
- src/Satellite/SatelliteChannel.vala \
- src/Satellite/SatelliteScanner.vala \
- src/Terrestrial/TerrestrialChannel.vala \
- src/Terrestrial/TerrestrialScanner.vala \
+ src/Parameters/DvbCEuropeParameter.vala \
+ src/Parameters/DvbSParameter.vala \
+ src/Parameters/DvbTParameter.vala \
src/database/sqlite/SqliteDatabase.vala \
src/database/sqlite/SqliteUtils.vala \
src/database/sqlite/SqliteConfigTimersStore.vala \
@@ -36,6 +33,7 @@ gnome_dvb_daemon_SOURCES = \
src/io/ChannelListWriter.vala \
src/io/RecordingReader.vala \
src/io/RecordingWriter.vala \
+ src/io/ScanningListReader.vala \
src/ChangeType.vala \
src/Channel.vala \
src/ChannelFactory.vala \
@@ -57,7 +55,7 @@ gnome_dvb_daemon_SOURCES = \
src/Recording.vala \
src/RecordingsStore.vala \
src/Scanner.vala \
- src/ScannedItem.vala \
+ src/Parameter.vala \
src/Schedule.vala \
src/Settings.vala \
src/Timer.vala \
@@ -73,14 +71,16 @@ vala_pkgs = \
--pkg gstreamer-1.0 \
--pkg gee-0.8 \
--pkg sqlite3 \
+ --pkg gstreamer-rtsp-1.0 \
--pkg gstreamer-rtsp-server-1.0 \
+ --pkg gstreamer-mpegts-1.0 \
--pkg gudev-1.0 \
$(NULL)
-
+
own_pkgs = \
--pkg config \
--pkg cutils
-
+
gnome_dvb_daemon_CPPFLAGS = \
-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
-DPACKAGE_SRC_DIR=\""$(srcdir)"\" \
@@ -129,7 +129,7 @@ DISTCLEANFILES = \
intltool-merge \
po/.intltool-merge-cache \
$(NULL)
-
+
dist-hook:
@if test -d "$(srcdir)/.git"; \
then \
diff --git a/client/gnomedvb/DBusWrapper.py b/client/gnomedvb/DBusWrapper.py
index 6d26776..d598ec7 100644
--- a/client/gnomedvb/DBusWrapper.py
+++ b/client/gnomedvb/DBusWrapper.py
@@ -45,14 +45,14 @@ CHANNEL_LIST_IFACE = "org.gnome.DVB.ChannelList"
SCHEDULE_IFACE = "org.gnome.DVB.Schedule"
def _default_error_handler_func(*args):
- print("Error: " + str(args), file=sys.stderr)
+ print("Error: " + str(args)) #, file=sys.stderr)
global_error_handler = _default_error_handler_func
def get_adapter_info(adapter, frontend):
manager = DVBManagerClient()
info_t, success = manager.get_adapter_info(adapter, frontend)
- info = {"name": info_t[0], "type": info_t[1]}
+ info = {"name": info_t[0], "type_t": info_t[1], "type_s": info_t[2], "type_c": info_t[3]}
return (success, info)
def get_dvb_devices():
@@ -91,8 +91,8 @@ class DVBManagerClient(GObject.GObject):
self.manager = _get_proxy(MANAGER_PATH, MANAGER_IFACE)
self.manager.connect("g-signal", self.on_g_signal)
- def get_scanner_for_device(self, adapter, frontend):
- objpath, scanner_iface, success = self.manager.GetScannerForDevice ('(uu)', adapter, frontend)
+ def get_scanner_for_device(self, adapter, frontend, type):
+ objpath, scanner_iface, success = self.manager.GetScannerForDevice ('(uui)', adapter, frontend, type)
if success:
return DVBScannerClient(objpath, scanner_iface)
else:
@@ -120,8 +120,8 @@ class DVBManagerClient(GObject.GObject):
else:
return [DVBDeviceGroupClient(path) for path in self.manager.GetRegisteredDeviceGroups()]
- def add_device_to_new_group (self, adapter, frontend, channels_file, recordings_dir, name, **kwargs):
- return self.manager.AddDeviceToNewGroup('(uusss)', adapter, frontend, channels_file, recordings_dir,
name, **kwargs)
+ def add_device_to_new_group (self, adapter, frontend, type, channels_file, recordings_dir, name,
**kwargs):
+ return self.manager.AddDeviceToNewGroup('(uuisss)', adapter, frontend, type, channels_file,
recordings_dir, name, **kwargs)
def get_name_of_registered_device(self, adapter, frontend, **kwargs):
return self.manager.GetNameOfRegisteredDevice('(uu)', adapter, frontend, **kwargs)
diff --git a/client/gnomedvb/DVBModel.py b/client/gnomedvb/DVBModel.py
index 7db18fe..b7a9588 100644
--- a/client/gnomedvb/DVBModel.py
+++ b/client/gnomedvb/DVBModel.py
@@ -17,8 +17,13 @@
# along with GNOME DVB Daemon. If not, see <http://www.gnu.org/licenses/>.
import gnomedvb
+from gnomedvb import GROUP_UNKNOWN
+from gnomedvb import GROUP_TERRESTRIAL
+from gnomedvb import GROUP_SATELLITE
+from gnomedvb import GROUP_CABLE
import re
from gnomedvb.Device import Device
+import copy
class DVBModel (gnomedvb.DVBManagerClient):
@@ -51,7 +56,7 @@ class DVBModel (gnomedvb.DVBManagerClient):
devs = []
for info in gnomedvb.get_dvb_devices():
dev = Device (0, "Unknown", info["adapter"], info["frontend"],
- "Unknown")
+ GROUP_UNKNOWN)
devs.append(dev)
result_handler(devs)
@@ -67,9 +72,21 @@ class DVBModel (gnomedvb.DVBManagerClient):
success, info = gnomedvb.get_adapter_info(dev.adapter,
dev.frontend)
if success:
- dev.name = info["name"]
- dev.type = info["type"]
- unregistered.add(dev)
+ if info["type_t"]:
+ dev_t = copy.copy(dev)
+ dev_t.name = info["name"]
+ dev_t.type = GROUP_TERRESTRIAL
+ unregistered.add(dev_t)
+ if info["type_s"]:
+ dev_s = copy.copy(dev)
+ dev_s.name = info["name"]
+ dev_s.type = GROUP_SATELLITE
+ unregistered.add(dev_s)
+ if info["type_c"]:
+ dev_c = copy.copy(dev)
+ dev_c.name = info["name"]
+ dev_c.type = GROUP_CABLE
+ unregistered.add(dev_c)
result_handler(unregistered)
def registered_handler(devgroups):
@@ -114,7 +131,7 @@ class DeviceGroup(gnomedvb.DVBDeviceGroupClient):
adapter = int(match.group(1))
frontend = int(match.group(2))
devname, success = manager.get_name_of_registered_device(adapter, frontend)
- dev = Device (self._id, devname, adapter, frontend, self["type"])
+ dev = Device (self._id, devname, adapter, frontend, self._type)
dev.group_name = self._name
devices.append(dev)
return devices
diff --git a/client/gnomedvb/Device.py b/client/gnomedvb/Device.py
index dfa2e21..cd1f6e7 100644
--- a/client/gnomedvb/Device.py
+++ b/client/gnomedvb/Device.py
@@ -29,15 +29,23 @@ class Device:
self.type = devtype
def __hash__(self):
- return 2 * PRIME + PRIME * self.adapter + self.frontend
+ return PRIME * PRIME * self.type + PRIME * self.adapter + self.frontend
def __eq__(self, other):
if not isinstance(other, Device):
return False
return (self.adapter == other.adapter \
- and self.frontend == other.frontend)
+ and self.frontend == other.frontend \
+ and self.type == other.type)
- def __repr__(self):
- return "/dev/dvb/adapter%d/frontend%d" % (self.adapter, self.frontend)
+ def __ne__(self, other):
+ if not isinstance(other, Device):
+ return True
+ return (self.adapter != other.adapter \
+ or self.frontend != other.frontend \
+ or self.type != other.type)
+
+ def __repr__(self):
+ return "/dev/dvb/adapter%d/frontend%d/%d" % (self.adapter, self.frontend, self.type)
\ No newline at end of file
diff --git a/client/gnomedvb/__init__.py b/client/gnomedvb/__init__.py
index c62336d..a88a9b9 100644
--- a/client/gnomedvb/__init__.py
+++ b/client/gnomedvb/__init__.py
@@ -38,6 +38,12 @@ INFOS = {
"website-label" : _("GNOME DVB Daemon Website"),
}
+# Group types
+GROUP_UNKNOWN = 0
+GROUP_TERRESTRIAL = 1
+GROUP_SATELLITE = 2
+GROUP_CABLE = 3
+
# From pyxdg
_home = os.environ.get('HOME', '/')
XDG_CONFIG_HOME = os.environ.get('XDG_CONFIG_HOME', join(_home, '.config'))
diff --git a/client/gnomedvb/ui/preferences/DeviceGroupsView.py
b/client/gnomedvb/ui/preferences/DeviceGroupsView.py
index 75af37b..9c1e062 100644
--- a/client/gnomedvb/ui/preferences/DeviceGroupsView.py
+++ b/client/gnomedvb/ui/preferences/DeviceGroupsView.py
@@ -19,6 +19,7 @@
from gi.repository import Gtk
from gi.repository import GObject
from gnomedvb import _
+from gnomedvb.ui.wizard import DVB_TYPE_TO_DESC
from gnomedvb.Device import Device
__all__ = ["UnassignedDevicesStore", "DeviceGroupsStore", "DeviceGroupsView"]
@@ -64,7 +65,7 @@ class DeviceGroupsView (Gtk.TreeView):
if isinstance(device, Device):
# translators: first is device's name, second its type
- text = _("<b>%s (%s)</b>\n") % (device.name, device.type)
+ text = _("<b>%s (%s)</b>\n") % (device.name, DVB_TYPE_TO_DESC[device.type])
text += "<small>%s</small>" % (_("Adapter: %d, Frontend: %d") % (device.adapter,
device.frontend))
else:
diff --git a/client/gnomedvb/ui/preferences/Preferences.py b/client/gnomedvb/ui/preferences/Preferences.py
index 994ff86..9c02514 100644
--- a/client/gnomedvb/ui/preferences/Preferences.py
+++ b/client/gnomedvb/ui/preferences/Preferences.py
@@ -272,7 +272,7 @@ class Preferences(Gtk.Window):
recdir = dialog.recordings_entry.get_text()
name = dialog.name_entry.get_text()
self._model.add_device_to_new_group(device.adapter,
- device.frontend, channels, recdir, name,
+ device.frontend, device.type, channels, recdir, name,
result_handler=add_device_to_new_group_callback,
error_handler=global_error_handler)
diff --git a/client/gnomedvb/ui/wizard/SetupWizard.py b/client/gnomedvb/ui/wizard/SetupWizard.py
index d0d4ec8..048147e 100644
--- a/client/gnomedvb/ui/wizard/SetupWizard.py
+++ b/client/gnomedvb/ui/wizard/SetupWizard.py
@@ -152,7 +152,7 @@ class SetupWizard(Gtk.Assistant):
self.__ask_on_exit = True
if self.__adapter_info["name"] != None:
page.start_scanning(self.__adapter_info["adapter"],
- self.__adapter_info["frontend"], self.tuning_data_page.get_tuning_data ())
+ self.__adapter_info["frontend"], self.__adapter_info["type"],
self.tuning_data_page.get_tuning_data ())
elif isinstance(page, SetupDevicePage):
page.set_adapter(self.__adapter_info)
page.set_scanner(self.scan_page.get_scanner())
diff --git a/client/gnomedvb/ui/wizard/__init__.py b/client/gnomedvb/ui/wizard/__init__.py
index f5867e2..b8a4704 100644
--- a/client/gnomedvb/ui/wizard/__init__.py
+++ b/client/gnomedvb/ui/wizard/__init__.py
@@ -1,13 +1,16 @@
from gnomedvb import _
+from gnomedvb import GROUP_TERRESTRIAL
+from gnomedvb import GROUP_SATELLITE
+from gnomedvb import GROUP_CABLE
DVB_TYPE_TO_DESC = {
- "DVB-C": _("digital cable"),
- "DVB-S": _("digital satellite"),
- "DVB-T": _("digital terrestrial")
+ GROUP_CABLE: _("digital cable"),
+ GROUP_SATELLITE: _("digital satellite"),
+ GROUP_TERRESTRIAL: _("digital terrestrial")
}
DVB_TYPE_TO_TV_DESC = {
- "DVB-C": _("digital cable TV"),
- "DVB-S": _("digital satellite TV"),
- "DVB-T": _("digital terrestrial TV")
+ GROUP_CABLE: _("digital cable TV"),
+ GROUP_SATELLITE: _("digital satellite TV"),
+ GROUP_TERRESTRIAL: _("digital terrestrial TV")
}
diff --git a/client/gnomedvb/ui/wizard/pages/AdaptersPage.py b/client/gnomedvb/ui/wizard/pages/AdaptersPage.py
index fa48057..4ef993a 100644
--- a/client/gnomedvb/ui/wizard/pages/AdaptersPage.py
+++ b/client/gnomedvb/ui/wizard/pages/AdaptersPage.py
@@ -20,9 +20,14 @@ from gi.repository import GObject
import gnomedvb
from gi.repository import Gtk
from gnomedvb import _
+from gnomedvb.Device import Device
+from gnomedvb import GROUP_TERRESTRIAL
+from gnomedvb import GROUP_SATELLITE
+from gnomedvb import GROUP_CABLE
from gnomedvb.ui.wizard import DVB_TYPE_TO_DESC
from gnomedvb.ui.wizard.pages.BasePage import BasePage
from gnomedvb.ui.widgets.Frame import BaseFrame
+import copy
class AdaptersPage(BasePage):
@@ -43,7 +48,7 @@ class AdaptersPage(BasePage):
self.frame = None
# Name, Type Name, Type, adapter, frontend, registered
- self.deviceslist = Gtk.ListStore(str, str, str, int, int, bool)
+ self.deviceslist = Gtk.ListStore(str, str, int, int, int, bool)
def show_no_devices(self):
if self.frame:
@@ -176,14 +181,36 @@ class AdaptersPage(BasePage):
success, info = gnomedvb.get_adapter_info(dev.adapter,
dev.frontend)
if success:
- dev.name = info["name"]
- dev.type = info["type"]
- if info["type"] in DVB_TYPE_TO_DESC:
- dev.type_name = DVB_TYPE_TO_DESC[info["type"]]
- else:
- dev.type_name = info["type"]
- dev.registered = False
- unregistered.add(dev)
+ if info["type_t"]:
+ dev_t = copy.copy(dev)
+ dev_t.name = info["name"]
+ dev_t.type = GROUP_TERRESTRIAL
+ if dev_t.type in DVB_TYPE_TO_DESC:
+ dev_t.type_name = DVB_TYPE_TO_DESC[dev_t.type]
+ else:
+ dev_t.type_name = "Unknown"
+ dev_t.registered = False
+ unregistered.add(dev_t)
+ if info["type_s"]:
+ dev_s = copy.copy(dev)
+ dev_s.name = info["name"]
+ dev_s.type = GROUP_SATELLITE
+ if dev_s.type in DVB_TYPE_TO_DESC:
+ dev_s.type_name = DVB_TYPE_TO_DESC[dev_s.type]
+ else:
+ dev_s.type_name = "Unknown"
+ dev_s.registered = False
+ unregistered.add(dev_s)
+ if info["type_c"]:
+ dev_c = copy.copy(dev)
+ dev_c.name = info["name"]
+ dev_c.type = GROUP_CABLE
+ if dev_c.type in DVB_TYPE_TO_DESC:
+ dev_c.type_name = DVB_TYPE_TO_DESC[dev_c.type]
+ else:
+ dev_c.type_name = "Unknown"
+ dev_c.registered = False
+ unregistered.add(dev_c)
else:
error = info
diff --git a/client/gnomedvb/ui/wizard/pages/ChannelScanPage.py
b/client/gnomedvb/ui/wizard/pages/ChannelScanPage.py
index b49a17d..06619a7 100644
--- a/client/gnomedvb/ui/wizard/pages/ChannelScanPage.py
+++ b/client/gnomedvb/ui/wizard/pages/ChannelScanPage.py
@@ -163,14 +163,14 @@ class ChannelScanPage(BasePage):
def get_selected_channel_sids(self):
return [row[self.COL_SID] for row in self.tvchannels if row[self.COL_ACTIVE]]
- def start_scanning(self, adapter, frontend, tuning_data):
+ def start_scanning(self, adapter, frontend, type, tuning_data):
def data_loaded(proxy, success, user_data):
if success:
self._scanner.run()
else:
self._scanner.destroy()
- self._scanner = self._model.get_scanner_for_device(adapter, frontend)
+ self._scanner = self._model.get_scanner_for_device(adapter, frontend, type)
if self._scanner == None:
return
diff --git a/client/gnomedvb/ui/wizard/pages/InitialTuningDataPage.py
b/client/gnomedvb/ui/wizard/pages/InitialTuningDataPage.py
index 536d64a..3eeafbb 100644
--- a/client/gnomedvb/ui/wizard/pages/InitialTuningDataPage.py
+++ b/client/gnomedvb/ui/wizard/pages/InitialTuningDataPage.py
@@ -26,11 +26,11 @@ import gettext
import locale
from gnomedvb import _
from gnomedvb.ui.wizard.pages.BasePage import BasePage
+from gnomedvb import GROUP_TERRESTRIAL
+from gnomedvb import GROUP_SATELLITE
+from gnomedvb import GROUP_CABLE
-DVB_APPS_DIRS = ("/usr/share/dvb",
- "/usr/share/dvb-apps",
- "/usr/share/dvb-apps/scan",
- "/usr/share/doc/dvb-utils/examples/scan")
+DVB_APPS_DIRS = ("/usr/share/dvb-v5",)
COUNTRIES = {
"ad": "Andorra",
@@ -158,13 +158,13 @@ class InitialTuningDataPage(BasePage):
self.setup_dvb_apps_missing()
return
- if info["type"] == "DVB-T":
+ if info["type"] == GROUP_TERRESTRIAL:
self.setup_dvb_t()
self.__page_title = _("Country and antenna selection")
- elif info["type"] == "DVB-S":
+ elif info["type"] == GROUP_SATELLITE:
self.setup_dvb_s()
self.__page_title = _("Satellite selection")
- elif info["type"] == "DVB-C":
+ elif info["type"] == GROUP_CABLE:
self.setup_dvb_c()
self.__page_title = _("Country and provider selection")
else:
@@ -232,7 +232,7 @@ class InitialTuningDataPage(BasePage):
self.country_combo = Gtk.ComboBox.new_with_model_and_entry(self.countries)
self.country_combo.set_hexpand(True)
self.country_combo.connect('changed', self.on_country_changed)
- self.__data_dir = "dvb-t"
+ self.__data_dir = "terrestrial"
cell = Gtk.CellRendererText()
self.country_combo.pack_start(cell, True)
self.country_combo.set_entry_text_column(0)
@@ -305,7 +305,7 @@ class InitialTuningDataPage(BasePage):
self.country_combo = Gtk.ComboBox.new_with_model_and_entry(self.countries)
self.country_combo.set_hexpand(True)
self.country_combo.connect('changed', self.on_country_changed)
- self.__data_dir = "dvb-c"
+ self.__data_dir = "cable"
cell = Gtk.CellRendererText()
self.country_combo.pack_start(cell, True)
self.country_combo.set_entry_text_column(0)
@@ -373,7 +373,7 @@ class InitialTuningDataPage(BasePage):
def _fill_providers(self, selected_country):
# Only DVB-T has bruteforce scan
- if self.__adapter_info["type"] == "DVB-T":
+ if self.__adapter_info["type"] == GROUP_TERRESTRIAL:
self.providers.append([_("Don't know"), self.NOT_LISTED])
for d in DVB_APPS_DIRS:
@@ -407,8 +407,8 @@ class InitialTuningDataPage(BasePage):
def read_satellites(self):
for d in DVB_APPS_DIRS:
if os.access(d, os.F_OK | os.R_OK):
- for f in os.listdir(os.path.join(d, 'dvb-s')):
- self.satellites.append([f, os.path.join(d, 'dvb-s', f)])
+ for f in os.listdir(os.path.join(d, 'satellite')):
+ self.satellites.append([f, os.path.join(d, 'satellite', f)])
def on_satellite_changed(self, selection):
model, aiter = selection.get_selected()
@@ -428,27 +428,22 @@ class InitialTuningDataPage(BasePage):
self.__tuning_data = []
for chan in range(5, 13):
freq = 142500000 + chan * 7000000
- for transmode in ["2k", "8k"]:
- for guard in [0, 32, 16, 8, 4]:
- self.__tuning_data.append(
- self.create_parameters_dict(freq, 7, transmode, guard))
+ self.__tuning_data.append(self.create_parameters_dict(freq, 7))
for chan in range(21, 70):
- freq = 306000000 + chan* 8000000
- for transmode in ["2k", "8k"]:
- for guard in [32, 16, 8, 4]:
- self.__tuning_data.append(
- self.create_parameters_dict(freq, 8, transmode, guard))
+ freq = 306000000 + chan * 8000000
+ self.__tuning_data.append(self.create_parameters_dict(freq, 8))
- def create_parameters_dict(self, freq, bandwidth, transmode, guard):
+ def create_parameters_dict(self, freq, bandwidth):
return {"frequency": GLib.Variant('u', freq),
- "hierarchy": GLib.Variant('u', 4), # AUTO
+ "delsys": GLib.Variant('s', "DVBT"),
+ "hierarchy": GLib.Variant('s', "AUTO"),
"bandwidth": GLib.Variant('u', bandwidth),
- "transmission-mode": GLib.Variant('s', transmode),
- "code-rate-hp": GLib.Variant('s', "NONE"),
+ "transmission-mode": GLib.Variant('s', "QAM/AUTO"),
+ "code-rate-hp": GLib.Variant('s', "AUTO"),
"code-rate-lp": GLib.Variant('s', "AUTO"),
- "constellation": GLib.Variant('s', "QAM64"),
- "guard-interval": GLib.Variant('u', guard)}
+ "constellation": GLib.Variant('s', "AUTO"),
+ "guard-interval": GLib.Variant('s', "AUTO")}
def combobox_sort_func(self, model, iter1, iter2, user_data):
name1, code1 = model[iter1]
diff --git a/client/gnomedvb/ui/wizard/pages/SetupDevicePage.py
b/client/gnomedvb/ui/wizard/pages/SetupDevicePage.py
index 58cddf8..a3e78cc 100644
--- a/client/gnomedvb/ui/wizard/pages/SetupDevicePage.py
+++ b/client/gnomedvb/ui/wizard/pages/SetupDevicePage.py
@@ -117,7 +117,7 @@ class SetupDevicePage(BasePage):
recordings_dir = gnomedvb.get_default_recordings_dir()
name = DVB_TYPE_TO_TV_DESC[self.__adapter_info["type"]]
self.__model.add_device_to_new_group(self.__adapter_info['adapter'],
- self.__adapter_info['frontend'], channels_file,
+ self.__adapter_info['frontend'], self.__adapter_info['type'], channels_file,
recordings_dir, name,
result_handler=result_handler, error_handler=error_handler)
else:
diff --git a/configure.ac b/configure.ac
index 413fc9f..683fa67 100644
--- a/configure.ac
+++ b/configure.ac
@@ -16,7 +16,7 @@ AM_PROG_CC_C_O
LT_PREREQ([2.2.6])
LT_INIT([disable-static])
-AM_PROG_VALAC([0.15.0])
+AM_PROG_VALAC([0.26.0])
AC_SUBST(CFLAGS)
AC_SUBST(CPPFLAGS)
@@ -57,10 +57,11 @@ dnl ******************
dnl * Check for libs
dnl ******************
GLIB_REQUIRED=2.32.0
-GST_REQUIRED=1.0
+GST_REQUIRED=1.4.0
GEE_REQUIRED=0.8.0
SQLITE_REQUIRED=3.4
-GST_RTSP_SERVER_REQUIRED=0.11.90
+GST_RTSP_SERVER_REQUIRED=1.4.0
+GST_MPEGTS_REQUIRED=1.4.0
PKG_CHECK_MODULES(GST, gstreamer-1.0 >= $GST_REQUIRED
gstreamer-rtsp-1.0 >= $GST_REQUIRED)
@@ -72,7 +73,8 @@ PKG_CHECK_MODULES(GNOME_DVB_DAEMON, glib-2.0 >= $GLIB_REQUIRED
gobject-2.0 >= $GLIB_REQUIRED
gee-0.8 >= $GEE_REQUIRED
sqlite3 >= $SQLITE_REQUIRED
- gstreamer-rtsp-server-1.0 >= $GST_RTSP_SERVER_REQUIRED)
+ gstreamer-rtsp-server-1.0 >= $GST_RTSP_SERVER_REQUIRED
+ gstreamer-mpegts-1.0 >= $GST_MPEGTS_REQUIRED)
AC_SUBST(GNOME_DVB_DAEMON_CFLAGS)
AC_SUBST(GNOME_DVB_DAEMON_LIBS)
@@ -97,7 +99,7 @@ AC_ARG_ENABLE([totem-plugin],
AS_HELP_STRING([--enable-totem-plugin], [Install the Totem plugin (default: no)]),
[enable_totem=$enableval],
[enable_totem=no])
-
+
AM_CONDITIONAL(ENABLE_TOTEM, test "x$enable_totem" = "xyes")
AC_ARG_WITH([totem-plugin-dir],
@@ -111,8 +113,8 @@ if test "x$enable_totem" = "xyes"; then
AC_MSG_ERROR(
[
- *** Could not determinate totem plugin directory.
-
+ *** Could not determinate totem plugin directory.
+
Please make sure totem is installed or set the directory
manually using --with-totem-plugin-dir
])
diff --git a/src/Channel.vala b/src/Channel.vala
index f5fd1cf..13c7b5a 100644
--- a/src/Channel.vala
+++ b/src/Channel.vala
@@ -18,10 +18,11 @@
*/
using GLib;
+using GstMpegTs;
namespace DVB {
- public abstract class Channel : GLib.Object {
+ public class Channel : GLib.Object {
public uint Sid {
get { return this.sid; }
@@ -33,14 +34,16 @@ namespace DVB {
}
}
}
+ /* delivery system depending settings */
+ public Parameter Param { get; set; }
public uint GroupId {get; construct;}
public string Name {get; set;}
+ public DVBServiceType ServiceType { get; set; }
public uint TransportStreamId {get; set;}
public string Network {get; set;}
public uint? LogicalChannelNumber {get; set;}
public uint VideoPID {get; set;}
public Gee.List<uint> AudioPIDs {get; set;}
- public uint Frequency {get; set;}
public bool Scrambled {get; set;}
public DVB.Schedule Schedule {
get { return this.schedule; }
@@ -88,8 +91,8 @@ namespace DVB {
return (this.VideoPID == 0);
}
- public virtual bool is_valid () {
- return (this.Name != null && this.Frequency != 0&& this.Sid != 0
+ public bool is_valid () {
+ return (this.Name != null && this.Param.Frequency != 0 && this.Sid != 0
&& (this.VideoPID != 0 || this.AudioPIDs.size != 0));
}
@@ -100,14 +103,15 @@ namespace DVB {
* Channels that are part of the same TS can be viewed/recorded
* at the same time with a single device.
*/
- public virtual bool on_same_transport_stream (Channel channel) {
- return (this.Frequency == channel.Frequency);
+ public bool on_same_transport_stream (Channel channel) {
+ // return (this.TransportStreamId == channel.TransportStreamId);
+ return (this.Param.Frequency == channel.Param.Frequency);
}
/**
* @returns: TRUE of both channels are identical
*/
- public virtual bool equals (Channel channel) {
+ public bool equals (Channel channel) {
return (this.sid == channel.Sid);
}
@@ -116,8 +120,14 @@ namespace DVB {
*
* Set properties of source so that the channel can be watched
*/
- public abstract void setup_dvb_source (Gst.Element source);
- public abstract string to_string ();
+ public void setup_dvb_source (Gst.Element source) {
+ this.Param.prepare (source);
+ }
+
+ public string to_string () {
+ return this.Param.to_string () + ":%s:%s:%u:%u:%s".printf(this.Name,
+ this.Network, this.Sid, this.VideoPID, get_audio_pids_string ());
+ }
}
}
diff --git a/src/ChannelFactory.vala b/src/ChannelFactory.vala
index d666df3..10bf0a4 100644
--- a/src/ChannelFactory.vala
+++ b/src/ChannelFactory.vala
@@ -20,6 +20,7 @@ using GLib;
using Gee;
using Gst;
using DVB.Logging;
+using GstMpegTs;
namespace DVB {
@@ -49,12 +50,13 @@ namespace DVB {
/**
* Emitted when we came across EIT table
*/
- public signal void eit_structure (Gst.Structure structure);
+ public signal void eit_structure (Section section);
// List of channels that are currently in use
public HashSet<Channel> active_channels {get; construct;}
// The device in use
public Device device {get; construct;}
+ public DeviceGroup group {get; construct;}
// Whether watching one of the channels was forced
public bool forced {
get {
@@ -86,9 +88,10 @@ namespace DVB {
/**
* @device: The device to use
* @epgscanner: #EPGScanner to forward EIT to
+ * @group: #DeviceGroup
*/
- public PlayerThread (Device device, EPGScanner? epgscanner) {
- base (device: device);
+ public PlayerThread (Device device, EPGScanner? epgscanner, DeviceGroup group) {
+ base (device: device, group: group);
this.epgscanner = epgscanner;
}
@@ -129,7 +132,6 @@ namespace DVB {
log.error ("Could not create dvbbasebin element");
return null;
}
- this.dvbbasebin.pad_added.connect (this.on_dvbbasebin_pad_added);
channel.setup_dvb_source (this.dvbbasebin);
@@ -144,11 +146,15 @@ namespace DVB {
this.add_element (tee);
bin = this.add_sink_bin (sink_element);
+ if (bin == null)
+ log.error ("no bin");
if (!tee.link (bin)) {
log.error ("Could not link tee and bin");
return null;
}
+ this.link_tee_pad (this.dvbbasebin, tee);
+
create_channel = true;
} else {
@@ -268,7 +274,7 @@ namespace DVB {
foreach (Gst.Element sink_bin in celems.sinks) {
Gst.Iterator it = ((Gst.Bin)sink_bin).iterate_elements ();
GLib.Value elem;
- if (it.find_custom<Gst.Element> (find_element, out elem, sink)) {
+ if (it.find_custom ((GLib.CompareFunc)find_element, out elem, sink)) {
result = sink_bin;
break;
}
@@ -424,7 +430,7 @@ namespace DVB {
lock (this.elements_map) {
foreach (ChannelElements celems in this.elements_map.values) {
if (celems.notify_func != null) {
- Channel channel = this.device.Channels.get_channel (
+ Channel channel = this.group.Channels.get_channel (
celems.sid);
celems.notify_func (channel);
}
@@ -458,41 +464,22 @@ namespace DVB {
return true;
}
+
/**
* Link program_%d pad with tee
*/
- private void on_dvbbasebin_pad_added (Gst.Element elem, Gst.Pad pad) {
- string pad_name = pad.get_name();
- log.debug ("Pad %s added", pad_name);
-
- if (!pad_name.has_prefix ("program_"))
- return;
-
- uint sid;
- pad_name.scanf("program_%u", out sid);
-
- log.debug ("SID is '%u'", sid);
- // Check if we're interested in the pad
- lock (this.elements_map) {
- if (this.elements_map.has_key (sid)) {
- Element? sink = this.elements_map.get (sid).tee;
- if (sink == null) {
- log.error ("Could not find sink for SID %u", sid);
- return;
- }
-
- log.debug ("Linking elements %s and %s", elem.get_name(), sink.get_name ());
- Pad sinkpad = sink.get_static_pad ("sink");
-
- PadLinkReturn rc = pad.link (sinkpad);
- if (rc != PadLinkReturn.OK) {
- log.error ("Could not link pads %s and %s", pad.get_name (),
- sinkpad.get_name ());
- } else {
- log.debug ("Src pad %s linked with sink pad %s",
- pad.get_name (), sinkpad.get_name ());
- }
- }
+ private void link_tee_pad (Gst.Element dvbbasebin, Gst.Element tee) {
+ log.debug ("link_tee_pad");
+
+ log.debug ("Linking elements %s and %s", dvbbasebin.get_name(), tee.get_name ());
+ Pad srcpad = dvbbasebin.get_static_pad ("src");
+ Pad sinkpad = tee.get_static_pad ("sink");
+
+ PadLinkReturn rc = srcpad.link (sinkpad);
+ if (rc != PadLinkReturn.OK) {
+ log.error ("Could not link pads %s and %s", srcpad.get_name (), sinkpad.get_name ());
+ } else {
+ log.debug ("Src pad %s linked with sink pad %s", srcpad.get_name (), sinkpad.get_name ());
}
}
@@ -503,11 +490,14 @@ namespace DVB {
unowned Gst.Structure structure = message.get_structure ();
switch (message.type) {
case Gst.MessageType.ELEMENT:
- string structure_name = structure.get_name ();
- if (structure_name == "eit") {
- if (this.epgscanner != null)
- this.epgscanner.on_eit_structure (structure);
- this.eit_structure (structure);
+ Section section = message_parse_mpegts_section(message);
+
+ if (section != null) {
+ if (section.section_type == SectionType.EIT) {
+ if (this.epgscanner != null)
+ this.epgscanner.on_eit_structure (section);
+ this.eit_structure (section);
+ }
}
break;
case Gst.MessageType.WARNING:
@@ -653,7 +643,7 @@ namespace DVB {
* @returns: a new #PlayerThread instance for @device
*/
public virtual PlayerThread create_player (Device device) {
- return new PlayerThread (device, this.device_group.epgscanner);
+ return new PlayerThread (device, this.device_group.epgscanner, this.device_group);
}
}
diff --git a/src/ChannelList.vala b/src/ChannelList.vala
index 43a6673..b3d21b1 100644
--- a/src/ChannelList.vala
+++ b/src/ChannelList.vala
@@ -94,8 +94,8 @@ namespace DVB {
}
public void load (AdapterType type) throws Error {
- var reader = new DVB.io.ChannelListReader (this, type);
- reader.read_into ();
+ var reader = new DVB.io.ChannelListReader (this, type);
+ reader.read_into ();
}
/**
@@ -267,11 +267,11 @@ namespace DVB {
return channels;
}
- /**
+ /**
* @channel_group_id: ID of the ChannelGroup
* @returns: TRUE on success
*/
- public bool GetChannelsOfGroup (int channel_group_id,
+ public bool GetChannelsOfGroup (int channel_group_id,
out uint[] channel_ids) throws DBusError
{
ConfigStore config = new Factory().get_config_store ();
@@ -293,12 +293,12 @@ namespace DVB {
return true;
}
- /**
+ /**
* @channel_id: ID of channel
- * @channel_group_id: ID of the ChannelGroup
+ * @channel_group_id: ID of the ChannelGroup
* @returns: TRUE on success
*/
- public bool AddChannelToGroup (uint channel_id, int channel_group_id)
+ public bool AddChannelToGroup (uint channel_id, int channel_group_id)
throws DBusError
{
ConfigStore config = new Factory().get_config_store ();
@@ -316,12 +316,12 @@ namespace DVB {
return ret;
}
- /**
- * @channel_id: ID of channel
- * @channel_group_id: ID of the ChannelGroup
+ /**
+ * @channel_id: ID of channel
+ * @channel_group_id: ID of the ChannelGroup
* @returns: TRUE on success
*/
- public bool RemoveChannelFromGroup (uint channel_id,
+ public bool RemoveChannelFromGroup (uint channel_id,
int channel_group_id) throws DBusError
{
ConfigStore config = new Factory().get_config_store ();
diff --git a/src/Device.vala b/src/Device.vala
index f7b17b1..d10e015 100644
--- a/src/Device.vala
+++ b/src/Device.vala
@@ -19,19 +19,20 @@
using GLib;
using Gst;
+using Gee;
using DVB.Logging;
namespace DVB {
public errordomain DeviceError {
- UNKNOWN_TYPE
+ UNKNOWN_TYPE
}
public enum AdapterType {
UNKNOWN,
- DVB_T,
- DVB_S,
- DVB_C
+ TERRESTRIAL,
+ SATELLITE,
+ CABLE
}
public class Device : GLib.Object {
@@ -42,67 +43,57 @@ namespace DVB {
public uint Adapter { get; construct; }
public uint Frontend { get; construct; }
- public AdapterType Type {
- get { return adapter_type; }
- }
- public string Name {
- get { return adapter_name; }
- }
- public ChannelList Channels { get; set; }
- public File RecordingsDirectory { get; set; }
-
- private string adapter_name;
- private AdapterType adapter_type;
-
- public Device (uint adapter, uint frontend) {
- base (Adapter: adapter, Frontend: frontend);
- }
- public static Device new_set_type (uint adapter, uint frontend,
- File channels_conf, File recordings_dir, string name, AdapterType type) {
- Device dev = new Device (adapter, frontend);
- dev.adapter_name = name;
- dev.adapter_type = type;
- dev.RecordingsDirectory = recordings_dir;
- dev.Channels = new ChannelList (channels_conf);
+ /* Device Path i.e. /dev/dvb/adapter0/frontend0 */
+ public string DevFile { get; private set; }
- return dev;
- }
+ /* unified ID */
+ public string UID { get; private set; }
- public static Device new_with_type (uint adapter, uint frontend) {
- var device = new Device (adapter, frontend);
+ public string Name { get; private set; }
- device.setAdapterTypeAndName(adapter, frontend);
+ private ArrayList<DvbSrcDelsys> delsys;
- return device;
+ public Device (uint adapter, uint frontend) {
+ base (Adapter: adapter, Frontend: frontend);
+ setAdapterTypeAndName(adapter, frontend);
}
- public static Device? new_full (uint adapter, uint frontend,
- File channels_conf, File recordings_dir)
- throws DeviceError
- {
- Device device = Device.new_with_type (adapter, frontend);
-
- /* The type of the device is checked in creation of
- * Device class. If the device does not exist the type
- * will be AdapterType.UNKNOWN
- */
- if (device.Type == AdapterType.UNKNOWN)
- throw new DeviceError.UNKNOWN_TYPE (
- "device %u,%u has unknown type", adapter, frontend);
-
- device.RecordingsDirectory = recordings_dir;
-
- device.Channels = new ChannelList (channels_conf);
-
- return device;
+ public Device.with_udev (GUdev.Device device, string dev_file,
+ uint adapter, uint frontend) {
+ base(Adapter: adapter, Frontend: frontend);
+ setAdapterTypeAndName(adapter, frontend);
+
+ GUdev.Device parent = device.get_parent ();
+ string name = this.Name;
+
+ string tmp = parent.get_property ("ID_MODEL_FROM_DATABASE");
+ tmp += ": " + name;
+ this.Name = tmp;
+ log.debug("Adding Device: %s", tmp);
+ this.DevFile = dev_file;
+
+ /* Generating UID */
+ if (parent.get_subsystem () == "pci") {
+ /* UID from PCI */
+ string uid = parent.get_property("PCI_SLOT_NAME");
+ uid += ":" + parent.get_property("PCI_SUBSYS_ID");
+ uid += ":" + name;
+ log.debug("UID: %s", uid);
+ this.UID = uid;
+ } else if (parent.get_subsystem () == "usb") {
+ string uid = parent.get_property("ID_SERIAL");
+ uid += ":" + name;
+ log.debug("UID: %s", uid);
+ this.UID = uid;
+ }
}
public static bool equal (Device dev1, Device dev2) {
if (dev1 == null || dev2 == null) return false;
return (dev1.Adapter == dev2.Adapter
- && dev2.Frontend == dev2.Frontend);
+ && dev1.Frontend == dev2.Frontend);
}
public static uint hash (Device device) {
@@ -115,6 +106,109 @@ namespace DVB {
return 2 * PRIME + PRIME * adapter + frontend;
}
+ public bool isTerrestrial () {
+ foreach (DvbSrcDelsys delsys in this.delsys) {
+ switch (delsys) {
+ case DvbSrcDelsys.SYS_DVBT:
+ case DvbSrcDelsys.SYS_DVBT2:
+ case DvbSrcDelsys.SYS_DVBH:
+ case DvbSrcDelsys.SYS_ATSC:
+ case DvbSrcDelsys.SYS_ATSCMH:
+ case DvbSrcDelsys.SYS_ISDBT:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+ }
+
+ public bool isCable () {
+ foreach (DvbSrcDelsys delsys in this.delsys) {
+ switch (delsys) {
+ case DvbSrcDelsys.SYS_DVBC_ANNEX_A:
+ case DvbSrcDelsys.SYS_DVBC_ANNEX_B:
+ case DvbSrcDelsys.SYS_DVBC_ANNEX_C:
+ case DvbSrcDelsys.SYS_ISDBC:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+ }
+
+ public bool isSatellite () {
+ bool ret = false;
+ foreach (DvbSrcDelsys delsys in this.delsys) {
+ switch (delsys) {
+ case DvbSrcDelsys.SYS_DVBS:
+ case DvbSrcDelsys.SYS_DVBS2:
+ case DvbSrcDelsys.SYS_ISDBS:
+ case DvbSrcDelsys.SYS_DSS:
+ case DvbSrcDelsys.SYS_TURBO:
+ return true;
+ default:
+ break;
+ }
+ }
+ return ret;
+ }
+
+ public bool isDVB () {
+ foreach (DvbSrcDelsys delsys in this.delsys) {
+ switch (delsys) {
+ case DvbSrcDelsys.SYS_DVBT:
+ case DvbSrcDelsys.SYS_DVBT2:
+ case DvbSrcDelsys.SYS_DVBS:
+ case DvbSrcDelsys.SYS_DVBS2:
+ case DvbSrcDelsys.SYS_DVBC_ANNEX_A:
+ case DvbSrcDelsys.SYS_DVBC_ANNEX_C:
+ case DvbSrcDelsys.SYS_DVBH:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+ }
+
+ public bool isATSC () {
+ foreach (DvbSrcDelsys delsys in this.delsys) {
+ switch (delsys) {
+ case DvbSrcDelsys.SYS_DVBC_ANNEX_B:
+ case DvbSrcDelsys.SYS_ATSC:
+ case DvbSrcDelsys.SYS_ATSCMH:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+ }
+
+ public bool isISDB () {
+ foreach (DvbSrcDelsys delsys in this.delsys) {
+ switch (delsys) {
+ case DvbSrcDelsys.SYS_ISDBT:
+ case DvbSrcDelsys.SYS_ISDBC:
+ case DvbSrcDelsys.SYS_ISDBS:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+ }
+
+ public bool isDelsys (DvbSrcDelsys delsys) {
+ foreach (DvbSrcDelsys d in this.delsys) {
+ if (d == delsys)
+ return true;
+ }
+ return false;
+ }
+
public bool is_busy () {
Element dvbsrc = ElementFactory.make ("dvbsrc", "text_dvbsrc");
if (dvbsrc == null) {
@@ -157,6 +251,7 @@ namespace DVB {
log.error ("Could not create dvbsrc element");
return false;
}
+
dvbsrc.set ("adapter", adapter);
dvbsrc.set ("frontend", frontend);
@@ -167,7 +262,7 @@ namespace DVB {
Gst.Bus bus = pipeline.get_bus();
bool success = false;
- string adapter_type = null;
+ this.delsys = new ArrayList<DvbSrcDelsys> ();
while (bus.have_pending()) {
Message msg = bus.pop();
@@ -176,8 +271,63 @@ namespace DVB {
weak Structure structure = msg.get_structure ();
if (structure.get_name() == "dvb-adapter") {
- adapter_type = "%s".printf (structure.get_string("type"));
- this.adapter_name = "%s".printf (structure.get_string("name"));
+
+ this.Name = "%s".printf (structure.get_string("name"));
+
+ if (structure.has_field("dvb-c-a"))
+ this.delsys.add (DvbSrcDelsys.SYS_DVBC_ANNEX_A);
+
+ if (structure.has_field("dvb-c-b"))
+ this.delsys.add (DvbSrcDelsys.SYS_DVBC_ANNEX_B);
+
+ if (structure.has_field("dvb-t"))
+ this.delsys.add (DvbSrcDelsys.SYS_DVBT);
+
+ if (structure.has_field("dss"))
+ this.delsys.add (DvbSrcDelsys.SYS_DSS);
+
+ if (structure.has_field("dvb-s"))
+ this.delsys.add (DvbSrcDelsys.SYS_DVBS);
+
+ if (structure.has_field("dvb-s2"))
+ this.delsys.add (DvbSrcDelsys.SYS_DVBS2);
+
+ if (structure.has_field("dvb-h"))
+ this.delsys.add (DvbSrcDelsys.SYS_DVBH);
+
+ if (structure.has_field("isdb-t"))
+ this.delsys.add (DvbSrcDelsys.SYS_ISDBT);
+
+ if (structure.has_field("isdb-s"))
+ this.delsys.add (DvbSrcDelsys.SYS_ISDBS);
+
+ if (structure.has_field("isdb-c"))
+ this.delsys.add (DvbSrcDelsys.SYS_ISDBC);
+
+ if (structure.has_field("atsc"))
+ this.delsys.add (DvbSrcDelsys.SYS_ATSC);
+
+ if (structure.has_field("atsc-mh"))
+ this.delsys.add (DvbSrcDelsys.SYS_ATSCMH);
+
+ if (structure.has_field("dtmb"))
+ this.delsys.add (DvbSrcDelsys.SYS_DTMB);
+
+ if (structure.has_field("cmmb"))
+ this.delsys.add (DvbSrcDelsys.SYS_CMMB);
+
+ if (structure.has_field("dab"))
+ this.delsys.add (DvbSrcDelsys.SYS_DAB);
+
+ if (structure.has_field("dvb-t2"))
+ this.delsys.add (DvbSrcDelsys.SYS_DVBT2);
+
+ if (structure.has_field("turbo"))
+ this.delsys.add (DvbSrcDelsys.SYS_TURBO);
+
+ if (structure.has_field("dvb-c-c"))
+ this.delsys.add (DvbSrcDelsys.SYS_DVBC_ANNEX_C);
+
success = true;
break;
}
@@ -191,22 +341,7 @@ namespace DVB {
pipeline.set_state(State.NULL);
- this.adapter_type = get_type_from_string (adapter_type);
-
return success;
}
-
- public static AdapterType get_type_from_string (string? adapter_type) {
- if (adapter_type == null)
- return AdapterType.UNKNOWN;
-
- AdapterType type;
- if (adapter_type == "DVB-T") type = AdapterType.DVB_T;
- else if (adapter_type == "DVB-S") type = AdapterType.DVB_S;
- else if (adapter_type == "DVB-C") type = AdapterType.DVB_C;
- else type = AdapterType.UNKNOWN;
- return type;
- }
}
-
}
diff --git a/src/DeviceGroup.vala b/src/DeviceGroup.vala
index 91c844f..072a4a8 100644
--- a/src/DeviceGroup.vala
+++ b/src/DeviceGroup.vala
@@ -35,20 +35,15 @@ namespace DVB {
public int size {
get { return this.devices.size; }
}
- public uint Id {get; construct;}
- public ChannelList Channels {
- get { return this.reference_device.Channels; }
- }
- public File RecordingsDirectory {
- get { return this.reference_device.RecordingsDirectory; }
- set {
- this.reference_device.RecordingsDirectory = value;
- this.update_all_devices ();
- }
- }
- public AdapterType Type {
- get { return this.reference_device.Type; }
+ public Set<Device> Devices {
+ get { return this.devices; }
}
+ public uint Id {get; construct;}
+ public ChannelList Channels { get; construct; }
+ public File RecordingsDirectory { get; set; }
+
+ public AdapterType Type { get; construct; }
+
public Recorder recorder {
get { return this._recorder; }
}
@@ -60,12 +55,6 @@ namespace DVB {
}
public string Name {get; set;}
- // All settings are copied from this one
- public Device reference_device {
- get;
- construct set;
- }
-
private Set<Device> devices;
private Recorder _recorder;
private EPGScanner? _epgscanner;
@@ -79,21 +68,20 @@ namespace DVB {
this.schedules = new HashSet<string> (
Gee.Functions.get_hash_func_for(typeof(string)),
Gee.Functions.get_equal_func_for(typeof(string)));
- this.devices.add (this.reference_device);
this._channelfactory = new ChannelFactory (this);
this._recorder = new Recorder (this);
}
/**
* @id: ID of group
- * @reference_device: All devices of this group will inherit
- * the settings from this device
+ * @channels_conf: the channel list file name (dvbv5 format)
+ * @recordings_dir: directory in which the records are saved
+ * @type: the type of this group (terrestrial, cable, satellite)
* @with_epg_scanner: Whether to provide an EPG scanner
*/
- public DeviceGroup (uint id, Device reference_device,
+ public DeviceGroup (uint id, File channels_conf, File recordings_dir, AdapterType type,
bool with_epg_scanner=true) {
- Object (Id: id, reference_device: reference_device);
- this.reference_device.Channels.GroupId = id;
+ Object (Id: id, Channels: new ChannelList (channels_conf), RecordingsDirectory: recordings_dir,
Type: type);
if (with_epg_scanner) {
this._epgscanner = new EPGScanner (this);
@@ -126,47 +114,38 @@ namespace DVB {
}
/**
- * @adapter: Number of the device's adapter
- * @frontend: Number of the device's frontend
- *
- * Creates a new device first and adds it to the group.
- * The new device inherits the settings from the reference
- * device.
- */
- public void create_and_add_device (uint adapter, uint frontend) {
- Device new_dev = Device.new_with_type (adapter, frontend);
- this.add (new_dev);
- }
-
- /**
* Add device to group. The device's settings will be overridden
* with those of the reference device.
*/
public bool add (Device device) {
- if (device.Type != this.Type) {
- warning ("Cannot add device, because it is not of same type");
- return false;
+ switch (this.Type) {
+ case AdapterType.TERRESTRIAL:
+ if (!device.isTerrestrial ()) {
+ warning ("Cannot add device, because it is not of same type");
+ return false;
+ }
+ break;
+ case AdapterType.SATELLITE:
+ if (!device.isSatellite ()) {
+ warning ("Cannot add device, because it is not of same type");
+ return false;
+ }
+ break;
+ case AdapterType.CABLE:
+ if (!device.isCable ()) {
+ warning ("Cannot add device, because it is not of same type");
+ return false;
+ }
+ break;
}
bool result;
lock (this.devices) {
- // Set settings from reference device
- device.Channels = this.reference_device.Channels;
- device.RecordingsDirectory = this.reference_device.RecordingsDirectory;
-
result = this.devices.add (device);
}
return result;
}
- public bool add_and_emit (Device device) {
- if (this.add (device)) {
- this.device_added (device.Adapter, device.Frontend);
- return true;
- }
- return false;
- }
-
public bool contains (Device device) {
bool result;
lock (this.devices) {
@@ -179,25 +158,10 @@ namespace DVB {
bool result;
lock (this.devices) {
result = this.devices.remove (device);
- if (Device.equal (device, this.reference_device)) {
- foreach (Device dev in this.devices) {
- log.debug ("Assigning new reference device");
- this.reference_device = dev;
- break;
- }
- }
}
return result;
}
- public bool remove_and_emit (Device device) {
- if (this.remove (device)) {
- this.device_removed (device.Adapter, device.Frontend);
- return true;
- }
- return false;
- }
-
/**
* Get first device that isn't busy.
* If all devices are busy NULL is returned.
@@ -220,15 +184,8 @@ namespace DVB {
* @returns: Name of adapter type the group holds
* or an empty string when group with given id doesn't exist.
*/
- public string GetType () throws DBusError {
- string type_str;
- switch (this.Type) {
- case AdapterType.DVB_T: type_str = "DVB-T"; break;
- case AdapterType.DVB_S: type_str = "DVB-S"; break;
- case AdapterType.DVB_C: type_str = "DVB-C"; break;
- default: type_str = ""; break;
- }
- return type_str;
+ public AdapterType GetType () throws DBusError {
+ return this.Type;
}
/**
@@ -244,20 +201,20 @@ namespace DVB {
// When the device is already registered we
// might see some errors if the device is
// currently in use
- Device device = Device.new_with_type (adapter, frontend);
+ Manager manager = Manager.get_instance ();
+
+ Device device = manager.get_device (adapter, frontend);
if (device == null) return false;
- Manager manager = Manager.get_instance ();
- if (manager.device_is_in_any_group (device)) {
+ if (manager.device_is_in_any_group (device, this.Type)) {
log.debug ("Device with adapter %u, frontend %u is" +
"already part of a group", adapter, frontend);
return false;
}
- uint group_id = this.Id;
log.debug ("Adding device with adapter %u, frontend %u to group %u",
- adapter, frontend, group_id);
+ adapter, frontend, this.Id);
if (this.add (device)) {
try {
@@ -308,7 +265,11 @@ namespace DVB {
* no devices after the removal it's removed as well.
*/
public bool RemoveDevice (uint adapter, uint frontend) throws DBusError {
- Device dev = new Device (adapter, frontend);
+ Manager m = Manager.get_instance ();
+
+ Device dev = m.get_device (adapter, frontend);
+
+ if (dev == null) return false;
if (this.contains (dev)) {
if (this.remove (dev)) {
@@ -460,20 +421,6 @@ namespace DVB {
return this.devices.iterator().foreach(f);
}
- /**
- * Set RecordingsDirectory property of all
- * devices to the values of the reference device
- */
- private void update_all_devices () {
- lock (this.devices) {
- foreach (Device device in this.devices) {
- if (device != this.reference_device) {
- device.RecordingsDirectory = this.reference_device.RecordingsDirectory;
- }
- }
- }
- }
-
}
}
diff --git a/src/EPGScanner.vala b/src/EPGScanner.vala
index a471bd2..bea9ca5 100644
--- a/src/EPGScanner.vala
+++ b/src/EPGScanner.vala
@@ -20,6 +20,7 @@
using GLib;
using Gee;
using DVB.Logging;
+using GstMpegTs;
namespace DVB {
@@ -36,7 +37,7 @@ namespace DVB {
private static const string PIPELINE_TEMPLATE =
"dvbsrc name=dvbsrc adapter=%u frontend=%u pids=0:16:17:18 stats-reporting-interval=0 ! tsparse !
fakesink silent=true";
- private unowned DVB.DeviceGroup DeviceGroup;
+ private DVB.DeviceGroup DeviceGroup;
private Gst.Element? pipeline;
private GLib.Queue<Channel> channels;
@@ -148,7 +149,7 @@ namespace DVB {
// clear doesn't unref for us so we do this instead
Channel c;
while ((c = this.channels.pop_head ()) != null) {
- // Vala unref's Channel instances for us
+ // Vala unref's Channel instances for us
}
this.channels.clear ();
this.channel_events.clear ();
@@ -191,9 +192,13 @@ namespace DVB {
* Scan the next frequency for EPG data
*/
private bool scan_new_frequency () {
+ ChannelList clist = this.DeviceGroup.Channels;
+ if (clist == null)
+ return false;
+
lock (this.channel_events) {
foreach (uint sid in this.channel_events.keys) {
- Channel channel = this.DeviceGroup.Channels.get_channel (sid);
+ Channel channel = clist.get_channel (sid);
if (channel == null) {
warning ("Could not find channel %u for this device", sid);
continue;
@@ -238,14 +243,17 @@ namespace DVB {
private bool bus_watch_func (Gst.Bus bus, Gst.Message message) {
switch (message.type) {
case Gst.MessageType.ELEMENT:
- unowned Gst.Structure structure = message.get_structure ();
- if (structure.get_name() == "dvb-read-failure") {
- log.warning ("Could not read from DVB device");
- } else if (structure.get_name() == "eit") {
- this.on_eit_structure (structure);
+ Section section = message_parse_mpegts_section (message);
+
+ if (section == null) {
+ unowned Gst.Structure structure = message.get_structure ();
+ if (structure.get_name() == "dvb-read-failure") {
+ log.warning ("Could not read from DVB device");
+ }
+ } else if (section.section_type == SectionType.EIT) {
+ this.on_eit_structure (section);
}
- break;
-
+ break;
case Gst.MessageType.ERROR:
Error gerror;
string debug;
@@ -265,107 +273,248 @@ namespace DVB {
return true;
}
- public void on_eit_structure (Gst.Structure structure) {
- Value events = structure.get_value ("events");
+ public void on_eit_structure (Section section) {
- if (!events.holds (typeof(Gst.ValueList)))
- return;
+ unowned EIT eit = section.get_eit();
- uint size = Gst.ValueList.get_size (events);
- Value val;
- weak Gst.Structure event;
- // Iterate over events
lock (this.channel_events) {
- uint sid = get_uint_val (structure, "service-id");
+ uint sid = section.subtable_extension;
+
if (!this.channel_events.has_key (sid)) {
this.channel_events.set (sid,
new HashSet<Event> (Event.hash, Event.equal));
}
HashSet<Event> list = this.channel_events.get (sid);
- for (uint i=0; i<size; i++) {
- val = Gst.ValueList.get_value (events, i);
- event = Gst.Value.get_structure (val);
-
+ EITEvent event;
+ uint len = eit.events.length;
+ for (uint i = 0; i < len; i++) {
+ event = eit events get(i);
var event_class = new Event ();
- event_class.id = get_uint_val (event, "event-id");
- event_class.year = get_uint_val (event, "year");
- event_class.month = get_uint_val (event, "month");
- event_class.day = get_uint_val (event, "day");
- event_class.hour = get_uint_val (event, "hour");
- event_class.minute = get_uint_val (event, "minute");
- event_class.second = get_uint_val (event, "second");
- event_class.duration = get_uint_val (event, "duration");
+
+ event_class.id = event.event_id;
+ event_class.year = event.start_time.get_year ();
+ event_class.month = event.start_time.get_month ();
+ event_class.day = event.start_time.get_day ();
+ event_class.hour = event.start_time.get_hour ();
+ event_class.minute = event.start_time.get_minute ();
+ event_class.second = event.start_time.get_second ();
+ event_class.duration = event.duration;
if (event_class.has_expired ())
continue;
- event_class.running_status = get_uint_val (event, "running-status");
- string name = event.get_string ("name");
- if (name != null && name.validate ())
- event_class.name = name;
- string desc = event.get_string ("description");
- if (desc != null && desc.validate ())
- event_class.description = desc;
- string ext_desc = event.get_string ("extended-text");
- if (ext_desc != null && ext_desc.validate ())
- event_class.extended_description = ext_desc;
- bool free_ca;
- event.get_boolean ("free-ca-mode", out free_ca);
- event_class.free_ca_mode = free_ca;
-/*
- Value components = event.get_value ("components");
- add_components (components, event_class);
-*/
- //log.debug ("Adding new event: %s", event_class.to_string ());
+ event_class.running_status = event.running_status;
+ event_class.free_ca_mode = event.free_CA_mode;
+
+ Descriptor desc;
+ for (uint j = 0 ;j < event.descriptors.length; j++) {
+ desc = event descriptors get (j);
+
+ switch (desc.tag) {
+ case DVBDescriptorType.SHORT_EVENT:
+ string lang;
+ desc.parse_dvb_short_event ( out lang,
+ out event_class.name,
+ out event_class.description);
+ break;
+ case DVBDescriptorType.EXTENDED_EVENT:
+ var ex_desc = ExtendedEventDescriptor();
+
+ if (!desc.parse_dvb_extended_event (out ex_desc))
+ log.debug ("Failed parse extended Event");
+
+ var builder = new StringBuilder ();
+ if (event_class.extended_description != null)
+ builder.append (event_class.extended_description);
+ builder.append (ex_desc.text);
+ event_class.extended_description = builder.str;
+
+ break;
+ case DVBDescriptorType.COMPONENT:
+ var comp = ComponentDescriptor();
+
+ desc.parse_dvb_component(out comp);
+
+ decode_component (comp, event_class);
+ break;
+ case DVBDescriptorType.CONTENT:
+ GenericArray<Content?> conts;
+
+ desc.parse_dvb_content(out conts);
+ if (conts.length != 0) {
+ for (uint k = 0; k < conts.length; k++) {
+ Content cont = conts get(k);
+ log.debug ("0x%01x, 0x%01x, 0x%02x",
+ cont.content_nibble_1,
+ cont.content_nibble_2,
+ cont.user_byte);
+ }
+ }
+ break;
+ default:
+ log.debug ("Unkown descriptor: 0x%02x",
+ desc.tag);
+ break;
+ }
+
+ }
+ log.debug ("Adding new event: %s", event_class.to_string ());
list.add (event_class);
+
}
}
}
-/*
- private static void add_components (Value components, Event event_class) {
- uint components_len = components.list_get_size ();
-
- Value comp_val;
- weak Gst.Structure component;
- for (uint j=0; j<components_len; j++) {
- comp_val = components.list_get_value (j);
- component = comp_val.get_structure ();
-
- string comp_name = component.get_name ();
- if (comp_name == "audio") {
- var audio = new Event.AudioComponent ();
- audio.type = component.get_string ("type");
-
- event_class.audio_components.append (audio);
- } else if (comp_name == "video") {
- var video = new Event.VideoComponent ();
- bool highdef;
- component.get_boolean ("high-definition", out highdef);
- video.high_definition = highdef;
+ private static void decode_component (ComponentDescriptor comp, Event event_class)
+ {
- video.aspect_ratio = component.get_string ("aspect-ratio");
+ switch (comp.stream_content) {
+ case 0x01:
+ case 0x05:
+ var video = new Event.VideoComponent ();
- int freq;
- component.get_int ("frequency", out freq);
- video.frequency = freq;
+ /* hd flag */
+ switch (comp.component_type) {
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ case 0x10:
+ case 0x80:
+ case 0x81:
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ video.has_hd = true;
+ break;
+ default:
+ video.has_hd = false;
+ break;
+ }
- event_class.video_components.append (video);
- } else if (comp_name == "teletext") {
- var teletext = new Event.TeletextComponent ();
- teletext.type = component.get_string ("type");
+ /* 3d flag */
+ switch (comp.component_type) {
+ case 0x80:
+ case 0x81:
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ video.has_3d = true;
+ break;
+ default:
+ video.has_3d = false;
+ break;
+ }
- event_class.teletext_components.append (teletext);
- }
- }
- }
-*/
- private static uint get_uint_val (Gst.Structure structure, string name) {
- uint val;
- structure.get_uint (name, out val);
- return val;
+ /* aspect radio
+ passible value are
+ 4:3, 16:9, 2.21:1
+ */
+ switch (comp.component_type) {
+ case 0x01:
+ case 0x05:
+ case 0x09:
+ case 0x0d:
+ video.aspect_ratio = "4:3";
+ break;
+ case 0x02:
+ case 0x06:
+ case 0x0a:
+ case 0x0e:
+ video.aspect_ratio = "16:9 with pan";
+ break;
+ case 0x03:
+ case 0x07:
+ case 0x0b:
+ case 0x0f:
+ case 0x80:
+ case 0x81:
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ video.aspect_ratio = "16:9";
+ break;
+ case 0x04:
+ case 0x08:
+ case 0x0c:
+ case 0x10:
+ video.aspect_ratio = "2.21:1";
+ break;
+ default:
+ video.aspect_ratio = "unknown";
+ break;
+ }
+
+ switch (comp.component_type) {
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ case 0x10:
+ case 0x82:
+ case 0x83:
+ video.frequency = 30;
+ break;
+ default:
+ video.frequency = 25;
+ break;
+ }
+ if (comp.stream_content == 0x01)
+ video.content = "MPEG-2";
+ else
+ video.content = "AVC/MVC";
+ video.type = comp.component_type.to_string("0x%02x");
+ video.tag = comp.component_tag;
+ video.text = comp.text;
+ event_class.video_component = video;
+ break;
+ case 0x02:
+ case 0x04:
+ case 0x06:
+ case 0x07:
+ var audio = new Event.AudioComponent ();
+
+ switch (comp.stream_content) {
+ case 0x02:
+ audio.content = "MPEG-1 Layer 2";
+ break;
+ case 0x04:
+ audio.content = "AC-3";
+ break;
+ case 0x06:
+ audio.content = "HE-AAC/HE-AACv2";
+ break;
+ case 0x07:
+ audio.content = "DTS";
+ break;
+ }
+
+ audio.type = comp.component_type.to_string("0x%02x");
+ audio.tag = comp.component_tag;
+ audio.text = comp.text;
+ audio.language = comp.language_code;
+ event_class.audio_components.append (audio);
+ break;
+ case 0x03:
+ var teletext = new Event.TeletextComponent ();
+
+ teletext.type = comp.component_type.to_string("0x%02x");
+ teletext.tag = comp.component_tag;
+ teletext.text = comp.text;
+ event_class.teletext_components.append (teletext);
+ break;
+ default:
+ break;
+ }
}
+
}
}
diff --git a/src/Event.vala b/src/Event.vala
index a2ec453..3273d8c 100644
--- a/src/Event.vala
+++ b/src/Event.vala
@@ -49,12 +49,12 @@ namespace DVB {
public string extended_description;
/* Components */
public SList<AudioComponent> audio_components;
- public SList<VideoComponent> video_components;
+ public VideoComponent video_component;
public SList<TeletextComponent> teletext_components;
public Event () {
this.audio_components = new SList<AudioComponent> ();
- this.video_components = new SList<VideoComponent> ();
+ this.video_component = null;
this.teletext_components = new SList<TeletextComponent> ();
this.year = 0;
@@ -106,8 +106,19 @@ namespace DVB {
+ "Duration: %u\nName: %s\nDescription: %s\n".printf (
this.duration, this.name, this.description);
+ if (this.video_component != null) {
+ text += "Video: HD = %s, 3D = %s, Aspect-Ratio = %s,
".printf(this.video_component.has_hd.to_string(),
+ this.video_component.has_3d.to_string(), this.video_component.aspect_ratio);
+ text += "Frequency = %s Hz, Type = %s\n".printf(this.video_component.frequency.to_string(),
+ this.video_component.type);
+ }
for (int i=0; i<this.audio_components.length (); i++) {
- text += "%s ".printf(this.audio_components.nth_data (i).type);
+ text += "Audio: Type = %s, Text = %s\n".printf(this.audio_components.nth_data (i).type,
this.audio_components.nth_data(i).text);
+ }
+
+ for (int i=0; i<this.teletext_components.length (); i++) {
+ text += "Teletext, VBI, Subpicture: Type = %s, Text =
%s\n".printf(this.teletext_components.nth_data (i).type,
+ this.teletext_components.nth_data (i).text);
}
return text;
}
@@ -206,16 +217,28 @@ namespace DVB {
public class AudioComponent {
public string type;
+ public string language;
+ public uint tag;
+ public string content;
+ public string text;
}
public class VideoComponent {
- public bool high_definition;
+ public bool has_hd;
+ public bool has_3d;
public string aspect_ratio;
public int frequency;
+ public string type;
+ public uint tag;
+ public string content;
+ public string text;
}
public class TeletextComponent {
public string type;
+ public string content;
+ public uint tag;
+ public string text;
}
}
diff --git a/src/Main.vala b/src/Main.vala
index 1c9a8ca..76fb93e 100644
--- a/src/Main.vala
+++ b/src/Main.vala
@@ -54,9 +54,10 @@ namespace Main {
DVB.Utils.dbus_register_object<DVB.IDBusManager> (_conn,
DVB.Constants.DBUS_MANAGER_PATH, manager);
conn = _conn;
- start_recordings_store ();
restore_device_groups ();
+
+ start_recordings_store ();
}
private static void start_recordings_store () {
@@ -101,16 +102,16 @@ namespace Main {
private static bool check_requirements () {
bool val;
- val = check_feature_version ("dvbsrc", 1, 2, 0);
+ val = check_feature_version ("dvbsrc", 1, 3, 1);
if (!val) return false;
- val = check_feature_version ("dvbbasebin", 1, 2, 0);
+ val = check_feature_version ("dvbbasebin", 1, 3, 1);
if (!val) return false;
- val = check_feature_version ("tsparse", 1, 2, 0);
+ val = check_feature_version ("tsparse", 1, 3, 1);
if (!val) return false;
- val = check_feature_version ("rtpmp2tpay", 1, 0, 0);
+ val = check_feature_version ("rtpmp2tpay", 1, 3, 1);
return val;
}
@@ -128,28 +129,25 @@ namespace Main {
uint max_group_id = 0;
log.info ("Restoring %d device groups", device_groups.size);
foreach (DVB.DeviceGroup device_group in device_groups) {
+ // add device to group if device is a member
+ foreach (DVB.Device dev in manager.devs) {
+ log.debug ("restoring device");
+ try {
+ if (config_store.is_group_member (dev, device_group)) {
+ log.debug ("add device %s", dev.DevFile);
+ if (device_group.add (dev))
+ device_group.device_added (dev.Adapter, dev.Frontend);
+ }
+ } catch (DVB.database.SqlError e) {
+ warning ("%s", e.message);
+ }
+ }
manager.restore_device_group_and_timers (device_group);
if (device_group.Id > max_group_id)
max_group_id = device_group.Id;
+ device_group.start_epg_scanner ();
}
- restore_fake_devices (max_group_id);
- }
-
- private static void restore_fake_devices (uint max_group_id) {
- DVB.Settings settings = new DVB.Factory().get_settings ();
- Gee.List<DVB.Device> devices = settings.get_fake_devices ();
- if (devices.size > 0) {
- DVB.Device ref_dev = devices.get (0);
- DVB.DeviceGroup group = new DVB.DeviceGroup (max_group_id + 1,
- ref_dev, false);
- group.Name = "Fake Devices";
- for (int i=1; i<devices.size; i++) {
- group.add (devices.get (i));
- }
-
- manager.restore_device_group (group, false);
- }
}
private static void configure_logging () {
@@ -214,6 +212,9 @@ namespace Main {
// Initializing GStreamer
Gst.init (ref args);
+ // Initializing GStreamer-Mpegts
+ GstMpegTs.initialize ();
+
configure_logging ();
if (!check_requirements ()) {
diff --git a/src/Manager.vala b/src/Manager.vala
index 599857f..22e94b0 100644
--- a/src/Manager.vala
+++ b/src/Manager.vala
@@ -35,14 +35,23 @@ namespace DVB {
public Gee.Collection<DeviceGroup> device_groups {
owned get {
- return this.devices.values;
+ return this.groups.values;
+ }
+ }
+
+ public Gee.ArrayList<Device> devs {
+ get {
+ return this.devices;
}
}
// Map object path to Scanner
private HashMap<string, ScannerData> scanners;
// Maps device group id to Device
- private HashMap<uint, DeviceGroup> devices;
+ private HashMap<uint, DeviceGroup> groups;
+
+ // Collection of devices
+ private Gee.ArrayList<Device> devices;
private uint device_group_counter;
private GUdev.Client udev_client;
@@ -56,10 +65,14 @@ namespace DVB {
Gee.Functions.get_hash_func_for(typeof(string)),
Gee.Functions.get_equal_func_for(typeof(string)),
Gee.Functions.get_equal_func_for(typeof(ScannerData)));
- this.devices = new HashMap<uint, DeviceGroup> ();
+ this.groups = new HashMap<uint, DeviceGroup> ();
+ this.devices = new Gee.ArrayList<Device> ();
this.device_group_counter = 0;
this.udev_client = new GUdev.Client (UDEV_SUBSYSTEMS);
this.udev_client.uevent.connect (this.on_udev_event);
+
+ GLib.List<GUdev.Device> devs = this.udev_client.query_by_subsystem ("dvb");
+ foreach (GUdev.Device dev in devs) this.first_add_device (dev);
}
public static unowned Manager get_instance () {
@@ -87,10 +100,14 @@ namespace DVB {
}
lock (m.devices) {
- foreach (DeviceGroup devgrp in m.devices.values) {
+ m.devices.clear ();
+ }
+
+ lock (m.groups) {
+ foreach (DeviceGroup devgrp in m.groups.values) {
devgrp.destroy ();
}
- m.devices.clear ();
+ m.groups.clear ();
}
instance = null;
@@ -101,66 +118,39 @@ namespace DVB {
/**
* @adapter: Number of the device's adapter
* @frontend: Number of the device's frontend
+ * @type: the type to scanned
* @opath: Object path of the scanner service
* @dbusiface: DBus interface of the scanner service
* @returns: TRUE on success
*
* Get the object path of the channel scanner for this device.
*/
- public bool GetScannerForDevice (uint adapter, uint frontend,
+ public bool GetScannerForDevice (uint adapter, uint frontend, AdapterType type,
out ObjectPath opath, out string dbusiface) throws DBusError
{
string path = Constants.DBUS_SCANNER_PATH.printf (adapter, frontend);
opath = new ObjectPath (path);
- Device device;
- Device? reg_dev = this.get_registered_device (adapter, frontend);
+ dbusiface = "";
- if (reg_dev == null) {
- // Create new device
- device = Device.new_with_type (adapter, frontend);
- } else {
- // Stop epgscanner for device if there's any
- this.get_device_group_of_device (reg_dev).stop_epg_scanner ();
-
- // Assign existing device
- device = reg_dev;
- }
+ Device? device = this.get_device (adapter, frontend);
+ if (device == null)
+ return false;
- switch (device.Type) {
- case AdapterType.DVB_C:
- case AdapterType.DVB_S:
- case AdapterType.DVB_T:
- dbusiface = "org.gnome.DVB.Scanner";
- break;
+ dbusiface = "org.gnome.DVB.Scanner";
- default:
- dbusiface = null;
- break;
+ /* stop epgscanner for device if there's any */
+ DeviceGroup[] groups = get_device_groups_of_device (device);
+ foreach (DeviceGroup group in groups) {
+ group.stop_epg_scanner ();
}
- if (dbusiface == null) {
- log.error ("Unknown adapter type");
- dbusiface = "";
- return false;
- }
lock (this.scanners) {
if (!this.scanners.has_key (path)) {
ScannerData data = new ScannerData ();
- switch (device.Type) {
- case AdapterType.DVB_T:
- data.scanner = new TerrestrialScanner (device);
- break;
-
- case AdapterType.DVB_S:
- data.scanner = new SatelliteScanner (device);
- break;
-
- case AdapterType.DVB_C:
- data.scanner = new CableScanner (device);
- break;
- }
+ /* change to universal Scanner */
+ data.scanner = new Scanner (device, type);
Utils.dbus_register_object (Main.conn, path, (IDBusScanner)data.scanner);
@@ -170,6 +160,7 @@ namespace DVB {
log.debug ("Created new Scanner D-Bus service for adapter %u, frontend %u (%s)",
adapter, frontend, dbusiface);
+
}
}
@@ -185,8 +176,8 @@ namespace DVB {
throws DBusError
{
bool ret;
- lock (this.devices) {
- if (this.devices.has_key (group_id)) {
+ lock (this.groups) {
+ if (this.groups.has_key (group_id)) {
opath = new ObjectPath (Constants.DBUS_DEVICE_GROUP_PATH.printf (group_id));
ret = true;
} else {
@@ -201,10 +192,11 @@ namespace DVB {
* @returns: Device groups' DBus path
*/
public ObjectPath[] GetRegisteredDeviceGroups () throws DBusError {
- ObjectPath[] devs = new ObjectPath[this.devices.size];
+ ObjectPath[] devs = new ObjectPath[this.groups.size];
+ log.debug ("%d", this.groups.size);
int i = 0;
- lock (this.devices) {
- foreach (uint key in this.devices.keys) {
+ lock (this.groups) {
+ foreach (uint key in this.groups.keys) {
devs[i] = new ObjectPath (
Constants.DBUS_DEVICE_GROUP_PATH.printf (key));
i++;
@@ -216,6 +208,7 @@ namespace DVB {
/**
* @adapter: Number of the device's adapter
* @frontend: Number of the device's frontend
+ * @type: type of the new group
* @channels_conf: Path to channels.conf for this device
* @recordings_dir: Path where the recordings should be stored
* @name: Name of group
@@ -226,34 +219,47 @@ namespace DVB {
* all other devices of this group will inherit the settings
* of the reference device).
*/
- public bool AddDeviceToNewGroup (uint adapter, uint frontend,
+ public bool AddDeviceToNewGroup (uint adapter, uint frontend, AdapterType type,
string channels_conf, string recordings_dir, string name)
throws DBusError
{
File chan_file = File.new_for_path (channels_conf);
File rec_dir = File.new_for_path (recordings_dir);
- Device device;
- try {
- device = Device.new_full (adapter, frontend, chan_file,
- rec_dir);
- } catch (DeviceError e) {
- log.error ("Could not create device: %s", e.message);
- return false;
- }
+ /* search device */
+ Device device = this.get_device (adapter, frontend);
+ if (device == null) return false;
// Check if device is already assigned to other group
- if (this.device_is_in_any_group (device)) return false;
+ if (this.device_is_in_any_group (device, type)) return false;
device_group_counter++;
- DeviceGroup devgroup = new DeviceGroup (device_group_counter, device);
- devgroup.Name = name;
+ DeviceGroup devgroup = new DeviceGroup (device_group_counter, chan_file, rec_dir, type);
+ if (devgroup == null) return false;
- this.restore_device_group (devgroup);
+ devgroup.Name = name;
+ this.add_device_group (devgroup, true);
this.group_added (device_group_counter);
+ if (devgroup.add (device)) {
+ try {
+ new Factory().get_config_store ().add_device_to_group (device,
+ devgroup);
+ } catch (SqlError e) {
+ log.error ("%s", e.message);
+ return false;
+ }
+
+ }
+
+ devgroup.device_added (adapter, frontend);
+
+ this.restore_device_group_and_timers (devgroup);
+
+ devgroup.start_epg_scanner ();
+
return true;
}
@@ -269,7 +275,7 @@ namespace DVB {
public bool GetNameOfRegisteredDevice (uint adapter, uint frontend,
out string name) throws DBusError
{
- Device? dev = this.get_registered_device (adapter, frontend);
+ Device? dev = this.get_device (adapter, frontend);
if (dev == null) {
name = "";
@@ -284,13 +290,13 @@ namespace DVB {
* @returns: the numner of configured device groups
*/
public int GetDeviceGroupSize () throws DBusError {
- return this.devices.size;
+ return this.groups.size;
}
/**
* @returns: ID and name of each channel group
*/
- public ChannelGroupInfo[] GetChannelGroups () throws DBusError {
+ public ChannelGroupInfo[] GetChannelGroups () throws DBusError {
ConfigStore config = new Factory().get_config_store ();
Gee.List<ChannelGroup> groups;
try {
@@ -313,7 +319,7 @@ namespace DVB {
* @name: Name of the new group
* @returns: TRUE on success
*/
- public bool AddChannelGroup (string name, out int channel_group_id) throws DBusError {
+ public bool AddChannelGroup (string name, out int channel_group_id) throws DBusError {
ConfigStore config = new Factory().get_config_store ();
bool ret;
try {
@@ -326,10 +332,10 @@ namespace DVB {
}
/**
- * @channel_group_id: ID of the ChannelGroup
+ * @channel_group_id: ID of the ChannelGroup
* @returns: TRUE on success
*/
- public bool RemoveChannelGroup (int channel_group_id) throws DBusError {
+ public bool RemoveChannelGroup (int channel_group_id) throws DBusError {
ConfigStore config = new Factory().get_config_store ();
bool ret;
try {
@@ -346,78 +352,39 @@ namespace DVB {
* devices retrieved via udev
*/
public GLib.HashTable<string, string>[] GetDevices () throws DBusError {
- GLib.List<GUdev.Device> devices =
- this.udev_client.query_by_subsystem ("dvb");
- var devices_list = new GLib.List<HashTable<string, string>> ();
-
- for (int i=0; i<devices.length (); i++) {
- GUdev.Device dev = devices.nth_data (i);
- string? device_file = dev.get_device_file ();
-
- if (device_file == null || !device_file.contains ("frontend"))
- continue;
- var map = new HashTable<string, string>.full (GLib.str_hash,
- GLib.str_equal, GLib.g_free, GLib.g_free);
- devices_list.prepend (map);
+ var arr = new GLib.HashTable<string, string>[devices.size];
- map.insert ("device_file", device_file);
+ for (int i = 0; i < this.devices.size; i++) {
+ Device dev = this.devices.get(i);
+ var map = new HashTable<string, string>.full (GLib.str_hash,
+ GLib.str_equal, GLib.g_free, GLib.g_free);
- GUdev.Device? parent = dev.get_parent ();
- if (parent != null) {
- string attr;
- attr = parent.get_sysfs_attr ("manufacturer");
- if (attr != null) map.insert ("manufacturer", attr);
-
- attr = parent.get_sysfs_attr ("product");
- if (attr != null) map.insert ("product", attr);
- }
- }
-
- var arr = new GLib.HashTable<string, string>[devices_list.length ()];
- for (int i=0; i<devices_list.length (); i++) {
- arr[i] = devices_list.nth_data (i);
+ map.insert ("device_file", "/dev/dvb/adapter%u/frontend%u".printf(dev.Adapter, dev.Frontend));
+ arr[i] = map;
}
-
return arr;
}
+ /**
+ * @adapter: the adapter
+ * @frontend: the frontend
+ * @info: return the AdapterInfo structure
+ * @returns: #false if device cannot found, otherwise #true
+ */
public bool GetAdapterInfo (uint adapter, uint frontend, out AdapterInfo info) throws DBusError {
- Gst.Element dvbelement = Gst.ElementFactory.make ("dvbsrc", null);
- dvbelement.set("adapter", adapter);
- dvbelement.set("frontend", frontend);
-
- Gst.Element pipeline = new Gst.Pipeline("get-adapter-info");
- ((Gst.Bin)pipeline).add(dvbelement);
- pipeline.set_state(Gst.State.READY);
-
- Gst.Bus bus = pipeline.get_bus ();
-
- info = AdapterInfo();
- bool success = false;
- while (bus.have_pending()) {
- Gst.Message msg = bus.pop ();
- if (msg.type == Gst.MessageType.ELEMENT && msg.src == dvbelement) {
- unowned Gst.Structure structure = msg.get_structure ();
- if (structure.get_name () == "dvb-adapter") {
- info.name = structure.get_string ("name");
- info.type = structure.get_string ("type");
- success = true;
- break;
- }
- } else if (msg.type == Gst.MessageType.ERROR) {
- log.warning ("Could not retrieve adapter infos: %s",
- msg.get_structure().to_string ());
- }
- }
- pipeline.set_state (Gst.State.NULL);
+ info = AdapterInfo ();
- if (!success) {
- info.name = "unknown";
- info.type = "unknown";
- }
+ Device? dev = this.get_device (adapter, frontend);
- return success;
+ if (dev == null) return false;
+
+ info.name = dev.Name;
+ info.type_t = dev.isTerrestrial ();
+ info.type_s = dev.isSatellite ();
+ info.type_c = dev.isCable ();
+
+ return true;
}
/**
@@ -436,8 +403,8 @@ namespace DVB {
return false;
}
- lock (this.devices) {
- this.devices.set (group_id, devgroup);
+ lock (this.groups) {
+ this.groups.set (group_id, devgroup);
}
if (store) {
try {
@@ -456,22 +423,20 @@ namespace DVB {
if (group_id > device_group_counter)
device_group_counter = group_id;
- devgroup.start_epg_scanner ();
-
return true;
}
public bool restore_device_group (DeviceGroup device_group, bool store = true) {
- log.debug ("Restoring group %u", device_group.Id);
+ log.info ("Restoring group %u", device_group.Id);
try {
device_group.Channels.load (device_group.Type);
} catch (Error e) {
- log.error ("Error reading channels from file: %s", e.message);
- return false;
+ log.error ("Error reading channels from file: %s", e.message);
+ return false;
}
- return this.add_device_group (device_group, store);
+ return this.add_device_group (device_group, false);
}
public void restore_timers (DeviceGroup device_group) {
@@ -506,28 +471,33 @@ namespace DVB {
recstore.update_last_id (max_id);
}
- public void restore_device_group_and_timers (DeviceGroup device_group)
- {
+ public void restore_device_group_and_timers (DeviceGroup device_group) {
if (this.restore_device_group (device_group)) {
this.restore_timers (device_group);
}
+ log.debug ("add media factory");
+ Gst.RTSPMountPoints points = DVB.RTSPServer.server.get_mount_points ();
+ foreach (Channel channel in device_group.Channels) {
+ MediaFactory factory = new MediaFactory ();
+ points.add_factory ("/%u/%u".printf (device_group.Id, channel.Sid), factory);
+ }
}
public DeviceGroup? get_device_group_if_exists (uint group_id) {
DeviceGroup? result = null;
- lock (this.devices) {
- if (this.devices.has_key (group_id))
- result = this.devices.get (group_id);
+ lock (this.groups) {
+ if (this.groups.has_key (group_id))
+ result = this.groups.get (group_id);
}
return result;
}
- public bool device_is_in_any_group (Device device) {
+ public bool device_is_in_any_group (Device device, AdapterType type) {
bool result = false;
- lock (this.devices) {
- foreach (uint group_id in this.devices.keys) {
- DeviceGroup devgroup = this.devices.get (group_id);
- if (devgroup.contains (device)) {
+ lock (this.groups) {
+ foreach (uint group_id in this.groups.keys) {
+ DeviceGroup devgroup = this.groups.get (group_id);
+ if (devgroup.contains (device) && devgroup.Type == type) {
result = true;
break;
}
@@ -536,6 +506,19 @@ namespace DVB {
return result;
}
+ public Device? get_device (uint adapter, uint frontend) {
+ Device? ret = null;
+ lock (this.devices) {
+ foreach (Device d in this.devices) {
+ if (d.Adapter == adapter && d.Frontend == frontend) {
+ ret = d;
+ break;
+ }
+ }
+ }
+ return ret;
+ }
+
private void on_scanner_destroyed (Scanner scanner) {
uint adapter = scanner.Device.Adapter;
uint frontend = scanner.Device.Frontend;
@@ -549,49 +532,26 @@ namespace DVB {
frontend, path);
// Start epgscanner for device again if there was one
- DeviceGroup? devgroup = this.get_device_group_of_device (scanner.Device);
- if (devgroup != null) {
- devgroup.start_epg_scanner ();
- }
- }
-
- private Device? get_registered_device (uint adapter, uint frontend) {
- Device? result = null;
- Device fake_device = new Device (adapter, frontend);
- lock (this.devices) {
- foreach (uint group_id in this.devices.keys) {
- DeviceGroup devgroup = this.devices.get (group_id);
- if (devgroup.contains (fake_device)) {
- foreach (Device device in devgroup) {
- if (Device.equal (fake_device, device)) {
- result = device;
- break;
- }
- }
- }
- }
+ DeviceGroup[]? devgroups = this.get_device_groups_of_device(scanner.Device);
+ foreach (DeviceGroup group in devgroups) {
+ if (group != null)
+ group.start_epg_scanner ();
}
-
- return result;
}
- private DeviceGroup? get_device_group_of_device (Device device) {
- DeviceGroup? result = null;
- lock (this.devices) {
- foreach (uint group_id in this.devices.keys) {
- DeviceGroup devgroup = this.devices.get (group_id);
+ private DeviceGroup[]? get_device_groups_of_device (Device device) {
+ DeviceGroup[]? ret = new DeviceGroup[this.groups.size];
+ lock (this.groups) {
+ uint i = 0;
+ foreach (uint group_id in this.groups.keys) {
+ DeviceGroup devgroup = this.groups.get (group_id);
if (devgroup.contains (device)) {
- foreach (Device grp_device in devgroup) {
- if (Device.equal (grp_device, device)) {
- result = devgroup;
- break;
- }
- }
+ ret[i] = devgroup;
+ i++;
}
}
}
-
- return result;
+ return ret;
}
private void on_device_removed_from_group (IDBusDeviceGroup idevgroup,
@@ -600,99 +560,158 @@ namespace DVB {
uint group_id = devgroup.Id;
if (devgroup.size == 0) {
bool success;
- lock (this.devices) {
- success = this.devices.unset (group_id);
+ lock (this.groups) {
+ success = this.groups.unset (group_id);
}
if (success) {
- devgroup.destroy ();
-
+ bool lastest = false;
try {
- new Factory().get_config_store ().remove_device_group (
- devgroup);
- new Factory().get_epg_store ().remove_events_of_group (
- devgroup.Id
- );
- new Factory().get_timers_store ().remove_all_timers_from_device_group (
- devgroup.Id
- );
- this.group_removed (group_id);
+ lastest = new Factory().get_config_store ().is_last_device (group_id);
} catch (SqlError e) {
log.error ("%s", e.message);
}
+
+ if ( lastest ) {
+ Gst.RTSPMountPoints points = DVB.RTSPServer.server.get_mount_points ();
+ foreach (Channel channel in devgroup.Channels)
+ points.remove_factory ("/%u/%u".printf (devgroup.Id, channel.Sid));
+
+ try {
+ new Factory().get_config_store ().remove_device_group (
+ devgroup);
+ new Factory().get_epg_store ().remove_events_of_group (
+ devgroup.Id
+ );
+ new Factory().get_timers_store ().remove_all_timers_from_device_group (
+ devgroup.Id
+ );
+
+ } catch (SqlError e) {
+ log.error ("%s", e.message);
+ }
+ }
+ devgroup.destroy ();
+ this.group_removed (group_id);
}
- }
+ }
}
- private void create_device_group_by_id (uint group_id) {
+ private DeviceGroup? create_device_group_by_id (uint group_id) {
ConfigStore config_store = new Factory().get_config_store ();
- Gee.List<DeviceGroup> groups;
+ DeviceGroup? group = null;
+
try {
- groups = config_store.get_all_device_groups ();
+ group = config_store.get_device_group (group_id);
} catch (SqlError e) {
log.error ("Error restoring group %u: %s", group_id,
e.message);
- return;
+ return group;
}
+ if (group == null)
+ log.debug ("device group is null");
+ add_device_group(group, false);
- foreach (DeviceGroup group in groups) {
- if (group.Id == group_id) {
- this.restore_device_group_and_timers (group);
- }
- }
+ this.restore_device_group_and_timers (group);
+ this.group_added (group.Id);
+ return group;
+ }
+
+ private void first_add_device (GUdev.Device device) {
+ string dev_file = device.get_device_file ();
+
+ if (device.get_property ("DVB_DEVICE_TYPE") != "frontend")
+ return;
+
+ uint adapter = (uint)device.get_property_as_uint64 ("DVB_ADAPTER_NUM");
+ uint frontend = (uint)device.get_property_as_uint64 ("DVB_DEVICE_NUM");
+
+ Device dvb_device = new Device.with_udev (device, dev_file, adapter, frontend);
+ this.devices.add(dvb_device);
}
private void on_udev_event (string action, GUdev.Device device) {
if (action == "add" || action == "remove") {
string dev_file = device.get_device_file ();
- uint adapter = -1, frontend = -1;
- if (dev_file.scanf ("/dev/dvb/adapter%u/frontend%u",
- &adapter, &frontend) != 2)
+ if (device.get_property ("DVB_DEVICE_TYPE") != "frontend")
return;
- uint group_id;
+ uint adapter = (uint)device.get_property_as_uint64 ("DVB_ADAPTER_NUM");
+ uint frontend = (uint)device.get_property_as_uint64 ("DVB_DEVICE_NUM");
+
+ /* Search all groups in which this device is */
+ uint[] group_ids;
bool found = false;
ConfigStore config_store = new Factory().get_config_store ();
try {
- found = config_store.get_parent_group (adapter,
- frontend, out group_id);
+ found = config_store.get_parent_groups (adapter,
+ frontend, out group_ids);
} catch (SqlError e) {
critical ("%s", e.message);
}
- if (!found)
- return;
- log.debug ("%s device %s, part of group %u", action, dev_file,
- group_id);
+ log.debug ("%s device %s", action, dev_file);
- DeviceGroup? group = this.get_device_group_if_exists (group_id);
- if (group != null)
- group.stop_epg_scanner ();
+ if (found) {
+ foreach (uint group_id in group_ids) {
+ log.debug ("DeviceGroup ID: %u", group_id);
+
+ DeviceGroup? group = this.get_device_group_if_exists (group_id);
+
+ if (group == null)
+ group = this.create_device_group_by_id (group_id);
+
+ if (group != null)
+ group.stop_epg_scanner ();
+ }
+ }
if (action == "add") {
- if (group == null) {
- /* This is the first device part of the group
- * that has been added. We have to create the
- * whole group */
- this.create_device_group_by_id (group_id);
- } else {
- Device dvb_device = Device.new_with_type (adapter,
- frontend);
- if (dvb_device == null) return;
-
- group.add (dvb_device);
+ Device dvb_device = new Device.with_udev (device, dev_file, adapter, frontend);
+ this.devices.add(dvb_device);
+
+ if (found) {
+ foreach (uint group_id in group_ids) {
+ DeviceGroup? group = this.get_device_group_if_exists (group_id);
+ if (group != null) {
+ if (group.add (dvb_device))
+ group.device_added (dvb_device.Adapter, dvb_device.Frontend);
+ }
+ }
}
} else {
- Device dvb_device = new Device (adapter, frontend);
- // FIXME emit signal without removing
- // the device from the DB
- group.remove (dvb_device);
+ /* Search device in devices */
+ foreach (Device d in this.devices) {
+ if (d.Frontend == frontend && d.Adapter == adapter) {
+
+ this.devices.remove(d);
+
+ }
+ if (found) {
+ foreach (uint group_id in group_ids) {
+ DeviceGroup? group = this.get_device_group_if_exists (group_id);
+ if (group != null) {
+ if (group.remove (d))
+ group.device_removed (d.Adapter, d.Frontend);
+
+ }
+ }
+ }
+ }
+
}
- if (group != null)
- group.start_epg_scanner ();
+ log.debug("Numbers of devices %u", this.devices.size);
+
+ if (found) {
+ foreach (uint group_id in group_ids) {
+ DeviceGroup? group = this.get_device_group_if_exists (group_id);
+ if (group != null)
+ group.start_epg_scanner ();
+ }
+ }
}
}
diff --git a/src/MpegTsEnums.vala b/src/MpegTsEnums.vala
index fb37112..48969d2 100644
--- a/src/MpegTsEnums.vala
+++ b/src/MpegTsEnums.vala
@@ -18,189 +18,363 @@
*/
using GLib;
+using GstMpegTs;
namespace DVB {
- public enum DvbSrcCodeRate {
- FEC_NONE,
- FEC_1_2,
- FEC_2_3,
- FEC_3_4,
- FEC_4_5,
- FEC_5_6,
- FEC_6_7,
- FEC_7_8,
- FEC_8_9,
- FEC_AUTO
+ public enum DvbSrcDelsys {
+ SYS_UNDEFINED,
+ SYS_DVBC_ANNEX_A,
+ SYS_DVBC_ANNEX_B,
+ SYS_DVBT,
+ SYS_DSS,
+ SYS_DVBS,
+ SYS_DVBS2,
+ SYS_DVBH,
+ SYS_ISDBT,
+ SYS_ISDBS,
+ SYS_ISDBC,
+ SYS_ATSC,
+ SYS_ATSCMH,
+ SYS_DTMB,
+ SYS_CMMB,
+ SYS_DAB,
+ SYS_DVBT2,
+ SYS_TURBO,
+ SYS_DVBC_ANNEX_C
}
- public enum DvbSrcModulation {
- QPSK,
- QAM_16,
- QAM_32,
- QAM_64,
- QAM_128,
- QAM_256,
- QAM_AUTO
- }
+ /* mpegts converts */
+ private DVBCodeRate getCodeRateEnum (string val) {
+ switch (val) {
+ case "1/2":
+ return DVBCodeRate 1_2;
+ case "2/3":
+ return DVBCodeRate 2_3;
+ case "2/5":
+ return DVBCodeRate 2_5;
+ case "3/4":
+ return DVBCodeRate 3_4;
+ case "3/5":
+ return DVBCodeRate 3_5;
+ case "4/5":
+ return DVBCodeRate 4_5;
+ case "5/6":
+ return DVBCodeRate 5_6;
+ case "6/7":
+ return DVBCodeRate 6_7;
+ case "7/8":
+ return DVBCodeRate 7_8;
+ case "8/9":
+ return DVBCodeRate 8_9;
+ case "9/10":
+ return DVBCodeRate 9_10;
+ case "NONE":
+ return DVBCodeRate.NONE;
+ default:
+ return DVBCodeRate.AUTO;
+ }
+ }
- public enum DvbSrcTransmissionMode {
- TRANSMISSION_MODE_2K,
- TRANSMISSION_MODE_8K,
- TRANSMISSION_MODE_AUTO
- }
+ private string getCodeRateString (DVBCodeRate val) {
+ switch (val) {
+ case DVBCodeRate 1_2:
+ return "1/2";
+ case DVBCodeRate 2_3:
+ return "2/3";
+ case DVBCodeRate 2_5:
+ return "2/5";
+ case DVBCodeRate 3_4:
+ return "3/4";
+ case DVBCodeRate 3_5:
+ return "3/5";
+ case DVBCodeRate 4_5:
+ return "4/5";
+ case DVBCodeRate 5_6:
+ return "5/6";
+ case DVBCodeRate 6_7:
+ return "6/7";
+ case DVBCodeRate 7_8:
+ return "7/8";
+ case DVBCodeRate 8_9:
+ return "8/9";
+ case DVBCodeRate 9_10:
+ return "9/10";
+ case DVBCodeRate.NONE:
+ return "NONE";
+ case DVBCodeRate.AUTO:
+ default:
+ return "AUTO";
+ }
+ }
- public enum DvbSrcBandwidth {
- BANDWIDTH_8_MHZ,
- BANDWIDTH_7_MHZ,
- BANDWIDTH_6_MHZ,
- BANDWIDTH_AUTO
- }
- public enum DvbSrcGuard {
- GUARD_INTERVAL_1_32,
- GUARD_INTERVAL_1_16,
- GUARD_INTERVAL_1_8,
- GUARD_INTERVAL_1_4,
- GUARD_INTERVAL_AUTO
- }
+ private ModulationType getModulationEnum (string val) {
+ switch (val) {
+ case "QPSK":
+ return ModulationType.QPSK;
+ case "QAM/16":
+ return ModulationType.QAM_16;
+ case "QAM/32":
+ return ModulationType.QAM_32;
+ case "QAM/64":
+ return ModulationType.QAM_64;
+ case "QAM/128":
+ return ModulationType.QAM_128;
+ case "QAM/256":
+ return ModulationType.QAM_256;
+ case "QAM/AUTO":
+ return ModulationType.QAM_AUTO;
+ case "VSB/8":
+ return ModulationType.VSB_8;
+ case "VSB/16":
+ return ModulationType.VSB_16;
+ case "PSK/8":
+ return ModulationType.PSK_8;
+ case "APSK/16":
+ return ModulationType.APSK_16;
+ case "APSK/32":
+ return ModulationType.APSK_32;
+ case "DQPSK":
+ return ModulationType.DQPSK;
+ case "QAM/4_NR":
+ return ModulationType.QAM_4_NR_;
+ default:
+ return ModulationType.QAM_AUTO;
+ }
+ }
- public enum DvbSrcHierarchy {
- HIERARCHY_NONE,
- HIERARCHY_1,
- HIERARCHY_2,
- HIERARCHY_4,
- HIERARCHY_AUTO
- }
+ private string getModulationString (ModulationType val) {
+ switch (val) {
+ case ModulationType.QPSK:
+ return "QPSK";
+ case ModulationType.QAM_16:
+ return "QAM/16";
+ case ModulationType.QAM_32:
+ return "QAM/32";
+ case ModulationType.QAM_64:
+ return "QAM/64";
+ case ModulationType.QAM_128:
+ return "QAM/128";
+ case ModulationType.QAM_256:
+ return "QAM/256";
+ case ModulationType.QAM_AUTO:
+ return "QAM/AUTO";
+ case ModulationType.VSB_8:
+ return "VSB/8";
+ case ModulationType.VSB_16:
+ return "VSB/16";
+ case ModulationType.PSK_8:
+ return "PSK/8";
+ case ModulationType.APSK_16:
+ return "APSK/16";
+ case ModulationType.APSK_32:
+ return "APSK/32";
+ case ModulationType.DQPSK:
+ return "DQPSK";
+ case ModulationType.QAM_4_NR_:
+ return "QAM/4_NR";
+ default:
+ return "QAM/AUTO";
+ }
+ }
- public enum DvbSrcInversion {
- INVERSION_OFF,
- INVERSION_ON,
- INVERSION_AUTO
- }
+ private TerrestrialGuardInterval getGuardIntervalEnum (string val) {
+ switch (val) {
+ case "1/32":
+ return TerrestrialGuardInterval 1_32;
+ case "1/16":
+ return TerrestrialGuardInterval 1_16;
+ case "1/8":
+ return TerrestrialGuardInterval 1_8;
+ case "1/4":
+ return TerrestrialGuardInterval 1_4;
+ case "AUTO":
+ return TerrestrialGuardInterval.AUTO;
+ case "1/128":
+ return TerrestrialGuardInterval 1_128;
+ case "19/128":
+ return TerrestrialGuardInterval 19_128;
+ case "19/256":
+ return TerrestrialGuardInterval 19_256;
+ case "PN420":
+ return TerrestrialGuardInterval.PN420;
+ case "PN595":
+ return TerrestrialGuardInterval.PN595;
+ case "PN945":
+ return TerrestrialGuardInterval.PN945;
+ default:
+ return TerrestrialGuardInterval.AUTO;
+ }
+ }
- /**
- * @bandwith: 0, 6, 7 or 8
- */
- public static DvbSrcBandwidth get_bandwidth_val (uint bandwidth) {
- DvbSrcBandwidth val;
- switch (bandwidth) {
- case 6: val = DvbSrcBandwidth.BANDWIDTH_6_MHZ; break;
- case 7: val = DvbSrcBandwidth.BANDWIDTH_7_MHZ; break;
- case 8: val = DvbSrcBandwidth.BANDWIDTH_8_MHZ; break;
- // 0
- default: val = DvbSrcBandwidth.BANDWIDTH_AUTO; break;
+ private string getGuardIntervalString (TerrestrialGuardInterval val) {
+ switch (val) {
+ case TerrestrialGuardInterval 1_32:
+ return "1/32";
+ case TerrestrialGuardInterval 1_16:
+ return "1/16";
+ case TerrestrialGuardInterval 1_8:
+ return "1/8";
+ case TerrestrialGuardInterval 1_4:
+ return "1/4";
+ case TerrestrialGuardInterval.AUTO:
+ return "AUTO";
+ case TerrestrialGuardInterval 1_128:
+ return "1/128";
+ case TerrestrialGuardInterval 19_128:
+ return "19/128";
+ case TerrestrialGuardInterval 19_256:
+ return "19/256";
+ case TerrestrialGuardInterval.PN420:
+ return "PN420";
+ case TerrestrialGuardInterval.PN595:
+ return "PN595";
+ case TerrestrialGuardInterval.PN945:
+ return "PN945";
+ default:
+ return "AUTO";
+ }
}
- return val;
- }
- /**
- * @hierarchy: 0, 1, 2 or 4.
- * If value doesn't match one of above HIERARCHY_AUTO is returned.
- */
- public static DvbSrcHierarchy get_hierarchy_val (uint hierarchy) {
- DvbSrcHierarchy val;
- switch (hierarchy) {
- case 0: val = DvbSrcHierarchy.HIERARCHY_NONE; break;
- case 1: val = DvbSrcHierarchy.HIERARCHY_1; break;
- case 2: val = DvbSrcHierarchy.HIERARCHY_2; break;
- case 4: val = DvbSrcHierarchy.HIERARCHY_4; break;
- default: val = DvbSrcHierarchy.HIERARCHY_AUTO; break;
+ private TerrestrialHierarchy getHierarchyEnum (string val) {
+ switch (val) {
+ case "NONE":
+ return TerrestrialHierarchy.NONE;
+ case "1":
+ return TerrestrialHierarchy 1;
+ case "2":
+ return TerrestrialHierarchy 2;
+ case "4":
+ return TerrestrialHierarchy 4;
+ case "AUTO":
+ default:
+ return TerrestrialHierarchy.AUTO;
+ }
}
- return val;
- }
- /**
- * @modulation: QPSK, QAM16, QAM32, QAM64, QAM128 or QAM256.
- * If value doesn't match one of above QAM_AUTO is returned.
- */
- public static DvbSrcModulation get_modulation_val (string constellation) {
- DvbSrcModulation val;
- if (constellation == "QPSK")
- val = DvbSrcModulation.QPSK;
- else if (constellation == "QAM16")
- val = DvbSrcModulation.QAM_16;
- else if (constellation == "QAM32")
- val = DvbSrcModulation.QAM_32;
- else if (constellation == "QAM64")
- val = DvbSrcModulation.QAM_64;
- else if (constellation == "QAM128")
- val = DvbSrcModulation.QAM_128;
- else if (constellation == "QAM256")
- val = DvbSrcModulation.QAM_256;
- else
- val = DvbSrcModulation.QAM_AUTO;
-
- return val;
- }
+ private string getHierarchyString (TerrestrialHierarchy val) {
+ switch (val) {
+ case TerrestrialHierarchy.NONE:
+ return "NONE";
+ case TerrestrialHierarchy 1:
+ return "1";
+ case TerrestrialHierarchy 2:
+ return "2";
+ case TerrestrialHierarchy 4:
+ return "4";
+ case TerrestrialHierarchy.AUTO:
+ default:
+ return "AUTO";
+ }
+ }
- /**
- * @code_rate_string: "NONE", 1/2", "2/3", "3/4", "4/5", "5/6", "6/7",
- * "7/8" or "8/9".
- * If value doesn't match one of above FEC_AUTO is returned.
- */
- public static DvbSrcCodeRate get_code_rate_val (string code_rate_string) {
- DvbSrcCodeRate val;
- if (code_rate_string == "NONE")
- val = DvbSrcCodeRate.FEC_NONE;
- else if (code_rate_string == "1/2")
- val = DvbSrcCodeRate.FEC_1_2;
- else if (code_rate_string == "2/3")
- val = DvbSrcCodeRate.FEC_2_3;
- else if (code_rate_string == "3/4")
- val = DvbSrcCodeRate.FEC_3_4;
- else if (code_rate_string == "4/5")
- val = DvbSrcCodeRate.FEC_4_5;
- else if (code_rate_string == "5/6")
- val = DvbSrcCodeRate.FEC_5_6;
- else if (code_rate_string == "6/7")
- val = DvbSrcCodeRate.FEC_5_6;
- else if (code_rate_string == "7/8")
- val = DvbSrcCodeRate.FEC_7_8;
- else if (code_rate_string == "8/9")
- val = DvbSrcCodeRate.FEC_8_9;
- else
- val = DvbSrcCodeRate.FEC_AUTO;
-
- return val;
- }
+ private TerrestrialTransmissionMode getTransmissionModeEnum (string val) {
+ switch (val) {
+ case "2K":
+ return TerrestrialTransmissionMode 2K;
+ case "8K":
+ return TerrestrialTransmissionMode 8K;
+ case "AUTO":
+ return TerrestrialTransmissionMode.AUTO;
+ case "4K":
+ return TerrestrialTransmissionMode 4K;
+ case "1K":
+ return TerrestrialTransmissionMode 1K;
+ case "16K":
+ return TerrestrialTransmissionMode 16K;
+ case "32K":
+ return TerrestrialTransmissionMode 32K;
+ case "C1":
+ return TerrestrialTransmissionMode.C1;
+ case "C3780":
+ return TerrestrialTransmissionMode.C3780;
+ default:
+ return TerrestrialTransmissionMode.AUTO;
+ }
+ }
- /**
- * @guard: 4, 8, 16 or 32.
- * If value doesn't match one of above GUARD_INTERVAL_AUTO is returned.
- */
- public static DvbSrcGuard get_guard_interval_val (uint guard) {
- DvbSrcGuard val;
- switch (guard) {
- case 4:
- val = DvbSrcGuard.GUARD_INTERVAL_1_4; break;
- case 8:
- val = DvbSrcGuard.GUARD_INTERVAL_1_8; break;
- case 16:
- val = DvbSrcGuard.GUARD_INTERVAL_1_16; break;
- case 32:
- val = DvbSrcGuard.GUARD_INTERVAL_1_32; break;
- default:
- val = DvbSrcGuard.GUARD_INTERVAL_AUTO; break;
+ private string getTransmissionModeString (TerrestrialTransmissionMode val) {
+ switch (val) {
+ case TerrestrialTransmissionMode 2K:
+ return "2K";
+ case TerrestrialTransmissionMode 8K:
+ return "8K";
+ case TerrestrialTransmissionMode.AUTO:
+ return "AUTO";
+ case TerrestrialTransmissionMode 4K:
+ return "4K";
+ case TerrestrialTransmissionMode 1K:
+ return "1K";
+ case TerrestrialTransmissionMode 16K:
+ return "16K";
+ case TerrestrialTransmissionMode 32K:
+ return "32K";
+ case TerrestrialTransmissionMode.C1:
+ return "C1";
+ case TerrestrialTransmissionMode.C3780:
+ return "C3780";
+ default:
+ return "AUTO";
+ }
}
- return val;
- }
- /**
- * @transmode: "2k" or "8k"
- * If value doesn't match one of above TRANSMISSION_MODE_AUTO is returned.
- */
- public static DvbSrcTransmissionMode get_transmission_mode_val (
- string transmode) {
- DvbSrcTransmissionMode val;
- if (transmode == "2k")
- val = DvbSrcTransmissionMode.TRANSMISSION_MODE_2K;
- else if (transmode == "8k")
- val = DvbSrcTransmissionMode.TRANSMISSION_MODE_8K;
- else
- val = DvbSrcTransmissionMode.TRANSMISSION_MODE_AUTO;
-
- return val;
- }
+ private SatellitePolarizationType getPolarizationEnum (string val) {
+ switch (val) {
+ case "VERTICAL":
+ return SatellitePolarizationType.LINEAR_VERTICAL;
+ case "HORIZONTAL":
+ return SatellitePolarizationType.LINEAR_HORIZONTAL;
+ case "LEFT":
+ return SatellitePolarizationType.CIRCULAR_LEFT;
+ case "RIGHT":
+ return SatellitePolarizationType.CIRCULAR_RIGHT;
+ default:
+ return SatellitePolarizationType.LINEAR_VERTICAL;
+ }
+ }
+ private string getPolarizationString (SatellitePolarizationType val) {
+ switch (val) {
+ case SatellitePolarizationType.LINEAR_VERTICAL:
+ return "VERTICAL";
+ case SatellitePolarizationType.LINEAR_HORIZONTAL:
+ return "HORIZONTAL";
+ case SatellitePolarizationType.CIRCULAR_LEFT:
+ return "LEFT";
+ case SatellitePolarizationType.CIRCULAR_RIGHT:
+ return "RIGHT";
+ default:
+ return "VERTICAL";
+ }
+ }
+
+ private bool isSupported (DvbSrcDelsys delsys, AdapterType type) {
+ switch (delsys) {
+ case DvbSrcDelsys.SYS_DVBC_ANNEX_A:
+ case DvbSrcDelsys.SYS_DVBC_ANNEX_B:
+ case DvbSrcDelsys.SYS_DVBC_ANNEX_C:
+ case DvbSrcDelsys.SYS_ISDBC:
+ return (type == AdapterType.CABLE);
+ case DvbSrcDelsys.SYS_DVBT:
+ case DvbSrcDelsys.SYS_DVBH:
+ case DvbSrcDelsys.SYS_ISDBT:
+ case DvbSrcDelsys.SYS_ATSC:
+ case DvbSrcDelsys.SYS_ATSCMH:
+ case DvbSrcDelsys.SYS_DVBT2:
+ return (type == AdapterType.TERRESTRIAL);
+ case DvbSrcDelsys.SYS_DSS:
+ case DvbSrcDelsys.SYS_DVBS:
+ case DvbSrcDelsys.SYS_DVBS2:
+ case DvbSrcDelsys.SYS_TURBO:
+ case DvbSrcDelsys.SYS_ISDBS:
+ return (type == AdapterType.SATELLITE);
+ case DvbSrcDelsys.SYS_DTMB:
+ case DvbSrcDelsys.SYS_CMMB:
+ case DvbSrcDelsys.SYS_DAB:
+ case DvbSrcDelsys.SYS_UNDEFINED:
+ default:
+ return false;
+ }
+ }
}
diff --git a/src/Parameter.vala b/src/Parameter.vala
new file mode 100644
index 0000000..8ee807c
--- /dev/null
+++ b/src/Parameter.vala
@@ -0,0 +1,48 @@
+/*
+ * Parameter.vala
+ *
+ * Copyright (C) 2014 Stefan Ringel <linuxtv stefanringel de>
+ *
+ * This file is part of GNOME DVB Daemon.
+ *
+ * GNOME DVB Daemon is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME DVB Daemon is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNOME DVB Daemon. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using GLib;
+
+namespace DVB {
+ /* base class for all tuning parameters */
+ public abstract class Parameter : GLib.Object {
+
+ /* delivery system which this tuning parameter has */
+ public DvbSrcDelsys Delsys { get; construct; }
+
+ /* center frequency */
+ public uint Frequency { get; protected set; }
+
+ // Constructor
+ public Parameter (DvbSrcDelsys delsys) {
+ base (Delsys: delsys);
+ }
+
+ public abstract void prepare (Gst.Element source);
+
+ public abstract bool add_scanning_data (HashTable<string, Variant> data);
+
+ public abstract bool equal (Parameter param);
+
+ public abstract string to_string ();
+ }
+ }
+
diff --git a/src/Parameters/DvbCEuropeParameter.vala b/src/Parameters/DvbCEuropeParameter.vala
new file mode 100644
index 0000000..9be7866
--- /dev/null
+++ b/src/Parameters/DvbCEuropeParameter.vala
@@ -0,0 +1,106 @@
+/*
+ * DvbCEuropeParameter.vala
+ *
+ * Copyright (C) 2014 Stefan Ringel
+ *
+ * GNOME DVB Daemon is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME DVB Daemon is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME DVB Daemon. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using GLib;
+using GstMpegTs;
+using DVB.Logging;
+
+namespace DVB {
+ public class DvbCEuropeParameter : Parameter {
+ private static Logger log = LogManager.getLogManager().getDefaultLogger();
+
+ public uint SymbolRate { get; private set; }
+
+ public ModulationType Modulation { get; private set; }
+
+ public DVBCodeRate InnerFEC { get; private set; }
+
+ // Constructor
+ public DvbCEuropeParameter () {
+ base (DvbSrcDelsys.SYS_DVBC_ANNEX_A);
+ }
+
+ public DvbCEuropeParameter.with_parameter (uint frequency, uint symbol_rate,
+ ModulationType modulation, DVBCodeRate inner_fec) {
+ base (DvbSrcDelsys.SYS_DVBC_ANNEX_A);
+ this.Frequency = frequency;
+ this.SymbolRate = symbol_rate;
+ this.Modulation = modulation;
+ this.InnerFEC = inner_fec;
+ }
+
+ public override bool add_scanning_data (HashTable<string, Variant> data) {
+ unowned Variant _var;
+
+ _var = data.lookup ("frequency");
+ if (_var == null)
+ return false;
+ this.Frequency = _var.get_uint32 ();
+
+ _var = data.lookup ("symbol-rate");
+ if (_var == null)
+ return false;
+ this.SymbolRate = _var.get_uint32 ();
+
+ _var = data.lookup ("inner-fec");
+ if (_var == null)
+ return false;
+ this.InnerFEC = getCodeRateEnum (_var.get_string ());
+
+ _var = data.lookup ("modulation");
+ if (_var == null)
+ return false;
+ this.Modulation = getModulationEnum (_var.get_string ());
+
+ return true;
+ }
+
+ public override bool equal (Parameter param) {
+ if (param == null)
+ return false;
+
+ if (param.Delsys != this.Delsys)
+ return false;
+
+ DvbCEuropeParameter cparam = (DvbCEuropeParameter)param;
+
+ if (cparam.Frequency == this.Frequency &&
+ cparam.SymbolRate == this.SymbolRate &&
+ cparam.InnerFEC == this.InnerFEC &&
+ cparam.Modulation == this.Modulation)
+ return true;
+
+ return false;
+ }
+
+ public override void prepare (Gst.Element source) {
+ log.debug ("Prepare DVB-C Scanning Parameter");
+ source.set ("frequency", this.Frequency);
+ source.set ("symbol-rate", this.SymbolRate / 1000);
+ source.set ("modulation", this.Modulation);
+ source.set ("code-rate-hp", this.InnerFEC);
+ source.set ("delsys", this.Delsys);
+ }
+
+ public override string to_string () {
+ return "DVBC/ANNEX_A:%u:%u:%s:%s".printf (this.Frequency, this.SymbolRate / 1000,
+ getModulationString (this.Modulation), getCodeRateString (this.InnerFEC));
+ }
+ }
+}
diff --git a/src/Parameters/DvbSParameter.vala b/src/Parameters/DvbSParameter.vala
new file mode 100644
index 0000000..d7b9fa8
--- /dev/null
+++ b/src/Parameters/DvbSParameter.vala
@@ -0,0 +1,134 @@
+/*
+ * DvbSParameter.vala
+ *
+ * Copyright (C) 2014 Stefan Ringel
+ *
+ * GNOME DVB Daemon is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME DVB Daemon is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME DVB Daemon. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using GLib;
+using GstMpegTs;
+using DVB.Logging;
+
+namespace DVB {
+ public class DvbSParameter : Parameter {
+ private static Logger log = LogManager.getLogManager().getDefaultLogger();
+
+ public uint SymbolRate { get; private set; }
+ public float OrbitalPosition { get; private set; }
+ public SatellitePolarizationType Polarization { get; private set; }
+ public int DiseqcSource { get; set; }
+ public DVBCodeRate InnerFEC { get; private set; }
+
+ // Constructor
+ public DvbSParameter () {
+ base (DvbSrcDelsys.SYS_DVBS);
+ this.DiseqcSource = -1;
+ }
+
+ public DvbSParameter.with_parameter (uint frequency, uint symbol_rate,
+ float position, SatellitePolarizationType polarization,
+ DVBCodeRate inner_fec) {
+ base (DvbSrcDelsys.SYS_DVBS);
+ this.Frequency = frequency;
+ this.SymbolRate = symbol_rate;
+ this.OrbitalPosition = position;
+ this.Polarization = polarization;
+ this.InnerFEC = inner_fec;
+ this.DiseqcSource = -1;
+ }
+
+ public override bool add_scanning_data (HashTable<string, Variant> data) {
+
+ unowned Variant _var;
+
+ _var = data.lookup ("frequency");
+ if (_var == null)
+ return false;
+ this.Frequency = _var.get_uint32 ();
+
+ _var = data.lookup ("symbol-rate");
+ if (_var == null)
+ return false;
+ this.SymbolRate = _var.get_uint32 ();
+
+ _var = data.lookup ("polarization");
+ if (_var == null)
+ return false;
+ this.Polarization = getPolarizationEnum (_var.get_string ());
+
+ _var = data.lookup ("inner-fec");
+ if (_var == null)
+ return false;
+ this.InnerFEC = getCodeRateEnum (_var.get_string ());
+
+ _var = data.lookup ("orbital-position");
+ if (_var == null)
+ return false;
+ this.OrbitalPosition = (float)_var.get_double ();
+
+ _var = data.lookup ("diseqc-source");
+ if (_var == null)
+ return false;
+ this.DiseqcSource = (int)_var.get_int16 ();
+
+ return true;
+ }
+
+ public override bool equal (Parameter param) {
+ if (param == null)
+ return false;
+
+ if (param.Delsys != this.Delsys)
+ return false;
+
+ DvbSParameter sparam = (DvbSParameter)param;
+
+ if (sparam.Frequency == this.Frequency &&
+ sparam.SymbolRate == this.SymbolRate &&
+ sparam.InnerFEC == this.InnerFEC &&
+ sparam.Polarization == this.Polarization &&
+ sparam.OrbitalPosition == this.OrbitalPosition &&
+ sparam.DiseqcSource == this.DiseqcSource)
+ return true;
+
+ return false;
+ }
+
+ public override void prepare (Gst.Element source) {
+ log.debug ("Prepare DVB-S Scanning Parameter");
+ source.set ("frequency", this.Frequency);
+ source.set ("sombol-rate", this.SymbolRate);
+ switch (this.Polarization) {
+ case SatellitePolarizationType.LINEAR_HORIZONTAL:
+ source.set ("polarity", "H");
+ break;
+ case SatellitePolarizationType.LINEAR_VERTICAL:
+ source.set ("polarity", "V");
+ break;
+ default:
+ break;
+ }
+ source.set ("code-rate-hp", this.InnerFEC);
+ source.set ("diseqc-source", this.DiseqcSource);
+ source.set ("delsys", this.Delsys);
+ }
+
+ public override string to_string () {
+ return "DVBS:%f:%d:%u:%u:%s:%s".printf (this.OrbitalPosition, this.DiseqcSource,
+ this.Frequency, this.SymbolRate, getCodeRateString (this.InnerFEC),
+ getPolarizationString (this.Polarization));
+ }
+ }
+}
diff --git a/src/Parameters/DvbTParameter.vala b/src/Parameters/DvbTParameter.vala
new file mode 100644
index 0000000..562cb0d
--- /dev/null
+++ b/src/Parameters/DvbTParameter.vala
@@ -0,0 +1,146 @@
+/*
+ * DvbTParameter.vala
+ *
+ * Copyright (C) 2014 Stefan Ringel
+ *
+ * GNOME DVB Daemon is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME DVB Daemon is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME DVB Daemon. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using GLib;
+using GstMpegTs;
+using DVB.Logging;
+
+namespace DVB {
+ public class DvbTParameter : Parameter {
+ private static Logger log = LogManager.getLogManager().getDefaultLogger();
+
+ public uint Bandwidth { get; private set; }
+ public TerrestrialGuardInterval GuardInterval { get; private set; }
+ public TerrestrialTransmissionMode TransmissionMode { get; private set; }
+ public TerrestrialHierarchy Hierarchy { get; private set; }
+ public ModulationType Constellation { get; private set; }
+ public DVBCodeRate CodeRateLP { get; private set; }
+ public DVBCodeRate CodeRateHP { get; private set; }
+
+ // Constructor
+ public DvbTParameter () {
+ base (DvbSrcDelsys.SYS_DVBT);
+ }
+
+ public DvbTParameter.with_parameter (uint frequency, uint bandwidth,
+ TerrestrialGuardInterval interval, TerrestrialTransmissionMode transmission,
+ TerrestrialHierarchy hierarchy, ModulationType constellation,
+ DVBCodeRate code_rate_lp, DVBCodeRate code_rate_hp) {
+ base (DvbSrcDelsys.SYS_DVBT);
+ this.Frequency = frequency;
+ this.Bandwidth = bandwidth;
+ this.GuardInterval = interval;
+ this.TransmissionMode = transmission;
+ this.Hierarchy = hierarchy;
+ this.Constellation = constellation;
+ this.CodeRateLP = code_rate_lp;
+ this.CodeRateHP = code_rate_hp;
+ }
+
+ public override bool add_scanning_data (HashTable<string, Variant> data) {
+ unowned Variant _var;
+
+ _var = data.lookup ("frequency");
+ if (_var == null)
+ return false;
+ this.Frequency = _var.get_uint32 ();
+
+ _var = data.lookup ("hierarchy");
+ if (_var == null)
+ return false;
+ this.Hierarchy = getHierarchyEnum (_var.get_string ());
+
+ _var = data.lookup ("bandwidth");
+ if (_var == null)
+ return false;
+ this.Bandwidth = _var.get_uint32 () * 1000000;
+
+ _var = data.lookup ("transmission-mode");
+ if (_var == null)
+ return false;
+ this.TransmissionMode = getTransmissionModeEnum (_var.get_string ());
+
+ _var = data.lookup ("code-rate-hp");
+ if (_var == null)
+ return false;
+ this.CodeRateHP = getCodeRateEnum (_var.get_string ());
+
+ _var = data.lookup ("code-rate-lp");
+ if (_var == null)
+ return false;
+ this.CodeRateLP = getCodeRateEnum (_var.get_string ());
+
+ _var = data.lookup ("constellation");
+ if (_var == null)
+ return false;
+ this.Constellation = getModulationEnum (_var.get_string ());
+
+ _var = data.lookup ("guard-interval");
+ if (_var == null)
+ return false;
+ this.GuardInterval = getGuardIntervalEnum (_var.get_string ());
+
+ return true;
+ }
+
+ public override bool equal (Parameter param) {
+ if (param == null)
+ return false;
+
+ if (param.Delsys != this.Delsys)
+ return false;
+
+ DvbTParameter tparam = (DvbTParameter)param;
+
+ if (tparam.Frequency == this.Frequency &&
+ tparam.Bandwidth == this.Bandwidth &&
+ tparam.Hierarchy == this.Hierarchy &&
+ tparam.TransmissionMode == this.TransmissionMode &&
+ tparam.CodeRateHP == this.CodeRateHP &&
+ tparam.CodeRateLP == this.CodeRateLP &&
+ tparam.Constellation == this.Constellation &&
+ tparam.GuardInterval == this.GuardInterval)
+ return true;
+
+ return false;
+ }
+
+ public override void prepare (Gst.Element source) {
+ log.debug ("Prepare DVB-T Scanning Parameter");
+ source.set ("frequency", this.Frequency);
+ source.set ("bandwidth-hz", this.Bandwidth);
+ source.set ("hierarchy", this.Hierarchy);
+ source.set ("modulation", this.Constellation);
+ source.set ("code-rate-hp", this.CodeRateHP);
+ source.set ("code-rate-lp", this.CodeRateLP);
+ source.set ("guard", this.GuardInterval);
+ source.set ("trans-mode", this.TransmissionMode);
+ source.set ("delsys", this.Delsys);
+
+ }
+
+ public override string to_string () {
+ return "DVBT:%u:%u:%s:%s:%s:%s:%s:%s".printf (this.Frequency, this.Bandwidth,
+ getCodeRateString (this.CodeRateLP), getCodeRateString (this.CodeRateHP),
+ getModulationString (this.Constellation), getTransmissionModeString (this.TransmissionMode),
+ getGuardIntervalString (this.GuardInterval), getHierarchyString (this.Hierarchy));
+ }
+ }
+}
+
diff --git a/src/Recorder.vala b/src/Recorder.vala
index 99b5bf8..3be31f4 100644
--- a/src/Recorder.vala
+++ b/src/Recorder.vala
@@ -21,6 +21,7 @@ using GLib;
using Gee;
using DVB.database;
using DVB.Logging;
+using GstMpegTs;
namespace DVB {
@@ -833,9 +834,11 @@ namespace DVB {
return val;
}
- private void on_eit_structure (PlayerThread player, Gst.Structure structure) {
- uint sid;
- structure.get_uint ("service-id", out sid);
+ private void on_eit_structure (PlayerThread player, Section section) {
+
+ uint sid = 0;
+
+ sid = section.subtable_extension;
lock (this.recordings) {
// Find name and description for recordings
diff --git a/src/Scanner.vala b/src/Scanner.vala
index 6b33e76..7738c42 100644
--- a/src/Scanner.vala
+++ b/src/Scanner.vala
@@ -20,13 +20,14 @@
using GLib;
using Gee;
using DVB.Logging;
+using GstMpegTs;
namespace DVB {
/**
- * An abstract class responsible for scanning for new channels
+ * A class responsible for scanning for new channels
*/
- public abstract class Scanner : GLib.Object {
+ public class Scanner : GLib.Object, IDBusScanner {
private static Logger log = LogManager.getLogManager().getDefaultLogger();
@@ -36,33 +37,6 @@ namespace DVB {
public signal void destroyed ();
/**
- * Emitted when a frequency has been scanned.
- * Whether a new channel has been found on that frequency or not.
- */
- public signal void frequency_scanned (uint frequency, uint freq_left);
-
- /**
- * @frequency: Frequency of the channel
- * @sid: SID of the channel
- * @name: Name of the channel
- * @network: Name of network the channel is part of
- * @type: What type of channel this is (Radio or TV)
- * @scrambled: Whether the channel is scrambled
- *
- * Emitted when a new channel has been found
- */
- public signal void channel_added (uint frequency, uint sid,
- string name, string network, string type, bool scrambled);
-
- public signal void frontend_stats (double signal_strength,
- double signal_noise_ratio);
-
- /**
- * Emitted when all frequencies have been scanned
- */
- public signal void finished ();
-
- /**
* The DVB device the scanner should use
*/
[DBus (visible = false)]
@@ -73,6 +47,8 @@ namespace DVB {
get { return this.channels; }
}
+ public AdapterType Type { get; construct; }
+
protected ChannelList channels;
/**
@@ -83,17 +59,17 @@ namespace DVB {
/**
* Contains the tuning parameters we use for scanning
*/
- protected GLib.Queue<Gst.Structure> frequencies;
+ private GLib.Queue<Parameter> queue_scanning_params;
/**
* The tuning paramters we're currently using
*/
- protected Gst.Structure? current_tuning_params;
+ private Parameter? current_scanning_param;
/**
* All the frequencies that have been scanned already
*/
- protected HashSet<ScannedItem> scanned_frequencies;
+ private Gee.HashSet<Parameter> scanned_scanning_params;
private static const string BASE_PIDS = "16:17"; // NIT, SDT
private static const string PIPELINE_TEMPLATE = "dvbsrc name=dvbsrc adapter=%u frontend=%u pids=%s
stats-reporting-interval=100 ! tsparse ! fakesink silent=true";
@@ -115,39 +91,16 @@ namespace DVB {
private uint bus_watch_id;
construct {
- this.scanned_frequencies =
- new HashSet<ScannedItem> (ScannedItem.hash, ScannedItem.equal);
+ this.scanned_scanning_params = new Gee.HashSet<Parameter> ();
this.new_channels = new ArrayList<uint> ();
- this.frequencies = new GLib.Queue<Gst.Structure> ();
+ this.queue_scanning_params = new GLib.Queue<Parameter> ();
this.context = new MainContext ();
this.running = false;
}
- /**
- * Setup the pipeline correctly
- */
- protected abstract void prepare();
-
- /**
- * Use the frequency and possibly other data to
- * mark the tuning paramters as already used
- */
- protected abstract ScannedItem get_scanned_item (Gst.Structure structure);
-
- /**
- * Return a new empty channel
- */
- protected abstract Channel get_new_channel ();
-
- /**
- * Retrieve the data from structure and add it to the Channel
- */
- protected abstract void add_values_from_structure_to_channel (Gst.Structure delivery, Channel
channel);
-
- /**
- * Called to parse a line from the initial tuning data
- */
- protected abstract void add_scanning_data_from_string (string line);
+ public Scanner (DVB.Device device, AdapterType type) {
+ Object (Device: device, Type: type);
+ }
/**
* Start the scanner
@@ -209,6 +162,43 @@ namespace DVB {
}
/**
+ * @data: all scanning parameter
+ *
+ * in progress
+ */
+ public bool AddScanningData (GLib.HashTable<string, Variant> data) throws DBusError {
+ unowned Variant _var = data.lookup ("delsys");
+ if (_var != null) {
+ switch (_var.get_string ()) {
+ case "DVBT":
+ DvbTParameter param = new DvbTParameter ();
+ if (param.add_scanning_data (data)) {
+ this.add_to_queue (param);
+ return true;
+ }
+ break;
+ case "DVBC/ANNEX_A":
+ DvbCEuropeParameter param = new DvbCEuropeParameter ();
+ if (param.add_scanning_data (data)) {
+ this.add_to_queue (param);
+ return true;
+ }
+ break;
+ case "DVBS":
+ DvbSParameter param = new DvbSParameter ();
+ if (param.add_scanning_data (data)) {
+ this.add_to_queue (param);
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return false;
+ }
+
+ /**
* @path: Location where the file will be stored
*
* Write all the channels stored in this.Channels to file
@@ -277,35 +267,22 @@ namespace DVB {
if (!Utils.is_readable_file (datafile)) return false;
- DataInputStream reader;
- try {
- reader = new DataInputStream (datafile.read (null));
- } catch (Error e) {
- log.error ("Could not open %s: %s", path, e.message);
- return false;
- }
+ DVB.io.ScanningListReader reader = new DVB.io.ScanningListReader (path);
- string line = null;
- size_t len;
try {
- while ((line = reader.read_line (out len, null)) != null) {
- if (len == 0) continue;
-
- line = line.chug ();
- if (line.has_prefix ("#")) continue;
-
- this.add_scanning_data_from_string (line);
- }
- } catch (Error e) {
- log.error ("Could not read %s: %s", path, e.message);
- return false;
+ reader.read_data ();
+ } catch (KeyFileError e) {
+ log.error ("could not read init file");
+ } catch (FileError e) {
+ log.error ("could not read init file");
}
- try {
- reader.close (null);
- } catch (Error e) {
- log.error ("Could not close file handle: %s", e.message);
- return false;
+ unowned GLib.List<Parameter> scanning_params = reader.Parameters;
+ log.debug ("read %u scanning parameter", scanning_params.length());
+
+ // add to queue
+ foreach (Parameter s in scanning_params) {
+ this.add_to_queue (s);
}
return true;
@@ -332,31 +309,39 @@ namespace DVB {
this.pipeline = null;
}
- this.scanned_frequencies.clear ();
- this.clear_frequencies ();
- this.current_tuning_params = null;
+ this.scanned_scanning_params.clear ();
+ this.clear_queue ();
+ this.current_scanning_param = null;
this.new_channels.clear ();
this.running = false;
}
- protected void clear_frequencies () {
- while (!this.frequencies.is_empty ()) {
- Gst.Structure? s = this.frequencies.pop_head ();
- // Force that gst_structure_free is called
+ protected void clear_queue () {
+ while (!this.queue_scanning_params.is_empty ()) {
+ Parameter? s = this.queue_scanning_params.pop_head ();
s = null;
}
- this.frequencies.clear ();
+ this.queue_scanning_params.clear ();
}
- protected void add_structure_to_scan (owned Gst.Structure structure) {
- if (structure == null) return;
+ protected void add_to_queue (Parameter param) {
+ if (param == null) return;
- ScannedItem item = this.get_scanned_item (structure);
+ if (!isSupported(param.Delsys, this.Type))
+ return;
- if (!this.scanned_frequencies.contains (item)) {
- log.debug ("Queueing new frequency %u", item.Frequency);
- this.frequencies.push_tail ((owned) structure);
- this.scanned_frequencies.add (item);
+ bool eq = false;
+ foreach (Parameter s in this.scanned_scanning_params) {
+ if (s.equal(param)) {
+ eq = true;
+ break;
+ }
+ }
+
+ if (!eq) {
+ log.debug ("Queueing new frequency %u", param.Frequency);
+ this.queue_scanning_params.push_tail (param);
+ this.scanned_scanning_params.add (param);
}
}
@@ -378,13 +363,11 @@ namespace DVB {
this.pmt_arrived = false;
this.locked = false;
- if (this.current_tuning_params != null) {
- uint old_freq;
- this.current_tuning_params.get_uint ("frequency", out old_freq);
- this.frequency_scanned (old_freq, this.frequencies.length);
+ if (this.current_scanning_param != null) {
+ this.frequency_scanned (this.current_scanning_param.Frequency,
this.queue_scanning_params.length);
}
- if (this.frequencies.is_empty()) {
+ if (this.queue_scanning_params.is_empty()) {
message("Finished scanning");
// We don't have all the information for those channels
// remove them
@@ -400,25 +383,25 @@ namespace DVB {
return false;
}
- this.current_tuning_params = this.frequencies.pop_head();
+ this.current_scanning_param = this.queue_scanning_params.pop_head();
// Remember that we already scanned this frequency
- uint freq;
- this.current_tuning_params.get_uint ("frequency", out freq);
+ uint freq = this.current_scanning_param.Frequency;
log.debug("Starting scanning frequency %u (%u left)", freq,
- this.frequencies.get_length ());
+ this.queue_scanning_params.get_length ());
this.pipeline.set_state (Gst.State.READY);
- this.prepare ();
-
- // Reset PIDs
+ // Reset PIDs and parameters
Gst.Element dvbsrc = ((Gst.Bin)this.pipeline).get_by_name ("dvbsrc");
+
+ this.current_scanning_param.prepare (dvbsrc);
+
dvbsrc.set ("pids", BASE_PIDS);
this.check_for_lock_source =
- new TimeoutSource.seconds (5);
+ new TimeoutSource.seconds (10);
this.check_for_lock_source.set_callback (this.check_for_lock);
this.check_for_lock_source.attach (this.context);
@@ -501,6 +484,7 @@ namespace DVB {
new TimeoutSource.seconds (10);
this.wait_for_tables_source.set_callback (this.wait_for_tables);
this.wait_for_tables_source.attach (this.context);
+ this.locked = true;
}
int _signal;
structure.get_int ("signal", out _signal);
@@ -517,36 +501,32 @@ namespace DVB {
*/
}
- protected void on_pat_structure (Gst.Structure structure) {
- log.debug("Received PAT");
+ protected void on_pat_structure (Section section) {
+ /* parse if we have the right nit */
+
+ log.debug("Received PAT, version %d, section number %d, last section number %d",
+ section.version_number, section.section_number, section.last_section_number);
+
+ GenericArray<weak PatProgram> pats = section.get_pat();
Set<uint> pid_set = new HashSet<uint> ();
// add BASE_PIDS
pid_set.add (16);
pid_set.add (17);
- Value programs = structure.get_value ("programs");
- uint size = Gst.ValueList.get_size (programs);
- Value val;
- weak Gst.Structure program;
- // Iterate over programs
- for (uint i=0; i<size; i++) {
- val = Gst.ValueList.get_value (programs, i);
- program = Gst.Value.get_structure (val);
-
- uint sid;
- program.get_uint ("program-number", out sid);
+ PatProgram pat;
+ for (int i = 0; i < pats.length; i++) {
+ pat = pats get(i);
- uint pmt;
- program.get_uint ("pid", out pmt);
+ uint pmt = pat.network_or_program_map_PID;
- pid_set.add (pmt);
+ pid_set.add(pmt);
}
StringBuilder new_pids = new StringBuilder ();
int i = 0;
foreach (uint pid in pid_set) {
- if (i+1 == pid_set.size)
+ if (i + 1 == pid_set.size)
new_pids.append ("%u".printf (pid));
else
new_pids.append ("%u:".printf (pid));
@@ -561,29 +541,23 @@ namespace DVB {
this.pat_arrived = true;
}
- protected void on_sdt_structure (Gst.Structure structure) {
- uint tsid;
- structure.get_uint ("transport-stream-id", out tsid);
+ protected void on_sdt_structure (Section section) {
- log.debug("Received SDT (0x%x)", tsid);
+ unowned SDT sdt = section.get_sdt();
- Value services = structure.get_value ("services");
- uint size = Gst.ValueList.get_size (services);
+ if (!sdt.actual_ts)
+ return;
- Value val;
- weak Gst.Structure service;
- // Iterate over services
- for (uint i=0; i<size; i++) {
- val = Gst.ValueList.get_value (services, i);
- service = Gst.Value.get_structure (val);
+ uint tsid = section.subtable_extension;
+ uint onid = sdt.original_network_id;
+ log.debug("Received SDT (0x%04x.0x%04x) , version %d, section number %d, last section number
%d", onid, tsid,
+ section.version_number, section.section_number, section.last_section_number);
- // Returns "service-%d"
- string name = service.get_name ();
- // Get the number at the end
- int sid = int.parse (name.substring (8, name.length - 8));
+ SDTService service;
+ for (int i = 0; i < sdt.services.length; i++) {
+ service = sdt services get(i);
- if (service.has_field ("name"))
- name = service.get_string ("name");
+ uint sid = service.service_id;
if (!this.channels.contains (sid)) {
this.add_new_channel (sid);
@@ -591,117 +565,185 @@ namespace DVB {
Channel channel = this.channels.get_channel (sid);
- if (service.has_field ("scrambled")) {
- bool scrambled;
- service.get_boolean ("scrambled", out scrambled);
- channel.Scrambled = scrambled;
- } else {
- channel.Scrambled = false;
- }
-
- if (name.validate ()) {
- channel.Name = name.replace ("\\s", " ");
- }
+ channel.Scrambled = service.free_CA_mode;
channel.TransportStreamId = tsid;
- string provider = service.get_string ("provider-name");
- if (provider != null && provider.validate ()) {
- channel.Network = provider;
- } else {
- channel.Network = "";
- }
- log.debug ("Found service 0x%x, %s, scrambled: %s", sid,
- channel.Name, channel.Scrambled.to_string ());
- }
+ Descriptor desc;
+ for (int j = 0; j < service.descriptors.length; j++) {
+ desc = service descriptors get(j);
+ if (desc.tag == DVBDescriptorType.EXTENSION)
+ log.debug ("Extentend descriptor 0x%02x", desc.tag_extension);
+ else
+ log.debug ("Descriptor 0x%02x", desc.tag);
+
+ switch (desc.tag) {
+ case DVBDescriptorType.SERVICE: {
+ DVBServiceType type;
+ string name, provider;
+ desc.parse_dvb_service(out type, out name,
+ out provider);
+
+ channel.Name = name;
+ channel.Network = provider;
+ channel.ServiceType = type;
+ break;
+ }
+ default:
+ break;
- this.sdt_arrived = true;
- }
+ }
- protected void on_nit_structure (Gst.Structure structure) {
- bool actual;
- structure.get_boolean ("actual-network", out actual);
- if (!actual)
- return;
- log.debug("Received NIT");
+ }
+
+ log.debug ("Found service 0x%04x, %s, scrambled: %s", sid,
+ channel.Name, channel.Scrambled.to_string ());
- string name;
- if (structure.has_field ("network-name")) {
- name = structure.get_string ("network-name");
- } else {
- uint nid;
- structure.get_uint ("network-id", out nid);
- name = "%u".printf (nid);
}
- log.debug ("Network name '%s'", name);
+ if (sdt.actual_ts)
+ this.sdt_arrived = true;
+ }
- Value transports = structure.get_value ("transports");
- uint size = Gst.ValueList.get_size (transports);
- Value val;
- weak Gst.Structure transport;
- // Iterate over transports
- for (uint i=0; i<size; i++) {
- val = Gst.ValueList.get_value (transports, i);
- transport = Gst.Value.get_structure (val);
+ protected void on_nit_structure (Section section) {
- uint tsid;
- transport.get_uint ("transport-stream-id", out tsid);
+ unowned NIT nit = section.get_nit();
- if (transport.has_field ("delivery")) {
- Value delivery_val = transport.get_value ("delivery");
- unowned Gst.Structure delivery = Gst.Value.get_structure (
- delivery_val);
+ if (!nit.actual_network)
+ return;
- log.debug ("Received TS 0x%x", tsid);
+ log.debug("Received NIT, version %d, section number %d, last section number %d",
+ section.version_number, section.section_number, section.last_section_number);
- uint freq;
- delivery.get_uint ("frequency", out freq);
- // Takes care of duplicates
- this.add_structure_to_scan (delivery.copy());
+ Descriptor desc;
+ string name = null;
+ for (int i = 0; i < nit.descriptors.length; i++) {
+ desc = nit descriptors get (i);
+ if (desc.tag == DVBDescriptorType.NETWORK_NAME) {
+ desc.parse_dvb_network_name (out name);
+ break;
}
+ }
- if (transport.has_field ("channels")) {
- Value channels = transport.get_value ("channels");
- uint channels_size = Gst.ValueList.get_size (channels);
+ uint nid = nit.network_id;
+ if (name == null)
+ name = "%u".printf (nid);
- Value channel_val;
- weak Gst.Structure channel_struct;
- // Iterate over channels
- for (int j=0; j<channels_size; j++) {
- channel_val = Gst.ValueList.get_value (channels, j);
- channel_struct = Gst.Value.get_structure (channel_val);
+ log.debug ("Network name '%s', id = 0x%04x", name, nid);
- uint sid;
- channel_struct.get_uint ("service-id", out sid);
+ NITStream stream;
+ for (int i = 0; i < nit.streams.length; i++) {
+ stream = nit streams get (i);
- if (!this.channels.contains (sid)) {
- this.add_new_channel (sid);
- }
+ uint tsid = stream.transport_stream_id;
+ uint onid = stream.original_network_id;
- Channel dvb_channel = this.channels.get_channel (sid);
+ log.debug ("Received TS 0x%04x, on_id = 0x%04x", tsid, onid);
+ // descriptors
- if (name.validate ()) {
- dvb_channel.Network = name;
- } else {
- dvb_channel.Network = "";
- }
+ for (int j = 0; j < stream.descriptors.length; j++) {
+ desc = stream descriptors get (j);
- uint lcnumber;
- channel_struct.get_uint ("logical-channel-number", out lcnumber);
- dvb_channel.LogicalChannelNumber = lcnumber;
+ if (desc.tag == DVBDescriptorType.EXTENSION)
+ log.debug ("Extentend desriptor 0x%02x", desc.tag_extension);
+ else
+ log.debug ("Desriptor 0x%02x", desc.tag);
+
+ switch (desc.tag) {
+ case DVBDescriptorType.TERRESTRIAL_DELIVERY_SYSTEM:
+ TerrestrialDeliverySystemDescriptor tdesc;
+ desc.parse_terrestrial_delivery_system (out tdesc);
+ DVBCodeRate ratehp, ratelp;
+
+ if (tdesc.priority) {
+ ratehp = tdesc.code_rate_hp;
+ ratelp = DVBCodeRate.NONE;
+ } else {
+ ratehp = DVBCodeRate.NONE;
+ ratelp = tdesc.code_rate_lp;
+ }
+
+ DvbTParameter dvbtp = new DvbTParameter.with_parameter (
+ tdesc.frequency, tdesc.bandwidth, tdesc.guard_interval,
+ tdesc.transmission_mode, tdesc.hierarchy, tdesc.constellation,
+ ratelp, ratehp);
+
+ if (this.current_scanning_param.Frequency == tdesc.frequency) {
+ lock (this.channels) {
+ foreach (Channel channel in this.channels) {
+ if (channel.Param.Frequency == tdesc.frequency)
+ channel.Param = dvbtp;
+ }
+ }
+ this.current_scanning_param = dvbtp;
+ } else
+ this.add_to_queue (dvbtp);
+
+ break;
+ case DVBDescriptorType.CABLE_DELIVERY_SYSTEM:
+ CableDeliverySystemDescriptor cdesc;
+ desc.parse_cable_delivery_system (out cdesc);
+
+ DvbCEuropeParameter dvbcp = new DvbCEuropeParameter.with_parameter (
+ cdesc.frequency, cdesc.symbol_rate, cdesc.modulation,
+ cdesc.fec_inner);
+
+ if (this.current_scanning_param.Frequency == cdesc.frequency)
+ this.current_scanning_param = dvbcp;
+ else
+ this.add_to_queue (dvbcp);
+
+ break;
+ case DVBDescriptorType.SATELLITE_DELIVERY_SYSTEM:
+ SatelliteDeliverySystemDescriptor sdesc;
+ desc.parse_satellite_delivery_system (out sdesc);
+ float position;
+
+ if (!sdesc.modulation_system) {
+ if (sdesc.modulation_type != ModulationType.QPSK) {
+ // TODO: Turbo
+ } else {
+ // DVB-S
+ position = sdesc.orbital_position;
+ if (!sdesc.west_east) {
+ // west
+ position *= -1;
+ }
+ log.debug ("Orbital position: %f", position);
+
+ DvbSParameter dvbsp = new DvbSParameter.with_parameter (
+ sdesc.frequency, sdesc.symbol_rate, position,
+ sdesc.polarization, sdesc.fec_inner);
+
+ if (this.current_scanning_param.Frequency == sdesc.frequency)
+ this.current_scanning_param = dvbsp;
+ else
+ this.add_to_queue (dvbsp);
+ }
+ } else {
+ // TODO: DVB-S2
+ }
+ break;
+ default:
+ break;
}
+
}
+
}
- this.nit_arrived = true;
+ if (nit.actual_network)
+ this.nit_arrived = true;
}
- protected void on_pmt_structure (Gst.Structure structure) {
- log.debug ("Received PMT");
+ protected void on_pmt_structure (Section section) {
+
+ log.debug ("Received PMT, version %d, section number %d, last section number %d",
+ section.version_number, section.section_number, section.last_section_number);
- uint program_number;
- structure.get_uint ("program-number", out program_number);
+ unowned PMT pmt = section.get_pmt();
+
+ uint program_number = pmt.program_number;
if (!this.channels.contains (program_number)) {
this.add_new_channel (program_number);
@@ -709,42 +751,47 @@ namespace DVB {
Channel dvb_channel = this.channels.get_channel (program_number);
- Value streams = structure.get_value ("streams");
- uint size = Gst.ValueList.get_size (streams);
-
- Value stream_val;
- weak Gst.Structure stream;
- // Iterate over streams
- for (int i=0; i<size; i++) {
- stream_val = Gst.ValueList.get_value (streams, i);
- stream = Gst.Value.get_structure (stream_val);
-
- uint pid;
- stream.get_uint ("pid", out pid);
+ PMTStream stream;
+ for (int i = 0; i < pmt.streams.length; i++) {
+ stream = pmt streams get(i);
- // See ISO/IEC 13818-1 Table 2-29
- uint stream_type;
- stream.get_uint ("stream-type", out stream_type);
+ uint pid = stream.pid;
- switch (stream_type) {
- case 0x01:
- case 0x02:
- case 0x1b: /* H.264 video stream */
- log.debug ("Found video PID 0x%x for channel 0x%x",
+ switch (stream.stream_type) {
+ case StreamType.VIDEO_MPEG1:
+ case StreamType.VIDEO_MPEG2:
+ case StreamType.VIDEO_H264:
+ log.debug ("Found video PID 0x%04x for channel 0x%04x",
pid, program_number);
dvb_channel.VideoPID = pid;
- break;
- case 0x03:
- case 0x04:
- case 0x0f:
- case 0x11:
- log.debug ("Found audio PID 0x%x for channel 0x%x",
+ break;
+ case StreamType.AUDIO_MPEG1:
+ case StreamType.AUDIO_MPEG2:
+ case StreamType.AUDIO_AAC_ADTS:
+ case StreamType.AUDIO_AAC_LATM:
+ case 0x81: // ATSC AC3
+ case 0x87: // ATSC EAC3
+ log.debug ("Found audio PID 0x%04x for channel 0x%04x",
pid, program_number);
- dvb_channel.AudioPIDs.add (pid);
- break;
+ // check is pid added ?
+ if (!dvb_channel.AudioPIDs.contains (pid))
+ dvb_channel.AudioPIDs.add (pid);
+ break;
+ case StreamType.PRIVATE_PES_PACKETS:
+ // we must looking for dts or ac3 descriptors
+ if (find_descriptor (stream.descriptors, DVBDescriptorType.DTS) != null
+ || find_descriptor (stream.descriptors, DVBDescriptorType.AC3) != null
+ || find_descriptor (stream.descriptors, DVBDescriptorType.ENHANCED_AC3) != null)
{
+ log.debug ("Found audio PID 0x%04x for channel 0x%04x",
+ pid, program_number);
+ // check is pid added ?
+ if (!dvb_channel.AudioPIDs.contains (pid))
+ dvb_channel.AudioPIDs.add (pid);
+ }
+ break;
default:
- log.debug ("Other stream type: 0x%02x", stream_type);
- break;
+ log.debug ("Other stream type: 0x%04x", stream.stream_type);
+ break;
}
}
@@ -754,22 +801,41 @@ namespace DVB {
protected bool bus_watch_func (Gst.Bus bus, Gst.Message message) {
switch (message.type) {
case Gst.MessageType.ELEMENT: {
- unowned Gst.Structure structure = message.get_structure ();
- string structure_name = structure.get_name();
- if (structure_name == "dvb-frontend-stats")
- this.on_dvb_frontend_stats_structure (structure);
- else if (structure_name == "dvb-read-failure")
- this.on_dvb_read_failure_structure ();
- else if (structure_name == "sdt")
- this.on_sdt_structure (structure);
- else if (structure_name == "nit")
- this.on_nit_structure (structure);
- else if (structure_name == "pat")
- this.on_pat_structure (structure);
- else if (structure_name == "pmt")
- this.on_pmt_structure (structure);
- else
- return true; /* We are not interested in the message */
+ Section section = message_parse_mpegts_section(message);
+
+ if (section == null) {
+ weak Gst.Structure structure = message.get_structure ();
+ string structure_name = structure.get_name();
+ if (structure_name == "dvb-frontend-stats")
+ this.on_dvb_frontend_stats_structure (structure);
+ else if (structure_name == "dvb-read-failure")
+ this.on_dvb_read_failure_structure ();
+ else return true;
+ }
+ else {
+ switch (section.section_type) {
+ case SectionType.PAT: {
+ this.on_pat_structure (section);
+ break;
+ }
+ case SectionType.PMT: {
+ this.on_pmt_structure (section);
+ break;
+ }
+ case SectionType.NIT: {
+ this.on_nit_structure (section);
+ break;
+ }
+ case SectionType.SDT: {
+ this.on_sdt_structure (section);
+ break;
+ }
+ default: {
+ return true;
+ }
+ }
+ }
+
break;
}
case Gst.MessageType.ERROR: {
@@ -784,7 +850,7 @@ namespace DVB {
}
// NIT gives us the transport stream, SDT links SID and TS ID
- if (this.nit_arrived && this.sdt_arrived && this.pat_arrived) {
+ if (this.nit_arrived && this.sdt_arrived && this.pat_arrived && this.pmt_arrived) {
// We received all tables at least once. Add valid channels.
lock (this.new_channels) {
ArrayList<uint> del_channels = new ArrayList<uint> ();
@@ -795,8 +861,8 @@ namespace DVB {
// because we didn't came across the sdt or pmt, yet
if (channel.is_valid ()) {
string type = (channel.is_radio ()) ? "Radio" : "TV";
- log.debug ("Channel added: %s", channel.to_string ());
- this.channel_added (channel.Frequency, sid,
+ log.debug ("Channel added: %s", channel.Name);
+ this.channel_added (channel.Param.Frequency, sid,
channel.Name, channel.Network, type,
channel.Scrambled);
// Mark channel for deletion of this.new_channels
@@ -827,14 +893,12 @@ namespace DVB {
return true;
}
- protected void add_new_channel (uint sid) {
+ private void add_new_channel (uint sid) {
log.debug ("Adding new channel with SID 0x%x", sid);
- Channel new_channel = this.get_new_channel ();
+ Channel new_channel = new Channel.without_schedule ();
new_channel.Sid = sid;
- // add values from Gst.Structure to Channel
- this.add_values_from_structure_to_channel (
- this.current_tuning_params,
- new_channel);
+ // add values Parameters
+ new_channel.Param = this.current_scanning_param;
this.channels.add (new_channel);
lock (this.new_channels) {
this.new_channels.add (sid);
diff --git a/src/Settings.vala b/src/Settings.vala
index 26cdf76..7227fc5 100644
--- a/src/Settings.vala
+++ b/src/Settings.vala
@@ -36,14 +36,6 @@ namespace DVB {
private static const string STREAMING_SECTION = "streaming";
private static const string INTERFACE = "interface";
- private static const string DEVICE_SECTION_PREFIX = "device.";
- private static const string DEVICE_NAME = "name";
- private static const string DEVICE_TYPE = "type";
- private static const string DEVICE_ADAPTER = "adapter";
- private static const string DEVICE_FRONTEND = "frontend";
- private static const string DEVICE_CHANNELS_FILE = "channels_file";
- private static const string DEVICE_RECORDINGS_DIR = "recordings_dir";
-
private static const int DEFAULT_MARGIN_START = 5;
private static const int DEFAULT_MARGIN_END = 5;
private static const int DEFAULT_SCAN_INTERVAL = 30;
@@ -108,37 +100,6 @@ namespace DVB {
return val;
}
- public Gee.List<Device> get_fake_devices () {
- Gee.List<Device> devices = new Gee.ArrayList<Device> ();
- string[] groups = this.keyfile.get_groups ();
- foreach (string group in groups) {
- if (group.has_prefix (DEVICE_SECTION_PREFIX)) {
- try {
- Device dev = this.get_device (group);
- devices.add (dev);
- } catch (KeyFileError e) {
- log.warning ("%s", e.message);
- }
- }
- }
- return devices;
- }
-
- private Device get_device (string group) throws KeyFileError {
- string name = this.get_string (group, DEVICE_NAME);
- int adapter = this.get_integer (group, DEVICE_ADAPTER);
- int frontend = this.get_integer (group, DEVICE_FRONTEND);
-
- string typestr = this.get_string (group, DEVICE_TYPE);
- AdapterType type = Device.get_type_from_string (typestr);
-
- File channels = File.new_for_path (this.get_string (group, DEVICE_CHANNELS_FILE));
- File rec_dir = File.new_for_path (this.get_string (group, DEVICE_RECORDINGS_DIR));
-
- return Device.new_set_type (adapter, frontend, channels, rec_dir,
- name, type);
- }
-
public File get_settings_file () {
File config_dir = File.new_for_path (
Environment.get_user_config_dir ());
diff --git a/src/database/ConfigStore.vala b/src/database/ConfigStore.vala
index 2fed09f..d69bd34 100644
--- a/src/database/ConfigStore.vala
+++ b/src/database/ConfigStore.vala
@@ -24,13 +24,16 @@ namespace DVB.database {
public interface ConfigStore : GLib.Object {
public abstract Gee.List<DeviceGroup> get_all_device_groups () throws SqlError;
+ public abstract DeviceGroup? get_device_group (uint group_id) throws SqlError;
+ public abstract bool is_last_device (uint group_id) throws SqlError;
+ public abstract bool is_group_member (Device dev, DeviceGroup group) throws SqlError;
public abstract bool add_device_group (DeviceGroup dev_group) throws SqlError;
public abstract bool remove_device_group (DeviceGroup devgroup) throws SqlError;
public abstract bool add_device_to_group (Device dev, DeviceGroup devgroup) throws SqlError;
public abstract bool remove_device_from_group (Device dev, DeviceGroup devgroup) throws SqlError;
public abstract bool update_from_group (DeviceGroup devgroup) throws SqlError;
- public abstract bool get_parent_group (uint adapter, uint frontend, out uint group_id) throws
SqlError;
+ public abstract bool get_parent_groups (uint adapter, uint frontend, out uint[] group_ids) throws
SqlError;
public abstract bool add_channel_group (string name, out int channel_group_id) throws SqlError;
public abstract bool remove_channel_group (int group_id) throws SqlError;
diff --git a/src/database/sqlite/SqliteConfigTimersStore.vala
b/src/database/sqlite/SqliteConfigTimersStore.vala
index ec7dd71..8e29e6c 100644
--- a/src/database/sqlite/SqliteConfigTimersStore.vala
+++ b/src/database/sqlite/SqliteConfigTimersStore.vala
@@ -28,7 +28,7 @@ namespace DVB.database.sqlite {
private static Logger log = LogManager.getLogManager().getDefaultLogger();
- private static const int VERSION = 1;
+ private static const int VERSION = 2;
private static const string CREATE_DEVICE_GROUPS =
"""CREATE TABLE device_groups (
@@ -44,7 +44,7 @@ namespace DVB.database.sqlite {
group_id INTEGER,
adapter INTEGER,
frontend INTEGER,
- PRIMARY KEY(adapter, frontend))""";
+ PRIMARY KEY(group_id, adapter, frontend))""";
private static const string CREATE_TIMERS =
"""CREATE TABLE timers (
@@ -77,12 +77,18 @@ namespace DVB.database.sqlite {
channel_group_id INTEGER,
PRIMARY KEY(sid, group_id, channel_group_id))""";
+ private static const string SELECT_GROUP =
+ "SELECT * FROM device_groups WHERE group_id=?";
+
private static const string SELECT_ALL_GROUPS =
"SELECT * FROM device_groups";
private static const string SELECT_DEVICES =
"SELECT * FROM devices WHERE group_id=?";
+ private static const string SELECT_DEVICE =
+ "SELECT * FROM devices WHERE group_id=? AND adapter=? AND frontend=?";
+
private static const string DELETE_GROUP =
"DELETE FROM device_groups WHERE group_id=?";
@@ -144,6 +150,7 @@ namespace DVB.database.sqlite {
"SELECT sid FROM channels WHERE group_id=? AND channel_group_id=?";
private Statement select_devices_statement;
+ private Statement select_device_group_statement;
private Statement delete_group_statement;
private Statement insert_group_statement;
private Statement update_group_statement;
@@ -192,6 +199,8 @@ namespace DVB.database.sqlite {
public override void on_open () {
this.db.prepare (SELECT_DEVICES, -1,
out this.select_devices_statement);
+ this.db.prepare (SELECT_GROUP, -1,
+ out this.select_device_group_statement);
this.db.prepare (DELETE_GROUP, -1,
out this.delete_group_statement);
this.db.prepare (INSERT_GROUP, -1,
@@ -247,11 +256,7 @@ namespace DVB.database.sqlite {
while (statement.step () == Sqlite.ROW) {
int group_id = statement.column_int (0);
-
- if (this.select_devices_statement.bind_int (1, group_id) != Sqlite.OK) {
- this.throw_last_error ();
- continue;
- }
+ AdapterType type = (AdapterType)statement.column_int (1);
File channels_file = File.new_for_path (
statement.column_text (2));
@@ -259,48 +264,93 @@ namespace DVB.database.sqlite {
File rec_dir = File.new_for_path (
statement.column_text (3));
- // Get devices of group
- Gee.List<Device> devs = new ArrayList<Device> ();
- Device ref_dev = null;
- while (this.select_devices_statement.step () == Sqlite.ROW) {
- uint adapter =
- (uint)this.select_devices_statement.column_int (1);
- uint frontend =
- (uint)this.select_devices_statement.column_int (2);
-
- if (ref_dev == null) {
- try {
- ref_dev = Device.new_full (adapter, frontend,
- channels_file, rec_dir);
- } catch (DeviceError e) {
- log.error ("Could not create device: %s", e.message);
- }
- } else {
- devs.add (Device.new_with_type (adapter, frontend));
- }
- }
- this.select_devices_statement.reset ();
-
- // No devices for this group
- if (ref_dev == null) {
- log.debug ("Group %d has no devices", group_id);
- continue;
- }
-
// Create device group
- DeviceGroup group = new DeviceGroup ((uint)group_id, ref_dev,
- !Main.get_disable_epg_scanner());
+ DeviceGroup group = new DeviceGroup ((uint)group_id, channels_file, rec_dir,
+ type, !Main.get_disable_epg_scanner ());
group.Name = statement.column_text (4);
- for (int i=0; i<devs.size; i++)
- group.add (devs.get (i));
-
groups.add (group);
}
return groups;
}
+ public DeviceGroup? get_device_group (uint group_id) throws SqlError {
+ DeviceGroup? group = null;
+
+ if (this.select_device_group_statement.bind_int (1, (int)group_id) != Sqlite.OK) {
+ this.throw_last_error ();
+ log.debug ("cannot read device group data");
+ return group;
+ }
+
+
+ this.begin_transaction ();
+ if (this.select_device_group_statement.step () == Sqlite.ROW) {
+
+ AdapterType type = (AdapterType)this.select_device_group_statement.column_int(1);
+
+ File channels_file = File.new_for_path (
+ this.select_device_group_statement.column_text (2));
+
+ File rec_dir = File.new_for_path (
+ this.select_device_group_statement.column_text (3));
+
+ // Create device group
+ group = new DeviceGroup ((uint)group_id, channels_file, rec_dir,
+ type, !Main.get_disable_epg_scanner());
+ group.Name = this.select_device_group_statement.column_text (4);
+ }
+
+ this.select_device_group_statement.reset ();
+
+ this.end_transaction ();
+
+ return group;
+ }
+
+ public bool is_group_member (Device dev, DeviceGroup group) throws SqlError {
+ Statement statement;
+
+ if (this.db.prepare (SELECT_DEVICE, -1, out statement) != Sqlite.OK) {
+ this.throw_last_error ();
+ return false;
+ }
+
+ if (statement.bind_int (1, (int)group.Id) != Sqlite.OK
+ || statement.bind_int (2, (int)dev.Adapter) != Sqlite.OK
+ || statement.bind_int (3, (int)dev.Frontend) != Sqlite.OK) {
+ this.throw_last_error ();
+ return false;
+ }
+
+ if (statement.step () == Sqlite.ROW)
+ return true;
+
+ return false;
+ }
+
+ public bool is_last_device (uint group_id) throws SqlError {
+ bool val = false;
+
+ if (this.select_devices_statement.bind_int (1, (int)group_id) !=Sqlite.OK) {
+ this.throw_last_error ();
+ return val;
+ }
+
+ this.begin_transaction ();
+
+ if (this.select_devices_statement.step() != Sqlite.ROW) {
+ if (this.select_devices_statement.data_count () == 0)
+ val = true;
+ }
+
+ this.select_devices_statement.reset ();
+
+ this.end_transaction ();
+ return val;
+ }
+
public bool add_device_group (DeviceGroup dev_group) throws SqlError {
if (this.contains_group (dev_group.Id)) return false;
@@ -323,9 +373,6 @@ namespace DVB.database.sqlite {
}
this.insert_group_statement.reset ();
- foreach (Device dev in dev_group)
- this.add_device_to_group (dev, dev_group);
-
this.end_transaction ();
return true;
@@ -360,8 +407,8 @@ namespace DVB.database.sqlite {
return true;
}
- public bool get_parent_group (uint adapter, uint frontend, out uint group_id) throws SqlError {
- group_id = 0;
+ public bool get_parent_groups (uint adapter, uint frontend, out uint[] group_ids) throws SqlError {
+ group_ids = null;
if (this.select_group_of_device_statement.bind_int (1, (int)adapter) != Sqlite.OK
|| this.select_group_of_device_statement.bind_int (2, (int)frontend) != Sqlite.OK)
@@ -371,8 +418,12 @@ namespace DVB.database.sqlite {
}
bool ret = false;
+ int count = this.select_group_of_device_statement.column_count ();
+ group_ids = new uint[count];
while (this.select_group_of_device_statement.step () == Sqlite.ROW) {
- group_id = this.select_group_of_device_statement.column_int (0);
+ for (int i = 0; i < count; i++) {
+ group_ids[i] = this.select_group_of_device_statement.column_int (i);
+ }
ret = true;
}
this.select_group_of_device_statement.reset ();
diff --git a/src/database/sqlite/SqliteEPGStore.vala b/src/database/sqlite/SqliteEPGStore.vala
index b2fb980..b718190 100644
--- a/src/database/sqlite/SqliteEPGStore.vala
+++ b/src/database/sqlite/SqliteEPGStore.vala
@@ -371,7 +371,7 @@ namespace DVB.database.sqlite {
statement.column_text (7));
// We don't save those
event.audio_components = null;
- event.video_components = null;
+ event.video_component = null;
event.teletext_components = null;
return event;
diff --git a/src/dbus/IDBusDeviceGroup.vala b/src/dbus/IDBusDeviceGroup.vala
index d3c7558..8154ec9 100644
--- a/src/dbus/IDBusDeviceGroup.vala
+++ b/src/dbus/IDBusDeviceGroup.vala
@@ -31,7 +31,7 @@ namespace DVB {
* @returns: Name of adapter type the group holds
* or an empty string when group with given id doesn't exist.
*/
- public abstract string GetType () throws DBusError;
+ public abstract AdapterType GetType () throws DBusError;
/**
* @returns: Object path of the device's recorder
diff --git a/src/dbus/IDBusManager.vala b/src/dbus/IDBusManager.vala
index 9341349..c8110a1 100644
--- a/src/dbus/IDBusManager.vala
+++ b/src/dbus/IDBusManager.vala
@@ -22,13 +22,15 @@ using GLib;
namespace DVB {
public struct ChannelGroupInfo {
- public int id;
- public string name;
+ public int id;
+ public string name;
}
public struct AdapterInfo {
public string name;
- public string type;
+ public bool type_t;
+ public bool type_s;
+ public bool type_c;
}
[DBus (name = "org.gnome.DVB.Manager")]
@@ -40,13 +42,14 @@ namespace DVB {
/**
* @adapter: Number of the device's adapter
* @frontend: Number of the device's frontend
+ * @type: the type
* @opath: Object path of the scanner service
* @dbusiface: DBus interface of the scanner service
* @returns: TRUE on success
*
* Get the object path of the channel scanner for this device.
*/
- public abstract bool GetScannerForDevice (uint adapter, uint frontend,
+ public abstract bool GetScannerForDevice (uint adapter, uint frontend, AdapterType type,
out ObjectPath opath, out string dbusiface) throws DBusError;
/**
@@ -64,6 +67,7 @@ namespace DVB {
/**
* @adapter: Number of the device's adapter
* @frontend: Number of the device's frontend
+ * @type: the type of the group
* @channels_conf: Path to channels.conf for this device
* @recordings_dir: Path where the recordings should be stored
* @name: Name of group
@@ -74,7 +78,7 @@ namespace DVB {
* all other devices of this group will inherit the settings
* of the reference device).
*/
- public abstract bool AddDeviceToNewGroup (uint adapter, uint frontend,
+ public abstract bool AddDeviceToNewGroup (uint adapter, uint frontend, AdapterType type,
string channels_conf, string recordings_dir, string name) throws DBusError;
/**
@@ -87,7 +91,7 @@ namespace DVB {
* is returned.
*/
public abstract bool GetNameOfRegisteredDevice (uint adapter, uint frontend,
- out string name) throws DBusError;
+ out string name) throws DBusError;
/**
* @returns: the numner of configured device groups
@@ -116,7 +120,7 @@ namespace DVB {
* @returns: informations about all connected
* devices retrieved via udev
*/
- public abstract GLib.HashTable<string, string>[] GetDevices () throws DBusError;
+ public abstract GLib.HashTable<string, string>[] GetDevices () throws DBusError;
/**
* @info: type and name of adapter
diff --git a/src/io/ChannelListReader.vala b/src/io/ChannelListReader.vala
index a07df10..667cb2f 100644
--- a/src/io/ChannelListReader.vala
+++ b/src/io/ChannelListReader.vala
@@ -19,6 +19,7 @@
using GLib;
using DVB.Logging;
+using GstMpegTs;
namespace DVB.io {
@@ -29,287 +30,118 @@ namespace DVB.io {
public ChannelList channels {get; construct;}
public AdapterType Type {get; construct;}
+ private KeyFile file;
+
public ChannelListReader (ChannelList channels, AdapterType type) {
base (channels: channels, Type: type);
+ this.file = new KeyFile ();
+ this.file.set_list_separator (' ');
}
public void read_into () throws Error {
return_if_fail (this.channels.channels_file != null);
- var reader = new DataInputStream (
- this.channels.channels_file.read (null));
-
- string line = null;
- size_t len;
- while ((line = reader.read_line (out len, null)) != null) {
- if (len > 0) {
- Channel c = this.parse_line (line);
- if (c != null) {
- channels.add (c);
- } else
- warning ("Could not parse channel");
- }
- }
- reader.close (null);
- }
+ try {
+ this.file.load_from_file (this.channels.channels_file.get_path(), KeyFileFlags.NONE);
+
+ foreach (unowned string group in this.file.get_groups ()) {
+ log.debug ("Channel: %s", group);
+
+ // parse Delivery system stuff
+ Channel c = null;
+ switch (this.file.get_string (group, "DELIVERY_SYSTEM")) {
+ case "DVBT":
+ c = parse_dvb_t (group);
+ break;
+ case "DVBC/ANNEX_A":
+ c = parse_dvb_c (group);
+ break;
+ case "DVBS":
+ c = parse_dvb_s (group);
+ break;
+ default:
+ break;
+ }
- private Channel? parse_line (string line) {
- Channel? c = null;
- switch (this.Type) {
- case AdapterType.DVB_T:
- c = parse_terrestrial_channel (line);
- break;
+ if (c == null) continue;
- case AdapterType.DVB_S:
- c = parse_satellite_channel (line);
- break;
+ c.Sid = (uint)this.file.get_uint64 (group, "SERVICE_ID");
+ c.Name = this.file.get_string (group, "SERVICE_NAME");
+ c.TransportStreamId = (uint)this.file.get_uint64 (group, "TRANSPORT_STREAM_ID");
+ c.Scrambled = this.file.get_boolean (group, "SCRAMBLED");
+ c.ServiceType = (DVBServiceType)this.file.get_uint64 (group, "SERVICE_TYPE");
+ if (this.file.has_key (group, "VIDEO_PID"))
+ c.VideoPID = (uint)this.file.get_uint64 (group, "VIDEO_PID");
- case AdapterType.DVB_C:
- c = parse_cable_channel (line);
- break;
+ if (this.file.has_key (group, "AUDIO_PID")) {
+ uint[] apids = (uint[])this.file.get_integer_list (group, "AUDIO_PID");
+ for (uint i = 0; i < apids.length; i++)
+ c.AudioPIDs.add(apids[i]);
+ }
- default:
- log.error ("Unknown adapter type");
- break;
+ if (c.is_valid ())
+ channels.add (c);
+ else
+ warning ("Could not parse channel");
+ }
+ } catch (FileError e) {
+ log.error ("Can not open channel file: %s", e.message);
+ } catch (KeyFileError e) {
+ log.error ("%s", e.message);
}
- if (c != null && c.is_valid ()) {
- return c;
- } else {
- string val = (c == null) ? "(null)" : c.to_string ();
- warning ("Channel is not valid: %s", val);
- return null;
- }
}
- /**
- * @line: The line to parse
- * @returns: #TerrestrialChannel representing that line
- *
- * A line looks like
- * Das
Erste:212500000:INVERSION_AUTO:BANDWIDTH_7_MHZ:FEC_3_4:FEC_1_2:QAM_16:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_4:HIERARCHY_NONE:513:514:32
- */
- private TerrestrialChannel? parse_terrestrial_channel (string line) {
- var channel = new TerrestrialChannel (this.channels.GroupId);
+ private Channel? parse_dvb_t (string group) throws KeyFileError, FileError {
+ if (this.Type != AdapterType.TERRESTRIAL) return null;
- string[] fields = line.split(":");
+ Channel c = new Channel (this.channels.GroupId);
+ DvbTParameter param = new DvbTParameter.with_parameter ((uint)this.file.get_uint64 (group,
"FREQUENCY"),
+ (uint)this.file.get_uint64 (group, "BANDWIDTH_HZ"),
+ getGuardIntervalEnum (this.file.get_string (group, "GUARD_INTERVAL")),
+ getTransmissionModeEnum (this.file.get_string (group, "TRANSMISSION_MODE")),
+ getHierarchyEnum (this.file.get_string (group, "HIERARCHY")),
+ getModulationEnum (this.file.get_string (group, "MODULATION")),
+ getCodeRateEnum (this.file.get_string (group, "CODE_RATE_LP")),
+ getCodeRateEnum (this.file.get_string (group, "CODE_RATE_HP")));
- int i=0;
- string val;
- bool failed = false;
- while ( (val = fields[i]) != null) {
- if (i == 0) {
- if (val.validate())
- channel.Name = val;
- else {
- warning ("Bad UTF-8 encoded channel name");
- channel.Name = "Bad encoding";
- }
- } else if (i == 1) {
- channel.Frequency = (uint)int.parse (val);
- } else if (i == 2) {
- int eval;
- if (get_value_with_prefix (typeof(DvbSrcInversion), val,
- "DVB_DVB_SRC_INVERSION_", out eval)) {
- channel.Inversion = (DvbSrcInversion) eval;
- } else {
- failed = true;
- break;
- }
- } else if (i == 3) {
- int eval;
- if (get_value_with_prefix (typeof(DvbSrcBandwidth), val,
- "DVB_DVB_SRC_BANDWIDTH_", out eval)) {
- channel.Bandwidth = (DvbSrcBandwidth) eval;
- } else {
- failed = true;
- break;
- }
- } else if (i == 4) {
- int eval;
- if (get_value_with_prefix (typeof(DvbSrcCodeRate), val,
- "DVB_DVB_SRC_CODE_RATE_", out eval)) {
- channel.CodeRateHP = (DvbSrcCodeRate) eval;
- } else {
- failed = true;
- break;
- }
- } else if (i == 5) {
- int eval;
- if (get_value_with_prefix (typeof(DvbSrcCodeRate), val,
- "DVB_DVB_SRC_CODE_RATE_", out eval)) {
- channel.CodeRateLP = (DvbSrcCodeRate) eval;
- } else {
- failed = true;
- break;
- }
- } else if (i == 6) {
- int eval;
- if (get_value_with_prefix (typeof(DvbSrcModulation), val,
- "DVB_DVB_SRC_MODULATION_", out eval)) {
- channel.Constellation = (DvbSrcModulation) eval;
- } else {
- failed = true;
- break;
- }
- } else if (i == 7) {
- int eval;
- if (get_value_with_prefix (typeof(DvbSrcTransmissionMode),
- val, "DVB_DVB_SRC_TRANSMISSION_MODE_", out eval)) {
- channel.TransmissionMode = (DvbSrcTransmissionMode) eval;
- } else {
- failed = true;
- break;
- }
- } else if (i == 8) {
- int eval;
- if (get_value_with_prefix (typeof(DvbSrcGuard), val,
- "DVB_DVB_SRC_GUARD_", out eval)) {
- channel.GuardInterval = (DvbSrcGuard) eval;
- } else {
- failed = true;
- break;
- }
- } else if (i == 9) {
- int eval;
- if (get_value_with_prefix (typeof(DvbSrcHierarchy), val,
- "DVB_DVB_SRC_HIERARCHY_", out eval)) {
- channel.Hierarchy = (DvbSrcHierarchy) eval;
- } else {
- failed = true;
- break;
- }
- } else if (i == 10) {
- channel.VideoPID = (uint)int.parse (val);
- } else if (i == 11) {
- channel.AudioPIDs.add ((uint)int.parse (val));
- } else if (i == 12) {
- channel.Sid = (uint)int.parse (val);
- }
-
- i++;
- }
+ c.Param = param;
- if (failed) return null;
- else return channel;
+ return c;
}
- /**
- *
- * A line looks like
- * Das Erste:11836:h:0:27500:101:102:28106
- */
- private SatelliteChannel? parse_satellite_channel (string line) {
- var channel = new SatelliteChannel (this.channels.GroupId);
+ private Channel? parse_dvb_s (string group) throws KeyFileError, FileError {
+ if (this.Type != AdapterType.SATELLITE) return null;
- string[] fields = line.split(":");
+ Channel c = new Channel (this.channels.GroupId);
+ DvbSParameter param = new DvbSParameter.with_parameter ((uint)this.file.get_uint64 (group,
"FREQUENCY"),
+ (uint)this.file.get_uint64 (group, "SYMBOL_RATE"),
+ (float)this.file.get_double (group, "ORBITAL_POSITION"),
+ getPolarizationEnum (this.file.get_string (group, "POLARIZATION")),
+ getCodeRateEnum (this.file.get_string (group, "INNER_FEC")));
- int i=0;
- string val;
- while ( (val = fields[i]) != null) {
- if (i == 0) {
- if (val.validate())
- channel.Name = val;
- else {
- warning ("Bad UTF-8 encoded channel name");
- channel.Name = "Bad encoding";
- }
- } else if (i == 1) {
- // frequency is stored in MHz
- channel.Frequency = (uint)(int.parse (val) * 1000);
- } else if (i == 2) {
- channel.Polarization = val;
- } else if (i == 3) {
- // Sat number
- channel.DiseqcSource = int.parse (val);
- } else if (i == 4) {
- // symbol rate is stored in kBaud
- channel.SymbolRate = (uint)int.parse (val);
- } else if (i == 5) {
- channel.VideoPID = (uint)int.parse (val);
- } else if (i == 6) {
- channel.AudioPIDs.add ((uint)int.parse (val));
- } else if (i == 7) {
- channel.Sid = (uint)int.parse (val);
- }
+ if (this.file.has_key (group, "SAT_NUMBER"))
+ param.DiseqcSource = this.file.get_integer (group, "SAT_NUMBER");
- i++;
- }
+ c.Param = param;
- return channel;
+ return c;
}
- /**
- *
- * line looks like
- * ProSieben:330000000:INVERSION_AUTO:6900000:FEC_NONE:QAM_64:255:256:898
- */
- private CableChannel? parse_cable_channel (string line) {
- var channel = new CableChannel (this.channels.GroupId);
+ private Channel? parse_dvb_c (string group) throws KeyFileError, FileError {
+ if (this.Type != AdapterType.CABLE) return null;
- string[] fields = line.split(":");
+ Channel c = new Channel (this.channels.GroupId);
+ DvbCEuropeParameter param = new DvbCEuropeParameter.with_parameter ((uint)this.file.get_uint64
(group, "FREQUENCY"),
+ (uint)this.file.get_uint64 (group, "SYMBOL_RATE"),
+ getModulationEnum (this.file.get_string (group, "MODULATION")),
+ getCodeRateEnum (this.file.get_string (group, "INNER_FEC")));
- int i=0;
- string val;
- bool failed = false;
- while ( (val = fields[i]) != null) {
- if (i == 0) {
- if (val.validate())
- channel.Name = val;
- else {
- warning ("Bad UTF-8 encoded channel name");
- channel.Name = "Bad encoding";
- }
- } else if (i == 1) {
- channel.Frequency = (uint)int.parse (val);
- } else if (i == 2) {
- int eval;
- if (get_value_with_prefix (typeof(DvbSrcInversion), val,
- "DVB_DVB_SRC_INVERSION_", out eval)) {
- channel.Inversion = (DvbSrcInversion) eval;
- } else {
- failed = true;
- break;
- }
- } else if (i == 3) {
- channel.SymbolRate = (uint)(int.parse (val) / 1000);
- } else if (i == 4) {
- int eval;
- if (get_value_with_prefix (typeof(DvbSrcCodeRate), val,
- "DVB_DVB_SRC_CODE_RATE_", out eval)) {
- channel.CodeRate = (DvbSrcCodeRate) eval;
- } else {
- failed = true;
- break;
- }
- } else if (i == 5) {
- int eval;
- if (get_value_with_prefix (typeof(DvbSrcModulation), val,
- "DVB_DVB_SRC_MODULATION_", out eval)) {
- channel.Modulation = (DvbSrcModulation) eval;
- } else {
- failed = true;
- break;
- }
- } else if (i == 6) {
- channel.VideoPID = (uint)int.parse (val);
- } else if (i == 7) {
- channel.AudioPIDs.add ((uint)int.parse (val));
- } else if (i == 8) {
- channel.Sid = (uint)int.parse (val);
- }
+ c.Param = param;
- i++;
- }
-
- if (failed) return null;
- else return channel;
+ return c;
}
- private static bool get_value_with_prefix (GLib.Type enumtype, string name,
- string prefix, out int val) {
- return Utils.get_value_by_name_from_enum (enumtype, prefix + name, out val);
- }
}
}
diff --git a/src/io/ChannelListWriter.vala b/src/io/ChannelListWriter.vala
index cd22240..4975dcd 100644
--- a/src/io/ChannelListWriter.vala
+++ b/src/io/ChannelListWriter.vala
@@ -18,6 +18,8 @@
*/
using GLib;
+using DVB.Logging;
+using GstMpegTs;
namespace DVB.io {
@@ -35,11 +37,20 @@ namespace DVB.io {
*/
public class ChannelListWriter : GLib.Object {
- public File file {get; construct;}
+ public File file { get; construct; }
+
+ private KeyFile keyfile;
private OutputStream stream;
- private void open_stream () throws Error {
+ private void open () throws Error {
+
+ if (this.keyfile != null)
+ return;
+
+ this.keyfile = new KeyFile ();
+ this.keyfile.set_list_separator (' ');
+
FileOutputStream fostream = null;
if (file.query_exists (null)) {
@@ -56,123 +67,96 @@ namespace DVB.io {
}
public void write (Channel channel) throws Error {
- if (this.stream == null) this.open_stream ();
- if (this.stream == null) return;
-
- string buffer;
-
- // Write channel name
- buffer = "%s:".printf (channel.Name);
- this.stream.write_all (buffer.data, null, null);
-
- // Write special data
- if (channel is TerrestrialChannel) {
- this.write_terrestrial_channel ((TerrestrialChannel)channel);
- } else if (channel is SatelliteChannel) {
- this.write_satellite_channel ((SatelliteChannel)channel);
- } else if (channel is CableChannel) {
- this.write_cable_channel ((CableChannel)channel);
- } else {
- warning ("Unknown channel type");
- }
- uint apid;
- if (channel.AudioPIDs.size == 0)
- apid = 0;
- else
- apid = channel.AudioPIDs.get (0);
+ if (this.keyfile == null) this.open ();
+ if (this.keyfile == null) return;
+
+ switch (channel.Param.Delsys) {
+ case DvbSrcDelsys.SYS_DVBT:
+ this.write_terrestrial_channel (channel);
+ break;
+ case DvbSrcDelsys.SYS_DVBC_ANNEX_A:
+ this.write_cable_channel (channel);
+ break;
+ case DvbSrcDelsys.SYS_DVBS:
+ this.write_satellite_channel (channel);
+ break;
+ default:
+ return;
+ }
- // Write common data
- buffer = ":%u:%u:%u\n".printf (channel.VideoPID,
- apid, channel.Sid);
- this.stream.write_all (buffer.data, null);
+ this.keyfile.set_uint64 (channel.Name, "SERVICE_ID", channel.Sid);
+ this.keyfile.set_uint64 (channel.Name, "SERVICE_TYPE", channel.ServiceType);
+ /* should remove ? */
+ if (channel.VideoPID != 0)
+ this.keyfile.set_uint64 (channel.Name, "VIDEO_PID", channel.VideoPID);
+ /* should remove ? */
+ if (channel.AudioPIDs.size > 0) {
+ int[] apid = new int[channel.AudioPIDs.size];
+ for (int i = 0; i < channel.AudioPIDs.size; i++) {
+ apid[i] = (int)channel AudioPIDs get(i);
+ }
+ this.keyfile.set_integer_list (channel.Name, "AUDIO_PID", apid);
+ }
+ this.keyfile.set_boolean (channel.Name, "SCRAMBLED", channel.Scrambled);
+ this.keyfile.set_string (channel.Name, "PROVIDER", channel.Network);
+ this.keyfile.set_string (channel.Name, "SERVICE_NAME", channel.Name);
+ this.keyfile.set_uint64 (channel.Name, "TRANSPORT_STREAM_ID", channel.TransportStreamId);
}
public bool close () throws Error {
- if (this.stream == null) return true;
- return this.stream.close (null);
- }
-
- private void write_terrestrial_channel (TerrestrialChannel channel) throws Error {
- string[] elements = new string[9];
-
- elements[0] = "%u".printf (channel.Frequency);
-
- elements[1] = get_name_without_prefix (typeof(DvbSrcInversion),
- channel.Inversion,
- "DVB_DVB_SRC_INVERSION_");
+ if (this.keyfile != null) {
+ // write now data
+ this.stream.write_all (this.keyfile.to_data ().data, null, null);
+ this.keyfile = null;
+ }
- elements[2] = get_name_without_prefix (typeof(DvbSrcBandwidth),
- channel.Bandwidth,
- "DVB_DVB_SRC_BANDWIDTH_");
+ if (this.stream == null) return true;
- elements[3] = get_name_without_prefix (typeof(DvbSrcCodeRate),
- channel.CodeRateHP,
- "DVB_DVB_SRC_CODE_RATE_");
+ return this.stream.close (null);
- elements[4] = get_name_without_prefix (typeof(DvbSrcCodeRate),
- channel.CodeRateLP,
- "DVB_DVB_SRC_CODE_RATE_");
-
- elements[5] = get_name_without_prefix (typeof(DvbSrcModulation),
- channel.Constellation,
- "DVB_DVB_SRC_MODULATION_");
-
- elements[6] = get_name_without_prefix (typeof(DvbSrcTransmissionMode),
- channel.TransmissionMode,
- "DVB_DVB_SRC_TRANSMISSION_MODE_");
-
- elements[7] = get_name_without_prefix (typeof(DvbSrcGuard),
- channel.GuardInterval,
- "DVB_DVB_SRC_GUARD_");
-
- elements[8] = get_name_without_prefix (typeof(DvbSrcHierarchy),
- channel.Hierarchy,
- "DVB_DVB_SRC_HIERARCHY_");
-
- string buffer = string.joinv (":", elements);
- this.stream.write_all (buffer.data, null);
}
- private void write_satellite_channel (SatelliteChannel channel) throws Error {
- string buffer = "%u:%s:%d:%u".printf (channel.Frequency / 1000,
- channel.Polarization,
- channel.DiseqcSource,
- channel.SymbolRate);
- this.stream.write_all (buffer.data, null);
+ private void write_terrestrial_channel (Channel channel) throws Error {
+ // write channel data
+ DvbTParameter param = (DvbTParameter)channel.Param;
+
+ this.keyfile.set_string (channel.Name, "DELIVERY_SYSTEM", "DVBT");
+ this.keyfile.set_uint64 (channel.Name, "FREQUENCY", param.Frequency);
+ this.keyfile.set_uint64 (channel.Name, "BANDWIDTH_HZ", param.Bandwidth);
+ this.keyfile.set_string (channel.Name, "MODULATION", getModulationString (param.Constellation));
+ this.keyfile.set_string (channel.Name, "CODE_RATE_HP", getCodeRateString (param.CodeRateHP));
+ this.keyfile.set_string (channel.Name, "CODE_RATE_LP", getCodeRateString (param.CodeRateLP));
+ this.keyfile.set_string (channel.Name, "GUARD_INTERVAL", getGuardIntervalString
(param.GuardInterval));
+ this.keyfile.set_string (channel.Name, "TRANSMISSION_MODE", getTransmissionModeString
(param.TransmissionMode));
+ this.keyfile.set_string (channel.Name, "HIERARCHY", getHierarchyString (param.Hierarchy));
}
- private void write_cable_channel (CableChannel channel) throws Error {
- string[] elements = new string [5];
-
- elements[0] = "%u".printf (channel.Frequency);
-
- elements[1] = get_name_without_prefix (typeof(DvbSrcInversion),
- channel.Inversion,
- "DVB_DVB_SRC_INVERSION_");
-
- elements[2] = "%u".printf (channel.SymbolRate * 1000);
-
- elements[3] = get_name_without_prefix (typeof(DvbSrcCodeRate),
- channel.CodeRate,
- "DVB_DVB_SRC_CODE_RATE_");
+ private void write_satellite_channel (Channel channel) throws Error {
+ // write channel data
+ DvbSParameter param = (DvbSParameter)channel.Param;
+
+ this.keyfile.set_string (channel.Name, "DELIVERY_SYSTEM", "DVBS");
+ this.keyfile.set_uint64 (channel.Name, "FREQUENCY", param.Frequency);
+ this.keyfile.set_uint64 (channel.Name, "SYMBOL_RATE", param.SymbolRate);
+ this.keyfile.set_string (channel.Name, "INNER_FEC", getCodeRateString (param.InnerFEC));
+ this.keyfile.set_string (channel.Name, "POLARIZATION", getPolarizationString
(param.Polarization));
+ this.keyfile.set_double (channel.Name, "ORBITAL_POSITION", (double)param.OrbitalPosition);
+ if (param.DiseqcSource > -1)
+ this.keyfile.set_uint64 (channel.Name, "SAT_NUMBER", param.DiseqcSource);
+ }
- elements[4] = get_name_without_prefix (typeof(DvbSrcModulation),
- channel.Modulation,
- "DVB_DVB_SRC_MODULATION_");
+ private void write_cable_channel (Channel channel) throws Error {
+ // write channel data
+ DvbCEuropeParameter param = (DvbCEuropeParameter)channel.Param;
- string buffer = string.joinv (":", elements);
- this.stream.write_all (buffer.data, null);
- }
+ this.keyfile.set_string (channel.Name, "DELIVERY_SYSTEM", "DVBC/ANNEX_A");
+ this.keyfile.set_uint64 (channel.Name, "FREQUENCY", param.Frequency);
+ this.keyfile.set_uint64 (channel.Name, "SYMBOL_RATE", param.SymbolRate);
+ this.keyfile.set_string (channel.Name, "INNER_FEC", getCodeRateString (param.InnerFEC));
+ this.keyfile.set_string (channel.Name, "MODULATION", getModulationString (param.Modulation));
- private static string? get_name_without_prefix (GLib.Type enumtype,
- int val, string prefix) {
- string? name = Utils.get_name_by_value_from_enum (enumtype,
- val);
- if (name == null) return null;
- else return name.substring (prefix.length,
- name.length - prefix.length);
- }
+ }
}
diff --git a/src/io/ScanningListReader.vala b/src/io/ScanningListReader.vala
new file mode 100644
index 0000000..d2a39cd
--- /dev/null
+++ b/src/io/ScanningListReader.vala
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2014 Stefan Ringel
+ *
+ * This file is part of GNOME DVB Daemon.
+ *
+ * GNOME DVB Daemon is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNOME DVB Daemon is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNOME DVB Daemon. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using GLib;
+using DVB.Logging;
+using GstMpegTs;
+using DVB;
+
+namespace DVB.io {
+
+ public class ScanningListReader : GLib.Object {
+
+ private KeyFile file;
+ private string path;
+ private List<Parameter> parameters;
+
+ public List<Parameter> Parameters { get { return this.parameters; }}
+
+ public ScanningListReader (string keyfile) {
+ this.file = new KeyFile();
+ this.path = keyfile;
+ this.parameters = new List<Parameter> ();
+ }
+
+ public void read_data () throws KeyFileError, FileError {
+
+ // reading data from scanning file
+
+ this.file.load_from_file (this.path, KeyFileFlags.NONE);
+
+ foreach (unowned string group in this.file.get_groups ()) {
+
+ switch (this.file.get_string (group, "DELIVERY_SYSTEM")) {
+ case "DVBT":
+ this.read_dvb_t (group);
+ break;
+ case "DVBC/ANNEX_A":
+ this.read_dvb_c (group);
+ break;
+ case "DVBS":
+ this.read_dvb_s (group);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private void read_dvb_t (string group) throws KeyFileError, FileError {
+ DvbTParameter param = new DvbTParameter.with_parameter (
+ (uint)this.file.get_uint64 (group, "FREQUENCY"),
+ (uint)this.file.get_uint64 (group, "BANDWIDTH_HZ"),
+ getGuardIntervalEnum (this.file.get_string (group, "GUARD_INTERVAL")),
+ getTransmissionModeEnum (this.file.get_string (group, "TRANSMISSION_MODE")),
+ getHierarchyEnum (this.file.get_string (group, "HIERARCHY")),
+ getModulationEnum (this.file.get_string (group, "MODULATION")),
+ getCodeRateEnum (this.file.get_string (group, "CODE_RATE_LP")),
+ getCodeRateEnum (this.file.get_string (group, "CODE_RATE_HP")));
+
+ this.parameters.append (param);
+ }
+
+ private void read_dvb_c (string group) throws KeyFileError, FileError {
+ DvbCEuropeParameter param = new DvbCEuropeParameter.with_parameter (
+ (uint)this.file.get_uint64 (group, "FREQUENCY"),
+ (uint)this.file.get_uint64 (group, "SYMBOL_RATE"),
+ getModulationEnum (this.file.get_string (group, "MODULATION")),
+ getCodeRateEnum (this.file.get_string (group, "INNER_FEC")));
+
+ this.parameters.append (param);
+ }
+
+ private void read_dvb_s (string group) throws KeyFileError, FileError {
+ DvbSParameter param = new DvbSParameter.with_parameter (
+ (uint)this.file.get_uint64 (group, "FREQUENCY"),
+ (uint)this.file.get_uint64 (group, "SYMBOL_RATE"),
+ (float)this.file.get_double (group, "ORBITAL_POSITION"),
+ getPolarizationEnum (this.file.get_string (group, "POLARIZATION")),
+ getCodeRateEnum (this.file.get_string (group, "INNER_FEC")));
+
+ if (this.file.has_key (group, "SAT_NUMBER"))
+ param.DiseqcSource = this.file.get_integer (group, "SAT_NUMBER");
+
+ this.parameters.append (param);
+ }
+
+ }
+}
diff --git a/src/rtsp/MediaFactory.vala b/src/rtsp/MediaFactory.vala
index c0944e2..4e21cfc 100644
--- a/src/rtsp/MediaFactory.vala
+++ b/src/rtsp/MediaFactory.vala
@@ -25,95 +25,81 @@ namespace DVB {
public class MediaFactory : Gst.RTSPMediaFactory {
private static Logger log = LogManager.getLogManager().getDefaultLogger();
+ private DeviceGroup group;
+ private Channel channel;
+ private Gst.Element payloader;
+ private PlayerThread player;
construct {
this.set_shared (true);
}
- public override Gst.RTSPMedia? @construct (Gst.RTSP.Url url) {
- uint sidnr = 0;
- uint grpnr = 0;
-
- string[] path_elements = url.abspath.split ("/");
- int i = 0;
- string elem;
- while ((elem = path_elements[i]) != null) {
- if (i == 1)
- grpnr = (uint)int.parse (elem);
- else if (i == 2)
- sidnr = (uint)int.parse (elem);
-
- i++;
- }
-
- Manager manager = Manager.get_instance();
-
- DeviceGroup? devgrp =
- manager.get_device_group_if_exists (grpnr);
- if (devgrp == null) {
- warning ("Unknown group %u", grpnr);
- return null;
- }
-
- Gst.Element payload = Gst.ElementFactory.make ("rtpmp2tpay",
- "pay0");
- if (payload == null) {
+ private void on_media_unprepared () {
+ ChannelFactory channels_factory = this.group.channel_factory;
+ channels_factory.stop_channel (this.channel, this.payloader);
+ this.group = null;
+ this.channel = null;
+ this.payloader = null;
+ this.player = null;
+ }
+
+ public override Gst.Element? create_element (Gst.RTSP.Url url) {
+ uint sidnr = 0;
+ uint grpnr = 0;
+ log.debug ("create element");
+ string[] path_elements = url.abspath.split ("/");
+ int i = 0;
+ string elem;
+ while ((elem = path_elements[i]) != null) {
+ if (i == 1)
+ grpnr = (uint)int.parse (elem);
+ else if (i == 2)
+ sidnr = (uint)int.parse (elem);
+
+ i++;
+ }
+
+ Manager manager = Manager.get_instance();
+
+ this.group = manager.get_device_group_if_exists (grpnr);
+ if (this.group == null) {
+ warning ("Unknown group %u", grpnr);
+ return null;
+ }
+
+ this.payloader = Gst.ElementFactory.make ("rtpmp2tpay", "pay0");
+ if (this.payloader == null) {
log.error ("Could not create rtpmp2tpay element");
return null;
}
- payload.set ("pt", 96);
-
- Channel? channel = devgrp.Channels.get_channel (sidnr);
- if (channel == null) {
- log.error ("No channel with SID %u", sidnr);
- return null;
- }
- ChannelFactory channels_factory = devgrp.channel_factory;
-
- PlayerThread? player = channels_factory.watch_channel (channel,
- payload, false, DVB.RTSPServer.stop_streaming);
- if (player == null) {
- log.debug ("Could not create player");
- return null;
- }
- log.debug ("Retrieving sink bin with payloader");
- Gst.Element? bin = player.get_sink_bin (sidnr, payload);
-
- // Construct media
- Gst.RTSPMedia media = new DVBMedia (devgrp, channel, payload);
- media.set_property("element", bin);
- // Set pipeline
- media.take_pipeline ( (Gst.Pipeline) player.get_pipeline ());
-
- media.collect_streams ();
-
- return media;
- }
+ this.payloader.set ("pt", 96);
- public override string gen_key (Gst.RTSP.Url url) {
- return url.abspath;
- }
- }
+ this.channel = this.group.Channels.get_channel (sidnr);
+ if (this.channel == null) {
+ log.error ("No channel with SID %u", sidnr);
+ return null;
+ }
+ ChannelFactory channels_factory = this.group.channel_factory;
+ this.player = channels_factory.watch_channel (this.channel,
+ this.payloader, false, DVB.RTSPServer.stop_streaming);
+ if (this.player == null) {
+ log.debug ("Could not create player");
+ return null;
+ }
+ log.debug ("Retrieving sink bin with payloader");
- public class DVBMedia : Gst.RTSPMedia {
+ return this.player.get_sink_bin (sidnr, this.payloader);
+ }
- protected DeviceGroup group;
- protected Channel channel;
- protected Gst.Element payloader;
+ protected override Gst.Element? create_pipeline (Gst.RTSPMedia media) {
+ log.debug ("create pipeline");
+ Gst.Element pipeline = this.player.get_pipeline ();
- public DVBMedia (DeviceGroup group, Channel channel,
- Gst.Element payloader) {
- this.group = group;
- this.channel = channel;
- this.payloader = payloader;
- }
+ media.unprepared.connect (this.on_media_unprepared);
+ media.take_pipeline ((Gst.Pipeline)pipeline);
- public override bool unprepare () {
- base.unprepare ();
- ChannelFactory channels_factory = this.group.channel_factory;
- channels_factory.stop_channel (this.channel, this.payloader);
- return true;
+ return pipeline;
}
}
}
diff --git a/src/rtsp/Server.vala b/src/rtsp/Server.vala
index 73b427d..7dfcbf2 100644
--- a/src/rtsp/Server.vala
+++ b/src/rtsp/Server.vala
@@ -51,7 +51,6 @@ namespace DVB.RTSPServer {
log = LogManager.getLogManager().getDefaultLogger();
log.info ("Starting RTSP server");
server = new Gst.RTSPServer ();
- server.get_mount_points().add_factory("/", new MediaFactory());
server.set_address (get_address ());
server.attach (null);
timeout_id = GLib.Timeout.add_seconds (2, (GLib.SourceFunc)timeout);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]