[gnome-dvb-daemon] Change to gstreamer 1.4.0 API and DVBv5 channel list



commit 3e42dd63011fba4b4498e5b44e5290d26d314bb6
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]