Index: /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/control
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/control	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/control	(revision 8762)
@@ -0,0 +1,10 @@
+Package: enigma2-plugin-swapepg-crossepg
+Version: 0.61
+Architecture: sh4
+OE: CrossEPG by sandro cavazzoni for SKYit, SKYuk, AUsat
+Section: epg
+Priority: optional
+Maintainer: sandro cavazzoni
+Homepage: http://code.google.com/p/crossepg/
+Source: http://code.google.com/p/crossepg/
+Description: Plugin CrossEPG by sandro cavazzoni   SWAPSTICK IS NEEDED!
Index: /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/postinst
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/postinst	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/postinst	(revision 8762)
@@ -0,0 +1,14 @@
+#!/bin/sh
+TMP=/tmp/.epg
+
+ln -s /var/swap/crossepg /var/crossepg
+
+echo "successfully installed"
+echo "syncing disk"
+sync
+if [ `df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1 | wc -l` -eq 1 ]; then
+	SPACE=`df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1`
+	FREE=`expr $SPACE - 100`
+	echo new freespace size $FREE kb
+fi
+exit 0
Index: /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/postrm
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/postrm	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/postrm	(revision 8762)
@@ -0,0 +1,14 @@
+#!/bin/sh
+TMP=/tmp/.epg
+PLUGINDIR=/var/swap/swapextensions/CrossEPG
+
+
+echo "successfully removed"
+echo "syncing disk"
+sync
+if [ `df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1 | wc -l` -eq 1 ]; then
+	SPACE=`df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1`
+	FREE=`expr $SPACE - 100`
+	echo new freespace size $FREE kb
+fi
+exit 0
Index: /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/preinst
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/preinst	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/preinst	(revision 8762)
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+TMP=/tmp/.epg
+echo "syncing disk"
+sync
+
+model=`cat /etc/model`
+echo""
+echo "Checking your Boxtype...."
+echo "Some Plugins will not work correctly on your $model!"
+echo ""
+if [ "$model" = "" ]; then
+	echo "Sorry! This Plugin is not available for your $model because it will not work correctly!!!"
+	echo "Aborting installation..."
+	exit 1
+else
+	echo "Boxtype: $model OK"
+fi
+
+echo "checking swapstick"
+if [ ! -d /var/swap/bin/ ]; then
+  echo "--------------------------"
+	echo "no swapstick found...."
+	echo "--------------------------"
+	exit 1
+fi
+echo "swapstick found...."
+
+if [ `df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1 | wc -l` -eq 1 ]; then
+	SPACE=`df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1`
+	FREE=`expr $SPACE - 100`
+	SIZE=307
+	echo "checking freespace"
+	echo packege size $SIZE kb
+	echo freespace size $FREE kb
+	if  [ "$FREE" -lt "$SIZE" ]; then
+		echo "sorry no freespace left on device"
+		exit 1
+	else
+		echo ok
+	fi
+fi   
+echo "installing CrossEPG 0.61 for Swapstick..."
+echo "checking OS"
+if  [ `cat /etc/motd | grep AAF | grep M | grep rev | wc -l` -eq 0 ]; then                      
+	echo ---------------------------
+	echo DONT USE this IPK Package!!
+	echo ---
+	echo Only for AAF Image!!
+	echo ---------------------------
+	exit 1
+fi
+exit 0
Index: /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/prerm
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/prerm	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/CONTROL/prerm	(revision 8762)
@@ -0,0 +1,14 @@
+#!/bin/sh
+TMP=/tmp/.epg
+
+rm -r /var/crossepg
+
+echo "syncing disk"
+sync
+if [ `df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1 | wc -l` -eq 1 ]; then
+	SPACE=`df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1`
+	FREE=`expr $SPACE - 100`
+	echo freespace size $FREE kb
+fi
+echo "removing CrossEPG v0.61"
+exit 0
Index: /ipk/source.sh4/swapepg_crossepg_0_61/usr/lib/python2.6/crossepg.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/usr/lib/python2.6/crossepg.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/usr/lib/python2.6/crossepg.py	(revision 8762)
@@ -0,0 +1,525 @@
+# This file was automatically generated by SWIG (http://www.swig.org).
+# Version 1.3.40
+#
+# Do not make changes to this file unless you know what you are doing--modify
+# the SWIG interface file instead.
+# This file is compatible with both classic and new-style classes.
+
+from sys import version_info
+if version_info >= (2,6,0):
+    def swig_import_helper():
+        from os.path import dirname
+        import imp
+        fp = None
+        try:
+            fp, pathname, description = imp.find_module('_crossepg', [dirname(__file__)])
+        except ImportError:
+            import _crossepg
+            return _crossepg
+        if fp is not None:
+            try:
+                _mod = imp.load_module('_crossepg', fp, pathname, description)
+            finally:
+                fp.close()
+            return _mod
+    _crossepg = swig_import_helper()
+    del swig_import_helper
+else:
+    import _crossepg
+del version_info
+try:
+    _swig_property = property
+except NameError:
+    pass # Python < 2.2 doesn't have 'property'.
+def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
+    if (name == "thisown"): return self.this.own(value)
+    if (name == "this"):
+        if type(value).__name__ == 'SwigPyObject':
+            self.__dict__[name] = value
+            return
+    method = class_type.__swig_setmethods__.get(name,None)
+    if method: return method(self,value)
+    if (not static) or hasattr(self,name):
+        self.__dict__[name] = value
+    else:
+        raise AttributeError("You cannot add attributes to %s" % self)
+
+def _swig_setattr(self,class_type,name,value):
+    return _swig_setattr_nondynamic(self,class_type,name,value,0)
+
+def _swig_getattr(self,class_type,name):
+    if (name == "thisown"): return self.this.own()
+    method = class_type.__swig_getmethods__.get(name,None)
+    if method: return method(self)
+    raise AttributeError(name)
+
+def _swig_repr(self):
+    try: strthis = "proxy of " + self.this.__repr__()
+    except: strthis = ""
+    return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+try:
+    _object = object
+    _newclass = 1
+except AttributeError:
+    class _object : pass
+    _newclass = 0
+
+
+
+def log_enable():
+  return _crossepg.log_enable()
+log_enable = _crossepg.log_enable
+
+def log_disable():
+  return _crossepg.log_disable()
+log_disable = _crossepg.log_disable
+
+def log_open(*args):
+  return _crossepg.log_open(*args)
+log_open = _crossepg.log_open
+
+def log_banner(*args):
+  return _crossepg.log_banner(*args)
+log_banner = _crossepg.log_banner
+
+def log_close():
+  return _crossepg.log_close()
+log_close = _crossepg.log_close
+
+def log_add(*args):
+  return _crossepg.log_add(*args)
+log_add = _crossepg.log_add
+
+def epgdb_aliases_clear():
+  return _crossepg.epgdb_aliases_clear()
+epgdb_aliases_clear = _crossepg.epgdb_aliases_clear
+
+def epgdb_aliases_add(*args):
+  return _crossepg.epgdb_aliases_add(*args)
+epgdb_aliases_add = _crossepg.epgdb_aliases_add
+
+def epgdb_channels_count():
+  return _crossepg.epgdb_channels_count()
+epgdb_channels_count = _crossepg.epgdb_channels_count
+
+def epgdb_channels_get_first():
+  return _crossepg.epgdb_channels_get_first()
+epgdb_channels_get_first = _crossepg.epgdb_channels_get_first
+
+def epgdb_channels_set_first(*args):
+  return _crossepg.epgdb_channels_set_first(*args)
+epgdb_channels_set_first = _crossepg.epgdb_channels_set_first
+
+def epgdb_channels_set_last(*args):
+  return _crossepg.epgdb_channels_set_last(*args)
+epgdb_channels_set_last = _crossepg.epgdb_channels_set_last
+
+def epgdb_channels_get_by_freq(*args):
+  return _crossepg.epgdb_channels_get_by_freq(*args)
+epgdb_channels_get_by_freq = _crossepg.epgdb_channels_get_by_freq
+
+def epgdb_channels_add(*args):
+  return _crossepg.epgdb_channels_add(*args)
+epgdb_channels_add = _crossepg.epgdb_channels_add
+
+def epgdb_channels_reset():
+  return _crossepg.epgdb_channels_reset()
+epgdb_channels_reset = _crossepg.epgdb_channels_reset
+
+def epgdb_index_count():
+  return _crossepg.epgdb_index_count()
+epgdb_index_count = _crossepg.epgdb_index_count
+
+def epgdb_index_empties_count():
+  return _crossepg.epgdb_index_empties_count()
+epgdb_index_empties_count = _crossepg.epgdb_index_empties_count
+
+def epgdb_index_get_first(*args):
+  return _crossepg.epgdb_index_get_first(*args)
+epgdb_index_get_first = _crossepg.epgdb_index_get_first
+
+def epgdb_index_empties_get_first():
+  return _crossepg.epgdb_index_empties_get_first()
+epgdb_index_empties_get_first = _crossepg.epgdb_index_empties_get_first
+
+def epgdb_index_empties_set_first(*args):
+  return _crossepg.epgdb_index_empties_set_first(*args)
+epgdb_index_empties_set_first = _crossepg.epgdb_index_empties_set_first
+
+def epgdb_index_empties_set_last(*args):
+  return _crossepg.epgdb_index_empties_set_last(*args)
+epgdb_index_empties_set_last = _crossepg.epgdb_index_empties_set_last
+
+def epgdb_index_empties_add(*args):
+  return _crossepg.epgdb_index_empties_add(*args)
+epgdb_index_empties_add = _crossepg.epgdb_index_empties_add
+
+def epgdb_index_init():
+  return _crossepg.epgdb_index_init()
+epgdb_index_init = _crossepg.epgdb_index_init
+
+def epgdb_index_clean():
+  return _crossepg.epgdb_index_clean()
+epgdb_index_clean = _crossepg.epgdb_index_clean
+
+def epgdb_index_get_by_crc_length(*args):
+  return _crossepg.epgdb_index_get_by_crc_length(*args)
+epgdb_index_get_by_crc_length = _crossepg.epgdb_index_get_by_crc_length
+
+def epgdb_index_add(*args):
+  return _crossepg.epgdb_index_add(*args)
+epgdb_index_add = _crossepg.epgdb_index_add
+
+def epgdb_index_mark_all_as_unused():
+  return _crossepg.epgdb_index_mark_all_as_unused()
+epgdb_index_mark_all_as_unused = _crossepg.epgdb_index_mark_all_as_unused
+
+def epgdb_index_mark_as_used(*args):
+  return _crossepg.epgdb_index_mark_as_used(*args)
+epgdb_index_mark_as_used = _crossepg.epgdb_index_mark_as_used
+
+def epgdb_index_empty_unused():
+  return _crossepg.epgdb_index_empty_unused()
+epgdb_index_empty_unused = _crossepg.epgdb_index_empty_unused
+class epgdb_search_res_t(_object):
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, epgdb_search_res_t, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, epgdb_search_res_t, name)
+    __repr__ = _swig_repr
+    __swig_setmethods__["titles"] = _crossepg.epgdb_search_res_t_titles_set
+    __swig_getmethods__["titles"] = _crossepg.epgdb_search_res_t_titles_get
+    if _newclass:titles = _swig_property(_crossepg.epgdb_search_res_t_titles_get, _crossepg.epgdb_search_res_t_titles_set)
+    __swig_setmethods__["channels"] = _crossepg.epgdb_search_res_t_channels_set
+    __swig_getmethods__["channels"] = _crossepg.epgdb_search_res_t_channels_get
+    if _newclass:channels = _swig_property(_crossepg.epgdb_search_res_t_channels_get, _crossepg.epgdb_search_res_t_channels_set)
+    __swig_setmethods__["count"] = _crossepg.epgdb_search_res_t_count_set
+    __swig_getmethods__["count"] = _crossepg.epgdb_search_res_t_count_get
+    if _newclass:count = _swig_property(_crossepg.epgdb_search_res_t_count_get, _crossepg.epgdb_search_res_t_count_set)
+    def __init__(self): 
+        this = _crossepg.new_epgdb_search_res_t()
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _crossepg.delete_epgdb_search_res_t
+    __del__ = lambda self : None;
+epgdb_search_res_t_swigregister = _crossepg.epgdb_search_res_t_swigregister
+epgdb_search_res_t_swigregister(epgdb_search_res_t)
+
+
+def epgdb_search_free(*args):
+  return _crossepg.epgdb_search_free(*args)
+epgdb_search_free = _crossepg.epgdb_search_free
+
+def epgdb_search_by_name(*args):
+  return _crossepg.epgdb_search_by_name(*args)
+epgdb_search_by_name = _crossepg.epgdb_search_by_name
+
+def epgdb_search_by_name_freq_time(*args):
+  return _crossepg.epgdb_search_by_name_freq_time(*args)
+epgdb_search_by_name_freq_time = _crossepg.epgdb_search_by_name_freq_time
+
+def epgdb_title_alloc():
+  return _crossepg.epgdb_title_alloc()
+epgdb_title_alloc = _crossepg.epgdb_title_alloc
+
+def epgdb_title_free(*args):
+  return _crossepg.epgdb_title_free(*args)
+epgdb_title_free = _crossepg.epgdb_title_free
+
+def epgdb_calculate_mjd(*args):
+  return _crossepg.epgdb_calculate_mjd(*args)
+epgdb_calculate_mjd = _crossepg.epgdb_calculate_mjd
+
+def epgdb_titles_count(*args):
+  return _crossepg.epgdb_titles_count(*args)
+epgdb_titles_count = _crossepg.epgdb_titles_count
+
+def epgdb_read_description(*args):
+  return _crossepg.epgdb_read_description(*args)
+epgdb_read_description = _crossepg.epgdb_read_description
+
+def epgdb_read_long_description(*args):
+  return _crossepg.epgdb_read_long_description(*args)
+epgdb_read_long_description = _crossepg.epgdb_read_long_description
+
+def epgdb_titles_set_long_description(*args):
+  return _crossepg.epgdb_titles_set_long_description(*args)
+epgdb_titles_set_long_description = _crossepg.epgdb_titles_set_long_description
+
+def epgdb_titles_set_description(*args):
+  return _crossepg.epgdb_titles_set_description(*args)
+epgdb_titles_set_description = _crossepg.epgdb_titles_set_description
+
+def epgdb_titles_set_long_description_utf8(*args):
+  return _crossepg.epgdb_titles_set_long_description_utf8(*args)
+epgdb_titles_set_long_description_utf8 = _crossepg.epgdb_titles_set_long_description_utf8
+
+def epgdb_titles_set_description_utf8(*args):
+  return _crossepg.epgdb_titles_set_description_utf8(*args)
+epgdb_titles_set_description_utf8 = _crossepg.epgdb_titles_set_description_utf8
+
+def epgdb_titles_get_by_id_and_mjd(*args):
+  return _crossepg.epgdb_titles_get_by_id_and_mjd(*args)
+epgdb_titles_get_by_id_and_mjd = _crossepg.epgdb_titles_get_by_id_and_mjd
+
+def epgdb_titles_get_by_time(*args):
+  return _crossepg.epgdb_titles_get_by_time(*args)
+epgdb_titles_get_by_time = _crossepg.epgdb_titles_get_by_time
+
+def epgdb_titles_delete_in_range(*args):
+  return _crossepg.epgdb_titles_delete_in_range(*args)
+epgdb_titles_delete_in_range = _crossepg.epgdb_titles_delete_in_range
+
+def epgdb_titles_add(*args):
+  return _crossepg.epgdb_titles_add(*args)
+epgdb_titles_add = _crossepg.epgdb_titles_add
+DB_REVISION = _crossepg.DB_REVISION
+FLAG_UTF8 = _crossepg.FLAG_UTF8
+class epgdb_title_t(_object):
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, epgdb_title_t, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, epgdb_title_t, name)
+    __repr__ = _swig_repr
+    __swig_setmethods__["event_id"] = _crossepg.epgdb_title_t_event_id_set
+    __swig_getmethods__["event_id"] = _crossepg.epgdb_title_t_event_id_get
+    if _newclass:event_id = _swig_property(_crossepg.epgdb_title_t_event_id_get, _crossepg.epgdb_title_t_event_id_set)
+    __swig_setmethods__["mjd"] = _crossepg.epgdb_title_t_mjd_set
+    __swig_getmethods__["mjd"] = _crossepg.epgdb_title_t_mjd_get
+    if _newclass:mjd = _swig_property(_crossepg.epgdb_title_t_mjd_get, _crossepg.epgdb_title_t_mjd_set)
+    __swig_setmethods__["start_time"] = _crossepg.epgdb_title_t_start_time_set
+    __swig_getmethods__["start_time"] = _crossepg.epgdb_title_t_start_time_get
+    if _newclass:start_time = _swig_property(_crossepg.epgdb_title_t_start_time_get, _crossepg.epgdb_title_t_start_time_set)
+    __swig_setmethods__["length"] = _crossepg.epgdb_title_t_length_set
+    __swig_getmethods__["length"] = _crossepg.epgdb_title_t_length_get
+    if _newclass:length = _swig_property(_crossepg.epgdb_title_t_length_get, _crossepg.epgdb_title_t_length_set)
+    __swig_setmethods__["genre_id"] = _crossepg.epgdb_title_t_genre_id_set
+    __swig_getmethods__["genre_id"] = _crossepg.epgdb_title_t_genre_id_get
+    if _newclass:genre_id = _swig_property(_crossepg.epgdb_title_t_genre_id_get, _crossepg.epgdb_title_t_genre_id_set)
+    __swig_setmethods__["flags"] = _crossepg.epgdb_title_t_flags_set
+    __swig_getmethods__["flags"] = _crossepg.epgdb_title_t_flags_get
+    if _newclass:flags = _swig_property(_crossepg.epgdb_title_t_flags_get, _crossepg.epgdb_title_t_flags_set)
+    __swig_setmethods__["description_crc"] = _crossepg.epgdb_title_t_description_crc_set
+    __swig_getmethods__["description_crc"] = _crossepg.epgdb_title_t_description_crc_get
+    if _newclass:description_crc = _swig_property(_crossepg.epgdb_title_t_description_crc_get, _crossepg.epgdb_title_t_description_crc_set)
+    __swig_setmethods__["description_seek"] = _crossepg.epgdb_title_t_description_seek_set
+    __swig_getmethods__["description_seek"] = _crossepg.epgdb_title_t_description_seek_get
+    if _newclass:description_seek = _swig_property(_crossepg.epgdb_title_t_description_seek_get, _crossepg.epgdb_title_t_description_seek_set)
+    __swig_setmethods__["long_description_crc"] = _crossepg.epgdb_title_t_long_description_crc_set
+    __swig_getmethods__["long_description_crc"] = _crossepg.epgdb_title_t_long_description_crc_get
+    if _newclass:long_description_crc = _swig_property(_crossepg.epgdb_title_t_long_description_crc_get, _crossepg.epgdb_title_t_long_description_crc_set)
+    __swig_setmethods__["long_description_seek"] = _crossepg.epgdb_title_t_long_description_seek_set
+    __swig_getmethods__["long_description_seek"] = _crossepg.epgdb_title_t_long_description_seek_get
+    if _newclass:long_description_seek = _swig_property(_crossepg.epgdb_title_t_long_description_seek_get, _crossepg.epgdb_title_t_long_description_seek_set)
+    __swig_setmethods__["description_length"] = _crossepg.epgdb_title_t_description_length_set
+    __swig_getmethods__["description_length"] = _crossepg.epgdb_title_t_description_length_get
+    if _newclass:description_length = _swig_property(_crossepg.epgdb_title_t_description_length_get, _crossepg.epgdb_title_t_description_length_set)
+    __swig_setmethods__["long_description_length"] = _crossepg.epgdb_title_t_long_description_length_set
+    __swig_getmethods__["long_description_length"] = _crossepg.epgdb_title_t_long_description_length_get
+    if _newclass:long_description_length = _swig_property(_crossepg.epgdb_title_t_long_description_length_get, _crossepg.epgdb_title_t_long_description_length_set)
+    __swig_setmethods__["iso_639_1"] = _crossepg.epgdb_title_t_iso_639_1_set
+    __swig_getmethods__["iso_639_1"] = _crossepg.epgdb_title_t_iso_639_1_get
+    if _newclass:iso_639_1 = _swig_property(_crossepg.epgdb_title_t_iso_639_1_get, _crossepg.epgdb_title_t_iso_639_1_set)
+    __swig_setmethods__["iso_639_2"] = _crossepg.epgdb_title_t_iso_639_2_set
+    __swig_getmethods__["iso_639_2"] = _crossepg.epgdb_title_t_iso_639_2_get
+    if _newclass:iso_639_2 = _swig_property(_crossepg.epgdb_title_t_iso_639_2_get, _crossepg.epgdb_title_t_iso_639_2_set)
+    __swig_setmethods__["iso_639_3"] = _crossepg.epgdb_title_t_iso_639_3_set
+    __swig_getmethods__["iso_639_3"] = _crossepg.epgdb_title_t_iso_639_3_get
+    if _newclass:iso_639_3 = _swig_property(_crossepg.epgdb_title_t_iso_639_3_get, _crossepg.epgdb_title_t_iso_639_3_set)
+    __swig_setmethods__["revision"] = _crossepg.epgdb_title_t_revision_set
+    __swig_getmethods__["revision"] = _crossepg.epgdb_title_t_revision_get
+    if _newclass:revision = _swig_property(_crossepg.epgdb_title_t_revision_get, _crossepg.epgdb_title_t_revision_set)
+    __swig_setmethods__["changed"] = _crossepg.epgdb_title_t_changed_set
+    __swig_getmethods__["changed"] = _crossepg.epgdb_title_t_changed_get
+    if _newclass:changed = _swig_property(_crossepg.epgdb_title_t_changed_get, _crossepg.epgdb_title_t_changed_set)
+    __swig_setmethods__["prev"] = _crossepg.epgdb_title_t_prev_set
+    __swig_getmethods__["prev"] = _crossepg.epgdb_title_t_prev_get
+    if _newclass:prev = _swig_property(_crossepg.epgdb_title_t_prev_get, _crossepg.epgdb_title_t_prev_set)
+    __swig_setmethods__["next"] = _crossepg.epgdb_title_t_next_set
+    __swig_getmethods__["next"] = _crossepg.epgdb_title_t_next_get
+    if _newclass:next = _swig_property(_crossepg.epgdb_title_t_next_get, _crossepg.epgdb_title_t_next_set)
+    def __init__(self): 
+        this = _crossepg.new_epgdb_title_t()
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _crossepg.delete_epgdb_title_t
+    __del__ = lambda self : None;
+epgdb_title_t_swigregister = _crossepg.epgdb_title_t_swigregister
+epgdb_title_t_swigregister(epgdb_title_t)
+
+class epgdb_index_t(_object):
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, epgdb_index_t, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, epgdb_index_t, name)
+    __repr__ = _swig_repr
+    __swig_setmethods__["crc"] = _crossepg.epgdb_index_t_crc_set
+    __swig_getmethods__["crc"] = _crossepg.epgdb_index_t_crc_get
+    if _newclass:crc = _swig_property(_crossepg.epgdb_index_t_crc_get, _crossepg.epgdb_index_t_crc_set)
+    __swig_setmethods__["seek"] = _crossepg.epgdb_index_t_seek_set
+    __swig_getmethods__["seek"] = _crossepg.epgdb_index_t_seek_get
+    if _newclass:seek = _swig_property(_crossepg.epgdb_index_t_seek_get, _crossepg.epgdb_index_t_seek_set)
+    __swig_setmethods__["length"] = _crossepg.epgdb_index_t_length_set
+    __swig_getmethods__["length"] = _crossepg.epgdb_index_t_length_get
+    if _newclass:length = _swig_property(_crossepg.epgdb_index_t_length_get, _crossepg.epgdb_index_t_length_set)
+    __swig_setmethods__["used"] = _crossepg.epgdb_index_t_used_set
+    __swig_getmethods__["used"] = _crossepg.epgdb_index_t_used_get
+    if _newclass:used = _swig_property(_crossepg.epgdb_index_t_used_get, _crossepg.epgdb_index_t_used_set)
+    __swig_setmethods__["prev"] = _crossepg.epgdb_index_t_prev_set
+    __swig_getmethods__["prev"] = _crossepg.epgdb_index_t_prev_get
+    if _newclass:prev = _swig_property(_crossepg.epgdb_index_t_prev_get, _crossepg.epgdb_index_t_prev_set)
+    __swig_setmethods__["next"] = _crossepg.epgdb_index_t_next_set
+    __swig_getmethods__["next"] = _crossepg.epgdb_index_t_next_get
+    if _newclass:next = _swig_property(_crossepg.epgdb_index_t_next_get, _crossepg.epgdb_index_t_next_set)
+    def __init__(self): 
+        this = _crossepg.new_epgdb_index_t()
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _crossepg.delete_epgdb_index_t
+    __del__ = lambda self : None;
+epgdb_index_t_swigregister = _crossepg.epgdb_index_t_swigregister
+epgdb_index_t_swigregister(epgdb_index_t)
+
+class epgdb_alias_t(_object):
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, epgdb_alias_t, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, epgdb_alias_t, name)
+    __repr__ = _swig_repr
+    __swig_setmethods__["nid"] = _crossepg.epgdb_alias_t_nid_set
+    __swig_getmethods__["nid"] = _crossepg.epgdb_alias_t_nid_get
+    if _newclass:nid = _swig_property(_crossepg.epgdb_alias_t_nid_get, _crossepg.epgdb_alias_t_nid_set)
+    __swig_setmethods__["tsid"] = _crossepg.epgdb_alias_t_tsid_set
+    __swig_getmethods__["tsid"] = _crossepg.epgdb_alias_t_tsid_get
+    if _newclass:tsid = _swig_property(_crossepg.epgdb_alias_t_tsid_get, _crossepg.epgdb_alias_t_tsid_set)
+    __swig_setmethods__["sid"] = _crossepg.epgdb_alias_t_sid_set
+    __swig_getmethods__["sid"] = _crossepg.epgdb_alias_t_sid_get
+    if _newclass:sid = _swig_property(_crossepg.epgdb_alias_t_sid_get, _crossepg.epgdb_alias_t_sid_set)
+    def __init__(self): 
+        this = _crossepg.new_epgdb_alias_t()
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _crossepg.delete_epgdb_alias_t
+    __del__ = lambda self : None;
+epgdb_alias_t_swigregister = _crossepg.epgdb_alias_t_swigregister
+epgdb_alias_t_swigregister(epgdb_alias_t)
+
+class epgdb_channel_t(_object):
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, epgdb_channel_t, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, epgdb_channel_t, name)
+    __repr__ = _swig_repr
+    __swig_setmethods__["nid"] = _crossepg.epgdb_channel_t_nid_set
+    __swig_getmethods__["nid"] = _crossepg.epgdb_channel_t_nid_get
+    if _newclass:nid = _swig_property(_crossepg.epgdb_channel_t_nid_get, _crossepg.epgdb_channel_t_nid_set)
+    __swig_setmethods__["tsid"] = _crossepg.epgdb_channel_t_tsid_set
+    __swig_getmethods__["tsid"] = _crossepg.epgdb_channel_t_tsid_get
+    if _newclass:tsid = _swig_property(_crossepg.epgdb_channel_t_tsid_get, _crossepg.epgdb_channel_t_tsid_set)
+    __swig_setmethods__["sid"] = _crossepg.epgdb_channel_t_sid_set
+    __swig_getmethods__["sid"] = _crossepg.epgdb_channel_t_sid_get
+    if _newclass:sid = _swig_property(_crossepg.epgdb_channel_t_sid_get, _crossepg.epgdb_channel_t_sid_set)
+    __swig_setmethods__["prev"] = _crossepg.epgdb_channel_t_prev_set
+    __swig_getmethods__["prev"] = _crossepg.epgdb_channel_t_prev_get
+    if _newclass:prev = _swig_property(_crossepg.epgdb_channel_t_prev_get, _crossepg.epgdb_channel_t_prev_set)
+    __swig_setmethods__["next"] = _crossepg.epgdb_channel_t_next_set
+    __swig_getmethods__["next"] = _crossepg.epgdb_channel_t_next_get
+    if _newclass:next = _swig_property(_crossepg.epgdb_channel_t_next_get, _crossepg.epgdb_channel_t_next_set)
+    __swig_setmethods__["title_first"] = _crossepg.epgdb_channel_t_title_first_set
+    __swig_getmethods__["title_first"] = _crossepg.epgdb_channel_t_title_first_get
+    if _newclass:title_first = _swig_property(_crossepg.epgdb_channel_t_title_first_get, _crossepg.epgdb_channel_t_title_first_set)
+    __swig_setmethods__["title_last"] = _crossepg.epgdb_channel_t_title_last_set
+    __swig_getmethods__["title_last"] = _crossepg.epgdb_channel_t_title_last_get
+    if _newclass:title_last = _swig_property(_crossepg.epgdb_channel_t_title_last_get, _crossepg.epgdb_channel_t_title_last_set)
+    __swig_setmethods__["aliases"] = _crossepg.epgdb_channel_t_aliases_set
+    __swig_getmethods__["aliases"] = _crossepg.epgdb_channel_t_aliases_get
+    if _newclass:aliases = _swig_property(_crossepg.epgdb_channel_t_aliases_get, _crossepg.epgdb_channel_t_aliases_set)
+    __swig_setmethods__["aliases_count"] = _crossepg.epgdb_channel_t_aliases_count_set
+    __swig_getmethods__["aliases_count"] = _crossepg.epgdb_channel_t_aliases_count_get
+    if _newclass:aliases_count = _swig_property(_crossepg.epgdb_channel_t_aliases_count_get, _crossepg.epgdb_channel_t_aliases_count_set)
+    def __init__(self): 
+        this = _crossepg.new_epgdb_channel_t()
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _crossepg.delete_epgdb_channel_t
+    __del__ = lambda self : None;
+epgdb_channel_t_swigregister = _crossepg.epgdb_channel_t_swigregister
+epgdb_channel_t_swigregister(epgdb_channel_t)
+
+
+def epgdb_open(*args):
+  return _crossepg.epgdb_open(*args)
+epgdb_open = _crossepg.epgdb_open
+
+def epgdb_close():
+  return _crossepg.epgdb_close()
+epgdb_close = _crossepg.epgdb_close
+
+def epgdb_load():
+  return _crossepg.epgdb_load()
+epgdb_load = _crossepg.epgdb_load
+
+def epgdb_save(*args):
+  return _crossepg.epgdb_save(*args)
+epgdb_save = _crossepg.epgdb_save
+
+def epgdb_clean():
+  return _crossepg.epgdb_clean()
+epgdb_clean = _crossepg.epgdb_clean
+
+def epgdb_get_fdd():
+  return _crossepg.epgdb_get_fdd()
+epgdb_get_fdd = _crossepg.epgdb_get_fdd
+
+def epgdb_get_creation_time():
+  return _crossepg.epgdb_get_creation_time()
+epgdb_get_creation_time = _crossepg.epgdb_get_creation_time
+
+def epgdb_get_update_time():
+  return _crossepg.epgdb_get_update_time()
+epgdb_get_update_time = _crossepg.epgdb_get_update_time
+import os
+import re
+
+def epgdb_get_installroot():
+	if os.path.exists("/usr/crossepg"):
+		return("/usr/crossepg")
+	elif os.path.exists("/var/crossepg"):
+		return("/var/crossepg")
+	else:
+		return False
+
+def epgdb_get_dbroot():
+	
+	homedir = epgdb_get_installroot()
+
+	if homedir == False:
+		return False
+
+	try:
+		f = open("%s/crossepg.config" % (homedir), "r")
+	except Exception, e:
+		return False
+		
+	entryRe = re.compile(r"db_root=(.*)")
+		
+	for line in f.readlines(): 
+		entry = re.findall(entryRe, line)
+		if entry:
+			dbroot = entry[0].strip()
+	
+	f.close()
+	return dbroot
+	
+def IS_UTF8(flags):
+	return flags & 0x01
+	
+def SET_UTF8(flags):
+	return flags | 0x01
+
+def UNSET_UTF8(flags):
+	return flags & (~0x01)
+
+
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/crossepg_epgmove.sh
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/crossepg_epgmove.sh	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/crossepg_epgmove.sh	(revision 8762)
@@ -0,0 +1,21 @@
+#!/bin/sh
+HOME=`echo $0 | sed "s/crossepg_epgmove\.sh//"`
+
+if [ -f "$HOME/crossepg.config" ] # if configuration exist
+then
+	DBROOT=`cat $HOME/crossepg.config | grep db_root= | sed "s/db_root=//"`
+else # else default path
+	DBROOT="/hdd/crossepg"
+fi
+
+if [ -f "$DBROOT/ext.epg.dat" ] # try on configuration path
+then
+	echo copying ext.epg.dat from $DBROOT
+	$HOME/crossepg_epgcopy "$DBROOT/ext.epg.dat" /hdd/epg.dat
+elif [ -f "/hdd/crossepg/ext.epg.dat" ] # if we have a bad path try with default path
+then
+	echo copying ext.epg.dat from /hdd/crossepg/
+	$HOME/crossepg_epgcopy /hdd/crossepg/ext.epg.dat /hdd/epg.dat
+else # no epg found
+	echo ext.epg.dat not found
+fi
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/alias_script.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/alias_script.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/alias_script.conf	(revision 8762)
@@ -0,0 +1,3 @@
+protocol=script
+filename=alias/alias.py
+description=ALIAS: do simple aliases handling
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/ausat_optusc1_156.0.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/ausat_optusc1_156.0.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/ausat_optusc1_156.0.conf	(revision 8762)
@@ -0,0 +1,13 @@
+description=Ausat OpenTV (Optusc1 on 156.0)
+# nid ,tsid, sid
+nid=4096
+tsid=17
+sid=17008
+namespace=102236160
+# channels pids
+channels_pids=17
+# titles pids
+titles_pids=48|49|50|51|52|53|54|55
+# summaries pids
+summaries_pids=64|65|66|67|68|69|70|71
+protocol=opentv
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/ausat_optusc1_156.0.dict
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/ausat_optusc1_156.0.dict	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/ausat_optusc1_156.0.dict	(revision 8762)
@@ -0,0 +1,512 @@
+ =101010111000110000101001100
+ =101010111000110000101001101
+ =101010111000110000101001110
+ =101010111000110000101001111
+ =101010111000110000101010000
+ =101010111000110000101010001
+ =101010111000110000101010010
+ =101010111000110000101010011
+ =101010111000110000101010100
+=0001000
+ =1110111
+ =101010111000110000101010101
+ =101010111000110000101010110
+ =101010111000110000101010111
+ =101010111000110000101011000
+ =101010111000110000101011001
+ =101010111000110000101011010
+ =101010111000110000101011011
+ =101010111000110000101011100
+ =101010111000110000101011101
+ =101010111000110000101011110
+ =101010111000110000101011111
+ =101010111000110000101100000
+ =101010111000110000101100001
+ =101010111000110000101100010
+ =101010111000110000101100011
+ =101010111000110000101100100
+ =101010111000110000101100101
+ =101010111000110000101100110
+ =101010111000110000101100111
+ =101010111000110000101101000
+ =101010111000110000101101001
+ =110
+!=01000011000
+"=101010111000110000101101010
+#=101010111000110000101101011
+$=1010101110001101
+%=101010111000110000101101100
+&=10000011101
+'=10000010
+(=11101000101
+)=1010101100
+*=100010101110
++=101010111000110000101101101
+,=1011000
+-=10001011
+.=1110110
+/=00010100011110
+0=111010010
+1=101100111
+2=1000101000
+3=1000001111
+4=0001010000
+5=1110101000
+6=1000101001
+7=1000100010
+8=10001010110
+9=0100001101
+:=11101000110
+;=00010100010
+<=1110100011111
+==101010111000110000101101110
+>=1110101001100
+?=111010100111
+@=101010111000110001
+A=11100010
+B=01000000
+C=01000010
+D=111000111
+E=1110100000
+F=101010100
+G=100010000
+H=101010101
+I=1110100001
+J=000101001
+K=1110100111
+L=100000110
+M=10001001
+N=111010111
+O=010000010
+P=00010101
+Q=1000101010111
+R=111010110
+S=0001001
+T=0001011
+U=10101011101
+V=11101010101
+W=10110010
+X=1110001101101111
+Y=10101011110
+Z=1110101010000
+[=10101011100011001
+\=101010111000110000101101111
+]=11100011011011100
+^=101010111000110000101110000
+_=101010111000110000101110001
+`=11101010010
+a=1001
+b=1110000
+c=111001
+d=01001
+e=1111
+f=100001
+g=100011
+h=10111
+i=0101
+j=11100011010
+k=1000000
+l=10100
+m=101011
+n=0111
+o=0011
+p=000111
+q=10101011011
+r=0010
+s=0000
+t=0110
+u=101101
+v=1010100
+w=000110
+x=1110101011
+y=010001
+z=1011001100
+{=101010111000110000101110010
+|=101010111000110000101110011
+}=101010111000110000101110100
+~=101010111000110000101110101
+ =101010111000110000101110110
+ =101010111000110000101110111
+ =101010111000110000101111000
+ =101010111000110000101111001
+ =101010111000110000101111010
+ =101010111000110000101111011
+ =101010111000110000101111100
+ =101010111000110000101111101
+ =101010111000110000101111110
+ =101010111000110000101111111
+ =101010111000110000110000000
+ =101010111000110000110000001
+ =101010111000110000110000010
+ =101010111000110000110000011
+ =101010111000110000110000100
+ =101010111000110000110000101
+ =101010111000110000110000110
+ =101010111000110000110000111
+ =101010111000110000110001000
+ =101010111000110000110001001
+ =101010111000110000110001010
+ =101010111000110000110001011
+ =101010111000110000110001100
+ =101010111000110000110001101
+ =101010111000110000110001110
+ =101010111000110000110001111
+ =101010111000110000110010000
+ =101010111000110000110010001
+ =101010111000110000110010010
+ =11100011011011101
+ =101010111000110000110010011
+ =101010111000110000110010100
+ =101010111000110000110010101
+ =101010111000110000110010110
+¡=101010111000110000110010111
+¢=101010111000110000110011000
+£=101010111000110000110011001
+¤=101010111000110000110011010
+¥=101010111000110000110011011
+¦=101010111000110000110011100
+§=101010111000110000110011101
+¨=101010111000110000110011110
+©=101010111000110000110011111
+ª=101010111000110000110100000
+«=101010111000110000110100001
+¬=101010111000110000110100010
+­=101010111000110000110100011
+®=101010111000110000110100100
+¯=101010111000110000110100101
+°=101010111000110000110100110
+±=101010111000110000110100111
+²=101010111000110000110101000
+³=101010111000110000110101001
+´=101010111000110000110101010
+µ=101010111000110000110101011
+¶=101010111000110000110101100
+·=101010111000110000110101101
+¸=101010111000110000110101110
+¹=101010111000110000110101111
+º=101010111000110000110110000
+»=101010111000110000110110001
+¼=101010111000110000110110010
+½=101010111000110000110110011
+¾=101010111000110000110110100
+¿=101010111000110000110110101
+À=101010111000110000110110110
+Á=101010111000110000110110111
+Â=101010111000110000110111000
+Ã=101010111000110000110111001
+Ä=101010111000110000110111010
+Å=101010111000110000110111011
+Æ=101010111000110000110111100
+Ç=101010111000110000110111101
+È=101010111000110000110111110
+É=101010111000110000110111111
+Ê=101010111000110000111000000
+Ë=101010111000110000111000001
+Ì=101010111000110000111000010
+Í=101010111000110000111000011
+Î=101010111000110000111000100
+Ï=101010111000110000111000101
+Ð=101010111000110000111000110
+Ñ=101010111000110000111000111
+Ò=101010111000110000111001000
+Ó=101010111000110000111001001
+Ô=101010111000110000111001010
+Õ=101010111000110000111001011
+Ö=101010111000110000111001100
+×=101010111000110000111001101
+Ø=101010111000110000111001110
+Ù=101010111000110000111001111
+Ú=101010111000110000111010000
+Û=101010111000110000111010001
+Ü=101010111000110000111010010
+Ý=101010111000110000111010011
+Þ=101010111000110000111010100
+ß=101010111000110000111010101
+à=101010111000110000111010110
+á=101010111000110000111010111
+â=101010111000110000111011000
+ã=101010111000110000111011001
+ä=101010111000110000111011010
+å=101010111000110000111011011
+æ=101010111000110000111011100
+ç=101010111000110000111011101
+è=101010111000110000111011110
+é=101010111000110000111011111
+ê=101010111000110000111100000
+ë=101010111000110000111100001
+ì=101010111000110000111100010
+í=101010111000110000111100011
+î=101010111000110000111100100
+ï=101010111000110000111100101
+ð=101010111000110000111100110
+ñ=101010111000110000111100111
+ò=101010111000110000111101000
+ó=101010111000110000111101001
+ô=101010111000110000111101010
+õ=101010111000110000111101011
+ö=101010111000110000111101100
+÷=101010111000110000111101101
+ø=101010111000110000111101110
+ù=101010111000110000111101111
+ú=101010111000110000111110000
+û=101010111000110000111110001
+ü=101010111000110000111110010
+ý=101010111000110000111110011
+þ=101010111000110000111110100
+ÿ=101010111000110000111110101
+(Including =10101011111110
+(New Series)=11101000100010
+(Part =1110100011101
+(Repeat)=1110100110
+(Stereo)=010000111
+(Stereo) (Teletext)=010000011
+(Teletext)=1110001100
+(Widescreen)=100000111001110
+Action=101010111000111
+Adventures=10110011011111
+America=0100001100100
+Animated=111010100110111
+Australia=0100001100101
+Away=11101010100010
+BBC=10101011111111
+Baby=11100011011000
+Best=11101010100011
+Big=10110011011000
+Bill=1000101011111
+Black=1000101010000
+Blue=1011001101110
+Breakfast=000101000110
+Britain=1010101111100
+British=1110100011100
+Business=0100001100110
+Call=1010101111101
+Cartoon=10101011100000
+Channel=10101011100001
+Children=11101010100111
+Clock=11100011011001
+Comedy=11101000100011
+Cook=111010101001010
+Country=111010100110110
+Directed by =101010110100
+Drama=0100001100111
+East=1000101010001
+Education=100000111001111
+English=00010100011111
+Europe=0001010001110
+Extra=10110011011001
+Final=10101011100010
+Financial=111000110110100
+For=111000110111
+French=11101000111101
+From=1000101010010
+George=1010101111110
+Get=1000100011010
+Girls=10001000110110
+Golden=10001000110111
+Golf=111010101001011
+Good=1010101101010
+Great=11101000100100
+Hampshire=111010101001100
+Headlines=1000101010011
+Hear=11101010011010
+Hill=1000001110000
+Hollywood=111000110110101
+Home=1000101010100
+Hour=11101000100101
+House=1000001110010
+How=1010101101011
+ITN=11101010100100
+Important=111010101001101
+Including=1000101011110
+International=11101000100110
+John=10001000111
+Last=11101000100111
+Late=10000011100110
+Learn=10001010101100
+Little=10001010101101
+Live=1110100010000
+London=11101000111100
+Look=10110011011110
+Lunch=111000110110110
+Man=1000101010101
+Mark=1000001110001
+Meridian=101010111001
+Michael=1011001101101
+Minutes=101010111000110000111110110
+More=101010111000110000111110111
+Morning=101010111000110000111111000
+Murder=101010111000110000111111001
+Nation=101010111000110000111111010
+Neighbours=101010111000110000111111011
+New=101010111000110000111111100
+News & Weather=101010111000110000111111101
+News And Weather=101010111000110000111111110
+Paul=101010111000110000111111111
+Plus=10101011100011000000000000
+Prayer=10101011100011000000000001
+Present=10101011100011000000000010
+Presented by=10101011100011000000000011
+Quiz=10101011100011000000000100
+Regional=10101011100011000000000101
+Represent=10101011100011000000000110
+Resource=10101011100011000000000111
+Review=10101011100011000000001000
+Richard=10101011100011000000001001
+School=10101011100011000000001010
+Series=10101011100011000000001011
+Service=10101011100011000000001100
+Show=10101011100011000000001101
+Smith=10101011100011000000001110
+South=10101011100011000000001111
+Sport=10101011100011000000010000
+Star=10101011100011000000010001
+Street=10101011100011000000010010
+TV=10101011100011000000010011
+Teaching=10101011100011000000010100
+The=10101011100011000000010101
+Today=10101011100011000000010110
+Tonight=10101011100011000000010111
+Weather=10101011100011000000011000
+Western=10101011100011000000011001
+Westminster=10101011100011000000011010
+William=10101011100011000000011011
+With=10101011100011000000011100
+World=10101011100011000000011101
+about=10101011100011000000011110
+action-packed=10101011100011000000011111
+adventure=10101011100011000000100000
+afternoon=10101011100011000000100001
+alert=10101011100011000000100010
+all-star cast=10101011100011000000100011
+and=10101011100011000000100100
+anywhere=10101011100011000000100101
+audience=10101011100011000000100110
+based=10101011100011000000100111
+book=10101011100011000000101000
+business=10101011100011000000101001
+but=10101011100011000000101010
+celebrity=10101011100011000000101011
+chance=10101011100011000000101100
+chat=10101011100011000000101101
+child=10101011100011000000101110
+classic=10101011100011000000101111
+consumer=10101011100011000000110000
+contestants=10101011100011000000110001
+continues=10101011100011000000110010
+controversial=10101011100011000000110011
+dealer=10101011100011000000110100
+deliver=10101011100011000000110101
+discuss=10101011100011000000110110
+document=10101011100011000000110111
+drama=10101011100011000000111000
+edition=10101011100011000000111001
+education=10101011100011000000111010
+events=10101011100011000000111011
+every=10101011100011000000111100
+excellent=10101011100011000000111101
+eyed=10101011100011000000111110
+family=10101011100011000000111111
+famous=10101011100011000001000000
+featur=10101011100011000001000001
+film=10101011100011000001000010
+football=10101011100011000001000011
+for=10101011100011000001000100
+from=10101011100011000001000101
+general knowledge=10101011100011000001000110
+get=10101011100011000001000111
+guest=10101011100011000001001000
+guests=10101011100011000001001001
+has=10101011100011000001001010
+have=10101011100011000001001011
+headline=10101011100011000001001100
+her=10101011100011000001001101
+his=10101011100011000001001110
+home and abroad=10101011100011000001001111
+host=10101011100011000001010000
+how=10101011100011000001010001
+in=10101011100011000001010010
+including=10101011100011000001010011
+international=10101011100011000001010100
+interview=10101011100011000001010101
+introduce=10101011100011000001010110
+investigat=10101011100011000001010111
+invites=10101011100011000001011000
+issue=10101011100011000001011001
+knowledge=10101011100011000001011010
+life=10101011100011000001011011
+live=10101011100011000001011100
+look=10101011100011000001011101
+magazine=10101011100011000001011110
+meets =10101011100011000001011111
+morning=10101011100011000001100000
+morning magazine=10101011100011000001100001
+music=10101011100011000001100010
+near=10101011100011000001100011
+network=10101011100011000001100100
+new=10101011100011000001100101
+new series=10101011100011000001100110
+night=10101011100011000001100111
+of=10101011100011000001101000
+on=10101011100011000001101001
+onight=10101011100011000001101010
+out=10101011100011000001101011
+over=10101011100011000001101100
+part=10101011100011000001101101
+people=10101011100011000001101110
+phone=10101011100011000001101111
+poli=10101011100011000001110000
+police=10101011100011000001110001
+political chat show=10101011100011000001110010
+popular=10101011100011000001110011
+presented by =10101011100011000001110100
+programm=10101011100011000001110101
+quiz=10101011100011000001110110
+reconstruction=10101011100011000001110111
+report=10101011100011000001111000
+review=10101011100011000001111001
+school=10101011100011000001111010
+series=10101011100011000001111011
+short =10101011100011000001111100
+show=10101011100011000001111101
+some=10101011100011000001111110
+starring=10101011100011000001111111
+stars=10101011100011000010000000
+stories=10101011100011000010000001
+story=10101011100011000010000010
+studio=10101011100011000010000011
+surprise=10101011100011000010000100
+teller=10101011100011000010000101
+that=10101011100011000010000110
+the=10101011100011000010000111
+their=10101011100011000010001000
+them=10101011100011000010001001
+they=10101011100011000010001010
+this=10101011100011000010001011
+through=10101011100011000010001100
+to=10101011100011000010001101
+top=10101011100011000010001110
+trans=10101011100011000010001111
+under=10101011100011000010010000
+up=10101011100011000010010001
+very=10101011100011000010010010
+video=10101011100011000010010011
+view=10101011100011000010010100
+vintage=10101011100011000010010101
+visit=10101011100011000010010110
+was=10101011100011000010010111
+way=10101011100011000010011000
+week=10101011100011000010011001
+well=10101011100011000010011010
+what=10101011100011000010011011
+when=10101011100011000010011100
+which=10101011100011000010011101
+while=10101011100011000010011110
+who=10101011100011000010011111
+will=10101011100011000010100000
+win=10101011100011000010100001
+with=10101011100011000010100010
+words=10101011100011000010100011
+world=10101011100011000010100100
+written=10101011100011000010100101
+year=100010001100
+you=10110011010
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_bulsatcom_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_bulsatcom_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_bulsatcom_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni Bulsatcom Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/bulsat.headers.db.gz
+descriptors_url=http://krkadoni.com/bulsat.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_csat_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_csat_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_csat_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni CSAT Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/csat.headers.db.gz
+descriptors_url=http://krkadoni.com/csat.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_dplus_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_dplus_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_dplus_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni D+ Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/dplus.headers.db.gz
+descriptors_url=http://krkadoni.com/dplus.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_exyu_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_exyu_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_exyu_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni Ex-Yu Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/crossepg.headers.db.gz
+descriptors_url=http://krkadoni.com/crossepg.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_exyu_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_exyu_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_exyu_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Krkadoni ExYu XMLTV
+protocol=xmltv
+channels=http://www.krkadoni.com/krkadoni.channels.xml.gz
+url=http://krkadoni.com/krkadonixmltv_exyu.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_meo_zon_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_meo_zon_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_meo_zon_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni MEO/ZON Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/meozon.headers.db.gz
+descriptors_url=http://krkadoni.com/meozon.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_multichoice_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_multichoice_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_multichoice_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni ZA Multichoice/DSTV/OSN Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/multichoice.headers.db.gz
+descriptors_url=http://krkadoni.com/multichoice.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_nl_be_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_nl_be_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_nl_be_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni NL/BE Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/nlbe.headers.db.gz
+descriptors_url=http://krkadoni.com/nlbe.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_nordic_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_nordic_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_nordic_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni Nordic Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/nordic.headers.db.gz
+descriptors_url=http://krkadoni.com/nordic.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_nova_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_nova_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_nova_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni Nova Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/nova.headers.db.gz
+descriptors_url=http://krkadoni.com/nova.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_osn_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_osn_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_osn_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni OSN Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/osn.headers.db.gz
+descriptors_url=http://krkadoni.com/osn.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_poland_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_poland_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_poland_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni Poland Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/poland.headers.db.gz
+descriptors_url=http://krkadoni.com/poland.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_skyde_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_skyde_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_skyde_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni Sky DE Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/skyde.headers.db.gz
+descriptors_url=http://krkadoni.com/skyde.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_skyit_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_skyit_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_skyit_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni Sky IT Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/skyit.headers.db.gz
+descriptors_url=http://krkadoni.com/skyit.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_skylink_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_skylink_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_skylink_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni Skylink CZ/SK Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/skylink.headers.db.gz
+descriptors_url=http://krkadoni.com/skylink.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_skyuk_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_skyuk_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_skyuk_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni Sky UK Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/skyuk.headers.db.gz
+descriptors_url=http://krkadoni.com/skyuk.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_upc_xepgdb.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_upc_xepgdb.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/krkadoni_upc_xepgdb.conf	(revision 8762)
@@ -0,0 +1,4 @@
+description=Krkadoni UPC Direct Provider
+protocol=xepgdb
+headers_url=http://krkadoni.com/upc.headers.db.gz
+descriptors_url=http://krkadoni.com/upc.descriptors.db.gz
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/linuxsat_exussr_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/linuxsat_exussr_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/linuxsat_exussr_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Linuxsat ExUSSR XMLTV
+protocol=xmltv
+channels=http://linux-sat.tv/epg/ls.channels.xml.gz
+url=http://linux-sat.tv/epg/tvprogram_ua_ru.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/mediaprem_script.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/mediaprem_script.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/mediaprem_script.conf	(revision 8762)
@@ -0,0 +1,3 @@
+protocol=script
+filename=mediaprem/mediaprem.py
+description=MEDIAPREM: download EPG from Mediaset website
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rai_script.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rai_script.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rai_script.conf	(revision 8762)
@@ -0,0 +1,3 @@
+protocol=script
+filename=rai/rai.py
+description=RAI: download EPG from RAI website
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_benelux_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_benelux_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_benelux_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Benelux XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvbenl.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_bulgaria_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_bulgaria_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_bulgaria_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Bulgaria XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvbulsat.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_denmark_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_denmark_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_denmark_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Denmark XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels-denmark.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvnordic.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_erotic_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_erotic_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_erotic_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Erotic XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltverotic.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_finland_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_finland_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_finland_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Finland XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels-finland.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvnordic.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_france_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_france_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_france_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec France XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvcsat.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_germany_austria_swiss_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_germany_austria_swiss_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_germany_austria_swiss_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Germany/Austria/Swiss XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvskyde.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_greece_english_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_greece_english_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_greece_english_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Greece in English XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels-greece-en.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvnova.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_greece_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_greece_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_greece_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Greece XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvnova.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_hungary_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_hungary_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_hungary_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Hungary XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvmagyar.gz
+preferred_language=dut
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_italy_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_italy_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_italy_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Italy XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvskyit.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_norway_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_norway_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_norway_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Norway XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels-norway.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvnordic.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_osn_jsc_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_osn_jsc_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_osn_jsc_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec OSN/JSC XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvosn.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_poland_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_poland_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_poland_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Poland XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvpoland.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_portugal_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_portugal_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_portugal_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Portugal XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvportugal.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_romania_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_romania_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_romania_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Romania XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvromania.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_serbia_croatia_montenegro_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_serbia_croatia_montenegro_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_serbia_croatia_montenegro_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Serbia/Croatia/Montenegro XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvexyu.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_slovack_czech_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_slovack_czech_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_slovack_czech_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Slovak/Czech XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvskylink.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_slovenia_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_slovenia_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_slovenia_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Slovenia XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels-slovenia.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvexyu.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_spain_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_spain_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_spain_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Spain XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvdplus.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_sweden_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_sweden_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_sweden_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec Sweden XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels-sweden.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvnordic.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_uk_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_uk_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_uk_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec UK XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvuk.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_upc_direct_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_upc_direct_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_upc_direct_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec UK BBCi XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.oostwestedpnet.be/Box/rytecxmltvbbci.xml
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_west_africa_csat_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_west_africa_csat_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_west_africa_csat_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec West-Africa / Csat Horizons XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://www.xmltvepg.be/rytecxmltvcsathorizons.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_za_multichoice_dstv_osn_xmltv.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_za_multichoice_dstv_osn_xmltv.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/rytec_za_multichoice_dstv_osn_xmltv.conf	(revision 8762)
@@ -0,0 +1,5 @@
+description=Rytec ZA Multichoice/DSTV/OSN XMLTV
+protocol=xmltv
+channels=http://www.xmltvepg.be/rytec.channels.xml.gz
+url=http://zaxmltv.flash.za.org/schedule/ZA-XMLTV.xml.gz
+preferred_language=eng
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyit_hotbird_13.0.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyit_hotbird_13.0.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyit_hotbird_13.0.conf	(revision 8762)
@@ -0,0 +1,13 @@
+description=Sky Italia OpenTV (Hotbird on 13.0)
+# nid ,tsid, sid
+nid=64511
+tsid=5800
+sid=3635
+namespace=8519680
+# channels pids
+channels_pids=17
+# titles pids
+titles_pids=48|49|50|51|52|53|54|55
+# summaries pids
+summaries_pids=64|65|66|67|68|69|70|71
+protocol=opentv
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyit_hotbird_13.0.dict
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyit_hotbird_13.0.dict	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyit_hotbird_13.0.dict	(revision 8762)
@@ -0,0 +1,510 @@
+ =00001011010110001111010101010
+ =00001011010110001111010101011
+ =00001011010110001111010101100
+ =00001011010110001111010101101
+ =00001011010110001111010101110
+ =00001011010110001111010101111
+ =00001011010110001111010110000
+ =00001011010110001111010110001
+ =00001011010110001111010110010
+ =00001011010110001111010110011
+ =00001011010110001111010110100
+ =00001011010110001111010110101
+ =00001011010110001111010110110
+ =1001110
+ =00001011010110001111010110111
+ =00001011010110001111010111000
+ =00001011010110001111010111001
+ =00001011010110001111010111010
+ =00001011010110001111010111011
+ =00001011010110001111010111100
+ =00001011010110001111010111101
+ =00001011010110001111010111110
+ =00001011010110001111010111111
+ =00001011010110001111011000000
+ =00001011010110001111011000001
+ =00001011010110001111011000010
+ =00001011010110001111011000011
+ =00001011010110001111011000100
+ =00001011010110001111011000101
+ =00001011010110001111011000110
+ =00001011010110001111011000111
+ =00001011010110001111011001000
+ =01
+!=1110000011101
+"=11100010000100011
+#=00001011010110001111011001001
+$=00001011010110001111011001010
+%=00001011010110001111011001011
+&=11100010000101
+'=0000100
+(=0000101101010
+)=110100111111
+*=00001011010110001111011001100
++=000010110101100011111
+,=110000
+-=10110011
+.=100110
+/=111000100001001
+0=10010011
+1=100100000
+2=1111011001
+3=1110001110
+4=11000100101
+5=111101110100
+6=101100101111
+7=110100011110
+8=11010001110
+9=1111010111
+:=100100011
+;=10000111101
+<=00001011010110001111011001101
+==00001011010110001111011001110
+>=00001011010110001111011001111
+?=1100110110110
+@=1110001000010000
+A=00001010
+B=111101001
+C=10010100
+D=100001010
+E=111000000
+F=1110001100
+G=100101100
+H=1000011111
+I=1111011111
+J=1100010110
+K=11110100011
+L=001111101
+M=100001101
+N=100001011
+O=1100101011
+P=110100000
+Q=00001011000
+R=110010100
+S=10110100
+T=110101100
+U=110100010011
+V=1001000011
+W=1101000110
+X=1110001011001
+Y=1100011110011
+Z=1100010100110
+[=00001011010110001111011010000
+\=00001011010110001111011010001
+]=00001011010110001111011010010
+^=0000101101011000100
+_=00001011010110001111011010011
+`=00001011010111
+a=11111
+b=11100001
+c=111001
+d=1011000
+e=1010
+f=0011011
+g=000011
+h=10110110
+i=0001
+j=110100010000
+k=110001100
+l=1111001
+m=100010
+n=10111
+o=0010
+p=100011
+q=1110001001
+r=11011
+s=00000
+t=11101
+u=001110
+v=1100111
+w=001100110
+x=11100011110
+y=111101101
+z=0011010
+{=00001011010110001111011010100
+|=00001011010110001111011010101
+}=00001011010110001111011010110
+~=00001011010110001111011010111
+ =00001011010110001111011011000
+ =000010110101100000
+ =00001011010110001111011011001
+ =00001011010110001111011011010
+ =00001011010110001111011011011
+ =00001011010110001111011011100
+ =00001011010110001111011011101
+ =00001011010110001111011011110
+ =00001011010110001111011011111
+ =11100010000100010
+ =000010110101100001
+ =00001011010110001111011100000
+ =00001011010110001111011100001
+ =00001011010110001111011100010
+ =00001011010110001111011100011
+ =00001011010110001111011100100
+ =00001011010110001111011100101
+ =00001011010110001111011100110
+ =00001011010110001111011100111
+ =00001011010110001110
+ =00001011010110001111011101000
+ =00001011010110001111011101001
+ =00001011010110001111011101010
+ =00001011010110001111011101011
+ =0000101101011000101
+ =00001011010110001111011101100
+ =00001011010110001111011101101
+ =00001011010110001111011101110
+ =00001011010110001111011101111
+ =00001011010110001111011110000
+ =00001011010110001111011110001
+ =00001011010110001111011110010
+ =00001011010110001111011110011
+ =00001011010110001111011110100
+¡=00001011010110001111011110101
+¢=00001011010110001111011110110
+£=00001011010110001111011110111
+¤=00001011010110001111011111000
+¥=00001011010110001111011111001
+¦=00001011010110001111011111010
+§=00001011010110001111011111011
+¨=00001011010110001111011111100
+©=00001011010110001111011111101
+ª=00001011010110001111011111110
+«=00001011010110001111011111111
+¬=0000101101011000111100000000
+­=0000101101011000111100000001
+®=0000101101011000111100000010
+¯=0000101101011000111100000011
+°=0000101101011000111100000100
+±=0000101101011000111100000101
+²=0000101101011000111100000110
+³=0000101101011000111100000111
+´=0000101101011000111100001000
+µ=0000101101011000111100001001
+¶=0000101101011000111100001010
+·=0000101101011001
+¸=0000101101011000111100001011
+¹=0000101101011000111100001100
+º=0000101101011000111100001101
+»=0000101101011000111100001110
+¼=0000101101011000111100001111
+½=0000101101011000111100010000
+¾=0000101101011000111100010001
+¿=0000101101011000111100010010
+À=0000101101011000111100010011
+Á=0000101101011000111100010100
+Â=0000101101011000111100010101
+Ã=0000101101011000111100010110
+Ä=0000101101011000111100010111
+Å=0000101101011000111100011000
+Æ=000010110101101
+Ç=0000101101011000111100011001
+È=0000101101011000111100011010
+É=0000101101011000111100011011
+Ê=0000101101011000111100011100
+Ë=0000101101011000111100011101
+Ì=0000101101011000111100011110
+Í=0000101101011000111100011111
+Î=0000101101011000111100100000
+Ï=0000101101011000111100100001
+Ð=0000101101011000111100100010
+Ñ=0000101101011000111100100011
+Ò=0000101101011000111100100100
+Ó=0000101101011000111100100101
+Ô=0000101101011000111100100110
+Õ=0000101101011000111100100111
+Ö=0000101101011000111100101000
+×=0000101101011000111100101001
+Ø=0000101101011000111100101010
+Ù=0000101101011000111100101011
+Ú=0000101101011000111100101100
+Û=0000101101011000111100101101
+Ü=0000101101011000111100101110
+Ý=0000101101011000111100101111
+Þ=0000101101011000111100110000
+ß=0000101101011000111100110001
+à=0000101101011000110
+á=0000101101011000111100110010
+â=0000101101011000111100110011
+ã=0000101101011000111100110100
+ä=0000101101011000111100110101
+å=0000101101011000111100110110
+æ=0000101101011000111100110111
+ç=0000101101011000111100111000
+è=0000101101011000111100111001
+é=0000101101011000111100111010
+ê=0000101101011000111100111011
+ë=0000101101011000111100111100
+ì=0000101101011000111100111101
+í=0000101101011000111100111110
+î=0000101101011000111100111111
+ï=0000101101011000111101000000
+ð=0000101101011000111101000001
+ñ=0000101101011000111101000010
+ò=0000101101011000111101000011
+ó=0000101101011000111101000100
+ô=0000101101011000111101000101
+õ=0000101101011000111101000110
+ö=0000101101011000111101000111
+÷=0000101101011000111101001000
+ø=0000101101011000111101001001
+ù=0000101101011000111101001010
+ú=0000101101011000111101001011
+û=0000101101011000111101001100
+ü=0000101101011000111101001101
+ý=0000101101011000111101001110
+þ=0000101101011000111101001111
+ÿ=0000101101011000111101010000
+(dur=100001111000
+2001=001111100
+2002=111000110101
+Adulti=100001111001
+Alle=1100110111
+American=10110101100
+Argentina=110010101011
+Attualita'=110001000001
+Bateman=10010111111
+Bechis=1100010111011
+Campionato=1101001111000
+Carlos=1101000011101
+Cartoon=11110111011
+Club=10000110010
+Commedia=100001100001
+Con=10110101101
+D'Alo'=1100100011111
+Da=1001010111
+Dal=1111010100011
+Dalle=10010111110
+Drammatico=111101111001
+Durante=1101000111110
+Echeverria=1100011100110
+Emmanuelle=1100011100111
+Enzo=1101000100010
+Fares=00001011011
+Figli=1100100011000
+Film=1101011010
+Fine=100001001100
+Fiumi=00001011100
+Francia=10000110001
+Giallo=110001001000
+Giovanni=1100011101000
+Harron=10011110000
+ITV=1101000100100
+Il=0011001110
+In=1001011011
+Informazione=11110100001
+Intrattenimento=1000010000
+Italia=11100010001
+Javier=1100011101001
+Jean=10010101011
+John=1111011100101
+Kassovitz=00110000101
+L'appassionante=00001011101
+La=1001010110
+Le=11000100111
+Ma=1101001110
+Magazine=100001110010
+Mammuccari=1100011101010
+Manhattan=10110010010
+Marco=1110001011110
+Mary=10011110110
+Mathieu=00110000110
+Michael=1101001111011
+Momo=110010001011
+Nadia=00001011110
+News=110100111110
+Notiziario=101100101110
+Orario=1001000100
+Patrick=10110010110
+Paul=000010110011
+Per=11000100110
+Peter=1100101010101
+Programmazione=1110001101001
+Psycho=10011110111
+Regia=110010000
+Reno=00110000111
+Rosa=1100011110101
+Rubrica=1111011100100
+Sandrelli=1100100010001
+Seigner=1100011101011
+Servizi=001100000110
+Snow=100100001000
+Sorvino=1100011110110
+Stefania=1101011011010
+Stream=111101000100
+Street=10110101111
+Streghe=1100011101100
+TRAMA:=1100010111010
+Teo=110001110010
+USA=1101000101
+Un=11110111101
+Una=101100100010
+Veronesi=1100011101101
+Vincent=00110001001
+Wall=11000100001
+World=001100010110
+XXX=10000110011
+ad=1111010110
+affidare=00110000100
+ai=1001011110
+al=0011110
+alla=11010110111
+alle=111101110101
+amici=111000101110
+ammazzare=10011110001
+and=1111010101
+anfiteatro=1100100011001
+anni=10010101010
+as=110011010
+attraverso=1101011011001
+aver=000010110100
+bambina=1101000100011
+banda=1110001011000
+bello=10110101000
+brani=1100100010010
+broker=10011110010
+business=000010110010
+casa=101100100011
+casi=10000111010
+cassel=00001011111
+cerca=11100010100
+che=10010010
+chilometri=00110001111
+citta'=110001000101
+come=110001011100
+compagnia=1100110110001
+con=11010010
+conquista=1101000111111
+contro=110001000100
+crede=1110001111110
+cui=001100111110
+cultura=100001110001
+curiosita'=001100010111
+da=00110010
+dai=1101000100101
+dal=11110110000
+dalla=100101101001
+decidG266  :  dedicato=0000101101011000111101010001
+degli=110001000000
+dei=0011000110
+del=111100010
+della=1011001010
+delle=11000111000
+destra=1100101010001
+deve=1111010001011
+di=100000
+diabolici=1100100011010
+dice=1100110110000
+diretta=100100001011
+distanza=00110000000
+divide=10110010011
+divisi=1100011101110
+dolce=1101001111001
+domani=1111010100010
+due=1100011111
+e'=110001101
+ed=101101111
+essere=1110001000000
+esseri=1110001111101
+eventiG=0000101101011000111101010010
+fatti=001100111111
+feste=10110101001
+film=10000100011
+gemelli=1110001000011
+giorno=11110100000
+giovane=11100000110
+giovani=1111011110001
+gli=100101110
+grande=1110001011111
+grandi=1111010001010
+grigi'=1100100011011
+ha=1100010101
+il=11001011
+imbattere=1100100011100
+in=1101010
+incinta=1100101010000
+informazione=110001001001
+inizio=1001010100
+internazionale=100001110111
+interviste=100100001001
+la=11001100
+lavoro=11010000110
+le=11010111
+levatrice=1100011101111
+libro=1100011110100
+lo=111100011
+loro=11000101000
+ma=10011111
+maggiori=100001110110
+malcapitati=10110010000
+maschietto=1100011110000
+mondo=11100010101
+musica=111000001111
+nato=111101110011
+nel=11110111000
+nella=1111010100000
+nello=10000100100
+news=10010110101
+non=00110011110
+nord=1100100011101
+nuovi=001100000111
+of=1011010101
+ogni=100001110011
+ore=1101000010
+parte=1101011011011
+per=00111111
+piccola=1101001111010
+piu'=1001111010
+poliziotti=00110001110
+porpora=00110000001
+prima=1110001111100
+produttore=1100011110111
+programmazione=1110001101000
+proprio=1101011011000
+prossimo=1001000101
+quattro=1111011000110
+regime=1100011110001
+ricco=10110101110
+ricordi=1100101010100
+rovine=1110001000001
+salvare=1110000011100
+scrittore=1100110110111
+scrive=1101000011110
+serie=1111011000111
+servizi=100001110000
+settimanale=1100010100111
+si=11110000
+singolari=00110001000
+solo=110010001010
+sono=11000100011
+stesso=10000100010
+storia=11100011011
+streghe=1100100010000
+su=1110000010
+sua=10000100101
+successo=100101101000
+sui=110011011001
+sulle=100100001010
+suo=10000100111
+suoi=1101000011100
+tale=110010101001
+tempo=111101100010
+the=11110101001
+timida=1100100011110
+torturare=10011110011
+tra=110100110
+trasformarlo=1100011110010
+trecento=00110000010
+trovato=1101000011111
+tutto=110011011010
+ultimi=1100100010011
+un=11001001
+una=101101110
+uno=111000101101
+uomini=1111011110000
+vedono=00110001010
+vengono=100001001101
+verso=100001100000
+viaggio=110001010010
+viene=1111010100001
+vita=11000101111
+vuole=1110001111111
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyuk_astra2_28.2.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyuk_astra2_28.2.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyuk_astra2_28.2.conf	(revision 8762)
@@ -0,0 +1,13 @@
+description=Sky Uk OpenTV (Astra2 on 28.2)
+# nid ,tsid, sid
+nid=2
+tsid=2004
+sid=4152
+namespace=18481152
+# channels pids
+channels_pids=17
+# titles pids
+titles_pids=48|49|50|51|52|53|54|55
+# summaries pids
+summaries_pids=64|65|66|67|68|69|70|71
+protocol=opentv
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyuk_astra2_28.2.dict
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyuk_astra2_28.2.dict	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyuk_astra2_28.2.dict	(revision 8762)
@@ -0,0 +1,512 @@
+ =101010111000110000101001100
+ =101010111000110000101001101
+ =101010111000110000101001110
+ =101010111000110000101001111
+ =101010111000110000101010000
+ =101010111000110000101010001
+ =101010111000110000101010010
+ =101010111000110000101010011
+ =101010111000110000101010100
+=0001000
+ =1110111
+ =101010111000110000101010101
+ =101010111000110000101010110
+ =101010111000110000101010111
+ =101010111000110000101011000
+ =101010111000110000101011001
+ =101010111000110000101011010
+ =101010111000110000101011011
+ =101010111000110000101011100
+ =101010111000110000101011101
+ =101010111000110000101011110
+ =101010111000110000101011111
+ =101010111000110000101100000
+ =101010111000110000101100001
+ =101010111000110000101100010
+ =101010111000110000101100011
+ =101010111000110000101100100
+ =101010111000110000101100101
+ =101010111000110000101100110
+ =101010111000110000101100111
+ =101010111000110000101101000
+ =101010111000110000101101001
+ =110
+!=01000011000
+"=101010111000110000101101010
+#=101010111000110000101101011
+$=1010101110001101
+%=101010111000110000101101100
+&=10000011101
+'=10000010
+(=11101000101
+)=1010101100
+*=100010101110
++=101010111000110000101101101
+,=1011000
+-=10001011
+.=1110110
+/=00010100011110
+0=111010010
+1=101100111
+2=1000101000
+3=1000001111
+4=0001010000
+5=1110101000
+6=1000101001
+7=1000100010
+8=10001010110
+9=0100001101
+:=11101000110
+;=00010100010
+<=1110100011111
+==101010111000110000101101110
+>=1110101001100
+?=111010100111
+@=101010111000110001
+A=11100010
+B=01000000
+C=01000010
+D=111000111
+E=1110100000
+F=101010100
+G=100010000
+H=101010101
+I=1110100001
+J=000101001
+K=1110100111
+L=100000110
+M=10001001
+N=111010111
+O=010000010
+P=00010101
+Q=1000101010111
+R=111010110
+S=0001001
+T=0001011
+U=10101011101
+V=11101010101
+W=10110010
+X=1110001101101111
+Y=10101011110
+Z=1110101010000
+[=10101011100011001
+\=101010111000110000101101111
+]=11100011011011100
+^=101010111000110000101110000
+_=101010111000110000101110001
+`=11101010010
+a=1001
+b=1110000
+c=111001
+d=01001
+e=1111
+f=100001
+g=100011
+h=10111
+i=0101
+j=11100011010
+k=1000000
+l=10100
+m=101011
+n=0111
+o=0011
+p=000111
+q=10101011011
+r=0010
+s=0000
+t=0110
+u=101101
+v=1010100
+w=000110
+x=1110101011
+y=010001
+z=1011001100
+{=101010111000110000101110010
+|=101010111000110000101110011
+}=101010111000110000101110100
+~=101010111000110000101110101
+ =101010111000110000101110110
+ =101010111000110000101110111
+ =101010111000110000101111000
+ =101010111000110000101111001
+ =101010111000110000101111010
+ =101010111000110000101111011
+ =101010111000110000101111100
+ =101010111000110000101111101
+ =101010111000110000101111110
+ =101010111000110000101111111
+ =101010111000110000110000000
+ =101010111000110000110000001
+ =101010111000110000110000010
+ =101010111000110000110000011
+ =101010111000110000110000100
+ =101010111000110000110000101
+ =101010111000110000110000110
+ =101010111000110000110000111
+ =101010111000110000110001000
+ =101010111000110000110001001
+ =101010111000110000110001010
+ =101010111000110000110001011
+ =101010111000110000110001100
+ =101010111000110000110001101
+ =101010111000110000110001110
+ =101010111000110000110001111
+ =101010111000110000110010000
+ =101010111000110000110010001
+ =101010111000110000110010010
+ =11100011011011101
+ =101010111000110000110010011
+ =101010111000110000110010100
+ =101010111000110000110010101
+ =101010111000110000110010110
+¡=101010111000110000110010111
+¢=101010111000110000110011000
+£=101010111000110000110011001
+¤=101010111000110000110011010
+¥=101010111000110000110011011
+¦=101010111000110000110011100
+§=101010111000110000110011101
+¨=101010111000110000110011110
+©=101010111000110000110011111
+ª=101010111000110000110100000
+«=101010111000110000110100001
+¬=101010111000110000110100010
+­=101010111000110000110100011
+®=101010111000110000110100100
+¯=101010111000110000110100101
+°=101010111000110000110100110
+±=101010111000110000110100111
+²=101010111000110000110101000
+³=101010111000110000110101001
+´=101010111000110000110101010
+µ=101010111000110000110101011
+¶=101010111000110000110101100
+·=101010111000110000110101101
+¸=101010111000110000110101110
+¹=101010111000110000110101111
+º=101010111000110000110110000
+»=101010111000110000110110001
+¼=101010111000110000110110010
+½=101010111000110000110110011
+¾=101010111000110000110110100
+¿=101010111000110000110110101
+À=101010111000110000110110110
+Á=101010111000110000110110111
+Â=101010111000110000110111000
+Ã=101010111000110000110111001
+Ä=101010111000110000110111010
+Å=101010111000110000110111011
+Æ=101010111000110000110111100
+Ç=101010111000110000110111101
+È=101010111000110000110111110
+É=101010111000110000110111111
+Ê=101010111000110000111000000
+Ë=101010111000110000111000001
+Ì=101010111000110000111000010
+Í=101010111000110000111000011
+Î=101010111000110000111000100
+Ï=101010111000110000111000101
+Ð=101010111000110000111000110
+Ñ=101010111000110000111000111
+Ò=101010111000110000111001000
+Ó=101010111000110000111001001
+Ô=101010111000110000111001010
+Õ=101010111000110000111001011
+Ö=101010111000110000111001100
+×=101010111000110000111001101
+Ø=101010111000110000111001110
+Ù=101010111000110000111001111
+Ú=101010111000110000111010000
+Û=101010111000110000111010001
+Ü=101010111000110000111010010
+Ý=101010111000110000111010011
+Þ=101010111000110000111010100
+ß=101010111000110000111010101
+à=101010111000110000111010110
+á=101010111000110000111010111
+â=101010111000110000111011000
+ã=101010111000110000111011001
+ä=101010111000110000111011010
+å=101010111000110000111011011
+æ=101010111000110000111011100
+ç=101010111000110000111011101
+è=101010111000110000111011110
+é=101010111000110000111011111
+ê=101010111000110000111100000
+ë=101010111000110000111100001
+ì=101010111000110000111100010
+í=101010111000110000111100011
+î=101010111000110000111100100
+ï=101010111000110000111100101
+ð=101010111000110000111100110
+ñ=101010111000110000111100111
+ò=101010111000110000111101000
+ó=101010111000110000111101001
+ô=101010111000110000111101010
+õ=101010111000110000111101011
+ö=101010111000110000111101100
+÷=101010111000110000111101101
+ø=101010111000110000111101110
+ù=101010111000110000111101111
+ú=101010111000110000111110000
+û=101010111000110000111110001
+ü=101010111000110000111110010
+ý=101010111000110000111110011
+þ=101010111000110000111110100
+ÿ=101010111000110000111110101
+(Including =10101011111110
+(New Series)=11101000100010
+(Part =1110100011101
+(Repeat)=1110100110
+(Stereo)=010000111
+(Stereo) (Teletext)=010000011
+(Teletext)=1110001100
+(Widescreen)=100000111001110
+Action=101010111000111
+Adventures=10110011011111
+America=0100001100100
+Animated=111010100110111
+Australia=0100001100101
+Away=11101010100010
+BBC=10101011111111
+Baby=11100011011000
+Best=11101010100011
+Big=10110011011000
+Bill=1000101011111
+Black=1000101010000
+Blue=1011001101110
+Breakfast=000101000110
+Britain=1010101111100
+British=1110100011100
+Business=0100001100110
+Call=1010101111101
+Cartoon=10101011100000
+Channel=10101011100001
+Children=11101010100111
+Clock=11100011011001
+Comedy=11101000100011
+Cook=111010101001010
+Country=111010100110110
+Directed by =101010110100
+Drama=0100001100111
+East=1000101010001
+Education=100000111001111
+English=00010100011111
+Europe=0001010001110
+Extra=10110011011001
+Final=10101011100010
+Financial=111000110110100
+For=111000110111
+French=11101000111101
+From=1000101010010
+George=1010101111110
+Get=1000100011010
+Girls=10001000110110
+Golden=10001000110111
+Golf=111010101001011
+Good=1010101101010
+Great=11101000100100
+Hampshire=111010101001100
+Headlines=1000101010011
+Hear=11101010011010
+Hill=1000001110000
+Hollywood=111000110110101
+Home=1000101010100
+Hour=11101000100101
+House=1000001110010
+How=1010101101011
+ITN=11101010100100
+Important=111010101001101
+Including=1000101011110
+International=11101000100110
+John=10001000111
+Last=11101000100111
+Late=10000011100110
+Learn=10001010101100
+Little=10001010101101
+Live=1110100010000
+London=11101000111100
+Look=10110011011110
+Lunch=111000110110110
+Man=1000101010101
+Mark=1000001110001
+Meridian=101010111001
+Michael=1011001101101
+Minutes=101010111000110000111110110
+More=101010111000110000111110111
+Morning=101010111000110000111111000
+Murder=101010111000110000111111001
+Nation=101010111000110000111111010
+Neighbours=101010111000110000111111011
+New=101010111000110000111111100
+News & Weather=101010111000110000111111101
+News And Weather=101010111000110000111111110
+Paul=101010111000110000111111111
+Plus=10101011100011000000000000
+Prayer=10101011100011000000000001
+Present=10101011100011000000000010
+Presented by=10101011100011000000000011
+Quiz=10101011100011000000000100
+Regional=10101011100011000000000101
+Represent=10101011100011000000000110
+Resource=10101011100011000000000111
+Review=10101011100011000000001000
+Richard=10101011100011000000001001
+School=10101011100011000000001010
+Series=10101011100011000000001011
+Service=10101011100011000000001100
+Show=10101011100011000000001101
+Smith=10101011100011000000001110
+South=10101011100011000000001111
+Sport=10101011100011000000010000
+Star=10101011100011000000010001
+Street=10101011100011000000010010
+TV=10101011100011000000010011
+Teaching=10101011100011000000010100
+The=10101011100011000000010101
+Today=10101011100011000000010110
+Tonight=10101011100011000000010111
+Weather=10101011100011000000011000
+Western=10101011100011000000011001
+Westminster=10101011100011000000011010
+William=10101011100011000000011011
+With=10101011100011000000011100
+World=10101011100011000000011101
+about=10101011100011000000011110
+action-packed=10101011100011000000011111
+adventure=10101011100011000000100000
+afternoon=10101011100011000000100001
+alert=10101011100011000000100010
+all-star cast=10101011100011000000100011
+and=10101011100011000000100100
+anywhere=10101011100011000000100101
+audience=10101011100011000000100110
+based=10101011100011000000100111
+book=10101011100011000000101000
+business=10101011100011000000101001
+but=10101011100011000000101010
+celebrity=10101011100011000000101011
+chance=10101011100011000000101100
+chat=10101011100011000000101101
+child=10101011100011000000101110
+classic=10101011100011000000101111
+consumer=10101011100011000000110000
+contestants=10101011100011000000110001
+continues=10101011100011000000110010
+controversial=10101011100011000000110011
+dealer=10101011100011000000110100
+deliver=10101011100011000000110101
+discuss=10101011100011000000110110
+document=10101011100011000000110111
+drama=10101011100011000000111000
+edition=10101011100011000000111001
+education=10101011100011000000111010
+events=10101011100011000000111011
+every=10101011100011000000111100
+excellent=10101011100011000000111101
+eyed=10101011100011000000111110
+family=10101011100011000000111111
+famous=10101011100011000001000000
+featur=10101011100011000001000001
+film=10101011100011000001000010
+football=10101011100011000001000011
+for=10101011100011000001000100
+from=10101011100011000001000101
+general knowledge=10101011100011000001000110
+get=10101011100011000001000111
+guest=10101011100011000001001000
+guests=10101011100011000001001001
+has=10101011100011000001001010
+have=10101011100011000001001011
+headline=10101011100011000001001100
+her=10101011100011000001001101
+his=10101011100011000001001110
+home and abroad=10101011100011000001001111
+host=10101011100011000001010000
+how=10101011100011000001010001
+in=10101011100011000001010010
+including=10101011100011000001010011
+international=10101011100011000001010100
+interview=10101011100011000001010101
+introduce=10101011100011000001010110
+investigat=10101011100011000001010111
+invites=10101011100011000001011000
+issue=10101011100011000001011001
+knowledge=10101011100011000001011010
+life=10101011100011000001011011
+live=10101011100011000001011100
+look=10101011100011000001011101
+magazine=10101011100011000001011110
+meets =10101011100011000001011111
+morning=10101011100011000001100000
+morning magazine=10101011100011000001100001
+music=10101011100011000001100010
+near=10101011100011000001100011
+network=10101011100011000001100100
+new=10101011100011000001100101
+new series=10101011100011000001100110
+night=10101011100011000001100111
+of=10101011100011000001101000
+on=10101011100011000001101001
+onight=10101011100011000001101010
+out=10101011100011000001101011
+over=10101011100011000001101100
+part=10101011100011000001101101
+people=10101011100011000001101110
+phone=10101011100011000001101111
+poli=10101011100011000001110000
+police=10101011100011000001110001
+political chat show=10101011100011000001110010
+popular=10101011100011000001110011
+presented by =10101011100011000001110100
+programm=10101011100011000001110101
+quiz=10101011100011000001110110
+reconstruction=10101011100011000001110111
+report=10101011100011000001111000
+review=10101011100011000001111001
+school=10101011100011000001111010
+series=10101011100011000001111011
+short =10101011100011000001111100
+show=10101011100011000001111101
+some=10101011100011000001111110
+starring=10101011100011000001111111
+stars=10101011100011000010000000
+stories=10101011100011000010000001
+story=10101011100011000010000010
+studio=10101011100011000010000011
+surprise=10101011100011000010000100
+teller=10101011100011000010000101
+that=10101011100011000010000110
+the=10101011100011000010000111
+their=10101011100011000010001000
+them=10101011100011000010001001
+they=10101011100011000010001010
+this=10101011100011000010001011
+through=10101011100011000010001100
+to=10101011100011000010001101
+top=10101011100011000010001110
+trans=10101011100011000010001111
+under=10101011100011000010010000
+up=10101011100011000010010001
+very=10101011100011000010010010
+video=10101011100011000010010011
+view=10101011100011000010010100
+vintage=10101011100011000010010101
+visit=10101011100011000010010110
+was=10101011100011000010010111
+way=10101011100011000010011000
+week=10101011100011000010011001
+well=10101011100011000010011010
+what=10101011100011000010011011
+when=10101011100011000010011100
+which=10101011100011000010011101
+while=10101011100011000010011110
+who=10101011100011000010011111
+will=10101011100011000010100000
+win=10101011100011000010100001
+with=10101011100011000010100010
+words=10101011100011000010100011
+world=10101011100011000010100100
+written=10101011100011000010100101
+year=100010001100
+you=10110011010
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyuk_astra2_28.4.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyuk_astra2_28.4.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyuk_astra2_28.4.conf	(revision 8762)
@@ -0,0 +1,13 @@
+description=Sky Uk OpenTV (Astra2 on 28.4)
+# nid ,tsid, sid
+nid=2
+tsid=2004
+sid=4152
+namespace=18612224
+# channels pids
+channels_pids=17
+# titles pids
+titles_pids=48|49|50|51|52|53|54|55
+# summaries pids
+summaries_pids=64|65|66|67|68|69|70|71
+protocol=opentv
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyuk_astra2_28.4.dict
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyuk_astra2_28.4.dict	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/skyuk_astra2_28.4.dict	(revision 8762)
@@ -0,0 +1,512 @@
+ =101010111000110000101001100
+ =101010111000110000101001101
+ =101010111000110000101001110
+ =101010111000110000101001111
+ =101010111000110000101010000
+ =101010111000110000101010001
+ =101010111000110000101010010
+ =101010111000110000101010011
+ =101010111000110000101010100
+=0001000
+ =1110111
+ =101010111000110000101010101
+ =101010111000110000101010110
+ =101010111000110000101010111
+ =101010111000110000101011000
+ =101010111000110000101011001
+ =101010111000110000101011010
+ =101010111000110000101011011
+ =101010111000110000101011100
+ =101010111000110000101011101
+ =101010111000110000101011110
+ =101010111000110000101011111
+ =101010111000110000101100000
+ =101010111000110000101100001
+ =101010111000110000101100010
+ =101010111000110000101100011
+ =101010111000110000101100100
+ =101010111000110000101100101
+ =101010111000110000101100110
+ =101010111000110000101100111
+ =101010111000110000101101000
+ =101010111000110000101101001
+ =110
+!=01000011000
+"=101010111000110000101101010
+#=101010111000110000101101011
+$=1010101110001101
+%=101010111000110000101101100
+&=10000011101
+'=10000010
+(=11101000101
+)=1010101100
+*=100010101110
++=101010111000110000101101101
+,=1011000
+-=10001011
+.=1110110
+/=00010100011110
+0=111010010
+1=101100111
+2=1000101000
+3=1000001111
+4=0001010000
+5=1110101000
+6=1000101001
+7=1000100010
+8=10001010110
+9=0100001101
+:=11101000110
+;=00010100010
+<=1110100011111
+==101010111000110000101101110
+>=1110101001100
+?=111010100111
+@=101010111000110001
+A=11100010
+B=01000000
+C=01000010
+D=111000111
+E=1110100000
+F=101010100
+G=100010000
+H=101010101
+I=1110100001
+J=000101001
+K=1110100111
+L=100000110
+M=10001001
+N=111010111
+O=010000010
+P=00010101
+Q=1000101010111
+R=111010110
+S=0001001
+T=0001011
+U=10101011101
+V=11101010101
+W=10110010
+X=1110001101101111
+Y=10101011110
+Z=1110101010000
+[=10101011100011001
+\=101010111000110000101101111
+]=11100011011011100
+^=101010111000110000101110000
+_=101010111000110000101110001
+`=11101010010
+a=1001
+b=1110000
+c=111001
+d=01001
+e=1111
+f=100001
+g=100011
+h=10111
+i=0101
+j=11100011010
+k=1000000
+l=10100
+m=101011
+n=0111
+o=0011
+p=000111
+q=10101011011
+r=0010
+s=0000
+t=0110
+u=101101
+v=1010100
+w=000110
+x=1110101011
+y=010001
+z=1011001100
+{=101010111000110000101110010
+|=101010111000110000101110011
+}=101010111000110000101110100
+~=101010111000110000101110101
+ =101010111000110000101110110
+ =101010111000110000101110111
+ =101010111000110000101111000
+ =101010111000110000101111001
+ =101010111000110000101111010
+ =101010111000110000101111011
+ =101010111000110000101111100
+ =101010111000110000101111101
+ =101010111000110000101111110
+ =101010111000110000101111111
+ =101010111000110000110000000
+ =101010111000110000110000001
+ =101010111000110000110000010
+ =101010111000110000110000011
+ =101010111000110000110000100
+ =101010111000110000110000101
+ =101010111000110000110000110
+ =101010111000110000110000111
+ =101010111000110000110001000
+ =101010111000110000110001001
+ =101010111000110000110001010
+ =101010111000110000110001011
+ =101010111000110000110001100
+ =101010111000110000110001101
+ =101010111000110000110001110
+ =101010111000110000110001111
+ =101010111000110000110010000
+ =101010111000110000110010001
+ =101010111000110000110010010
+ =11100011011011101
+ =101010111000110000110010011
+ =101010111000110000110010100
+ =101010111000110000110010101
+ =101010111000110000110010110
+¡=101010111000110000110010111
+¢=101010111000110000110011000
+£=101010111000110000110011001
+¤=101010111000110000110011010
+¥=101010111000110000110011011
+¦=101010111000110000110011100
+§=101010111000110000110011101
+¨=101010111000110000110011110
+©=101010111000110000110011111
+ª=101010111000110000110100000
+«=101010111000110000110100001
+¬=101010111000110000110100010
+­=101010111000110000110100011
+®=101010111000110000110100100
+¯=101010111000110000110100101
+°=101010111000110000110100110
+±=101010111000110000110100111
+²=101010111000110000110101000
+³=101010111000110000110101001
+´=101010111000110000110101010
+µ=101010111000110000110101011
+¶=101010111000110000110101100
+·=101010111000110000110101101
+¸=101010111000110000110101110
+¹=101010111000110000110101111
+º=101010111000110000110110000
+»=101010111000110000110110001
+¼=101010111000110000110110010
+½=101010111000110000110110011
+¾=101010111000110000110110100
+¿=101010111000110000110110101
+À=101010111000110000110110110
+Á=101010111000110000110110111
+Â=101010111000110000110111000
+Ã=101010111000110000110111001
+Ä=101010111000110000110111010
+Å=101010111000110000110111011
+Æ=101010111000110000110111100
+Ç=101010111000110000110111101
+È=101010111000110000110111110
+É=101010111000110000110111111
+Ê=101010111000110000111000000
+Ë=101010111000110000111000001
+Ì=101010111000110000111000010
+Í=101010111000110000111000011
+Î=101010111000110000111000100
+Ï=101010111000110000111000101
+Ð=101010111000110000111000110
+Ñ=101010111000110000111000111
+Ò=101010111000110000111001000
+Ó=101010111000110000111001001
+Ô=101010111000110000111001010
+Õ=101010111000110000111001011
+Ö=101010111000110000111001100
+×=101010111000110000111001101
+Ø=101010111000110000111001110
+Ù=101010111000110000111001111
+Ú=101010111000110000111010000
+Û=101010111000110000111010001
+Ü=101010111000110000111010010
+Ý=101010111000110000111010011
+Þ=101010111000110000111010100
+ß=101010111000110000111010101
+à=101010111000110000111010110
+á=101010111000110000111010111
+â=101010111000110000111011000
+ã=101010111000110000111011001
+ä=101010111000110000111011010
+å=101010111000110000111011011
+æ=101010111000110000111011100
+ç=101010111000110000111011101
+è=101010111000110000111011110
+é=101010111000110000111011111
+ê=101010111000110000111100000
+ë=101010111000110000111100001
+ì=101010111000110000111100010
+í=101010111000110000111100011
+î=101010111000110000111100100
+ï=101010111000110000111100101
+ð=101010111000110000111100110
+ñ=101010111000110000111100111
+ò=101010111000110000111101000
+ó=101010111000110000111101001
+ô=101010111000110000111101010
+õ=101010111000110000111101011
+ö=101010111000110000111101100
+÷=101010111000110000111101101
+ø=101010111000110000111101110
+ù=101010111000110000111101111
+ú=101010111000110000111110000
+û=101010111000110000111110001
+ü=101010111000110000111110010
+ý=101010111000110000111110011
+þ=101010111000110000111110100
+ÿ=101010111000110000111110101
+(Including =10101011111110
+(New Series)=11101000100010
+(Part =1110100011101
+(Repeat)=1110100110
+(Stereo)=010000111
+(Stereo) (Teletext)=010000011
+(Teletext)=1110001100
+(Widescreen)=100000111001110
+Action=101010111000111
+Adventures=10110011011111
+America=0100001100100
+Animated=111010100110111
+Australia=0100001100101
+Away=11101010100010
+BBC=10101011111111
+Baby=11100011011000
+Best=11101010100011
+Big=10110011011000
+Bill=1000101011111
+Black=1000101010000
+Blue=1011001101110
+Breakfast=000101000110
+Britain=1010101111100
+British=1110100011100
+Business=0100001100110
+Call=1010101111101
+Cartoon=10101011100000
+Channel=10101011100001
+Children=11101010100111
+Clock=11100011011001
+Comedy=11101000100011
+Cook=111010101001010
+Country=111010100110110
+Directed by =101010110100
+Drama=0100001100111
+East=1000101010001
+Education=100000111001111
+English=00010100011111
+Europe=0001010001110
+Extra=10110011011001
+Final=10101011100010
+Financial=111000110110100
+For=111000110111
+French=11101000111101
+From=1000101010010
+George=1010101111110
+Get=1000100011010
+Girls=10001000110110
+Golden=10001000110111
+Golf=111010101001011
+Good=1010101101010
+Great=11101000100100
+Hampshire=111010101001100
+Headlines=1000101010011
+Hear=11101010011010
+Hill=1000001110000
+Hollywood=111000110110101
+Home=1000101010100
+Hour=11101000100101
+House=1000001110010
+How=1010101101011
+ITN=11101010100100
+Important=111010101001101
+Including=1000101011110
+International=11101000100110
+John=10001000111
+Last=11101000100111
+Late=10000011100110
+Learn=10001010101100
+Little=10001010101101
+Live=1110100010000
+London=11101000111100
+Look=10110011011110
+Lunch=111000110110110
+Man=1000101010101
+Mark=1000001110001
+Meridian=101010111001
+Michael=1011001101101
+Minutes=101010111000110000111110110
+More=101010111000110000111110111
+Morning=101010111000110000111111000
+Murder=101010111000110000111111001
+Nation=101010111000110000111111010
+Neighbours=101010111000110000111111011
+New=101010111000110000111111100
+News & Weather=101010111000110000111111101
+News And Weather=101010111000110000111111110
+Paul=101010111000110000111111111
+Plus=10101011100011000000000000
+Prayer=10101011100011000000000001
+Present=10101011100011000000000010
+Presented by=10101011100011000000000011
+Quiz=10101011100011000000000100
+Regional=10101011100011000000000101
+Represent=10101011100011000000000110
+Resource=10101011100011000000000111
+Review=10101011100011000000001000
+Richard=10101011100011000000001001
+School=10101011100011000000001010
+Series=10101011100011000000001011
+Service=10101011100011000000001100
+Show=10101011100011000000001101
+Smith=10101011100011000000001110
+South=10101011100011000000001111
+Sport=10101011100011000000010000
+Star=10101011100011000000010001
+Street=10101011100011000000010010
+TV=10101011100011000000010011
+Teaching=10101011100011000000010100
+The=10101011100011000000010101
+Today=10101011100011000000010110
+Tonight=10101011100011000000010111
+Weather=10101011100011000000011000
+Western=10101011100011000000011001
+Westminster=10101011100011000000011010
+William=10101011100011000000011011
+With=10101011100011000000011100
+World=10101011100011000000011101
+about=10101011100011000000011110
+action-packed=10101011100011000000011111
+adventure=10101011100011000000100000
+afternoon=10101011100011000000100001
+alert=10101011100011000000100010
+all-star cast=10101011100011000000100011
+and=10101011100011000000100100
+anywhere=10101011100011000000100101
+audience=10101011100011000000100110
+based=10101011100011000000100111
+book=10101011100011000000101000
+business=10101011100011000000101001
+but=10101011100011000000101010
+celebrity=10101011100011000000101011
+chance=10101011100011000000101100
+chat=10101011100011000000101101
+child=10101011100011000000101110
+classic=10101011100011000000101111
+consumer=10101011100011000000110000
+contestants=10101011100011000000110001
+continues=10101011100011000000110010
+controversial=10101011100011000000110011
+dealer=10101011100011000000110100
+deliver=10101011100011000000110101
+discuss=10101011100011000000110110
+document=10101011100011000000110111
+drama=10101011100011000000111000
+edition=10101011100011000000111001
+education=10101011100011000000111010
+events=10101011100011000000111011
+every=10101011100011000000111100
+excellent=10101011100011000000111101
+eyed=10101011100011000000111110
+family=10101011100011000000111111
+famous=10101011100011000001000000
+featur=10101011100011000001000001
+film=10101011100011000001000010
+football=10101011100011000001000011
+for=10101011100011000001000100
+from=10101011100011000001000101
+general knowledge=10101011100011000001000110
+get=10101011100011000001000111
+guest=10101011100011000001001000
+guests=10101011100011000001001001
+has=10101011100011000001001010
+have=10101011100011000001001011
+headline=10101011100011000001001100
+her=10101011100011000001001101
+his=10101011100011000001001110
+home and abroad=10101011100011000001001111
+host=10101011100011000001010000
+how=10101011100011000001010001
+in=10101011100011000001010010
+including=10101011100011000001010011
+international=10101011100011000001010100
+interview=10101011100011000001010101
+introduce=10101011100011000001010110
+investigat=10101011100011000001010111
+invites=10101011100011000001011000
+issue=10101011100011000001011001
+knowledge=10101011100011000001011010
+life=10101011100011000001011011
+live=10101011100011000001011100
+look=10101011100011000001011101
+magazine=10101011100011000001011110
+meets =10101011100011000001011111
+morning=10101011100011000001100000
+morning magazine=10101011100011000001100001
+music=10101011100011000001100010
+near=10101011100011000001100011
+network=10101011100011000001100100
+new=10101011100011000001100101
+new series=10101011100011000001100110
+night=10101011100011000001100111
+of=10101011100011000001101000
+on=10101011100011000001101001
+onight=10101011100011000001101010
+out=10101011100011000001101011
+over=10101011100011000001101100
+part=10101011100011000001101101
+people=10101011100011000001101110
+phone=10101011100011000001101111
+poli=10101011100011000001110000
+police=10101011100011000001110001
+political chat show=10101011100011000001110010
+popular=10101011100011000001110011
+presented by =10101011100011000001110100
+programm=10101011100011000001110101
+quiz=10101011100011000001110110
+reconstruction=10101011100011000001110111
+report=10101011100011000001111000
+review=10101011100011000001111001
+school=10101011100011000001111010
+series=10101011100011000001111011
+short =10101011100011000001111100
+show=10101011100011000001111101
+some=10101011100011000001111110
+starring=10101011100011000001111111
+stars=10101011100011000010000000
+stories=10101011100011000010000001
+story=10101011100011000010000010
+studio=10101011100011000010000011
+surprise=10101011100011000010000100
+teller=10101011100011000010000101
+that=10101011100011000010000110
+the=10101011100011000010000111
+their=10101011100011000010001000
+them=10101011100011000010001001
+they=10101011100011000010001010
+this=10101011100011000010001011
+through=10101011100011000010001100
+to=10101011100011000010001101
+top=10101011100011000010001110
+trans=10101011100011000010001111
+under=10101011100011000010010000
+up=10101011100011000010010001
+very=10101011100011000010010010
+video=10101011100011000010010011
+view=10101011100011000010010100
+vintage=10101011100011000010010101
+visit=10101011100011000010010110
+was=10101011100011000010010111
+way=10101011100011000010011000
+week=10101011100011000010011001
+well=10101011100011000010011010
+what=10101011100011000010011011
+when=10101011100011000010011100
+which=10101011100011000010011101
+while=10101011100011000010011110
+who=10101011100011000010011111
+will=10101011100011000010100000
+win=10101011100011000010100001
+with=10101011100011000010100010
+words=10101011100011000010100011
+world=10101011100011000010100100
+written=10101011100011000010100101
+year=100010001100
+you=10110011010
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/test_script.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/test_script.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/providers/test_script.conf	(revision 8762)
@@ -0,0 +1,3 @@
+protocol=script
+filename=test.py
+description=example test script (do nothing)
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/alias/alias.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/alias/alias.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/alias/alias.conf	(revision 8762)
@@ -0,0 +1,59 @@
+# alias.conf by ambrosa http://www.ambrosa.net
+# configuration file
+# 
+
+# how to setup [aliases] section
+#
+# format:
+# SOURCE=DESTINATION
+# epg data will be copied from SOURCE to DESTINATION
+#
+# SOURCE is:
+# channel_name-provider_name
+#
+#   or
+#
+# SID-TSID-ONID
+# i.e. 0002:00820000:1770:0110:1:0
+#       SID:   ns   :TSID:ONID:stype:unused
+# SID = 0002  TSID = 1770  ONID = 0110
+#
+#
+# DESTINATION is:
+# channel_name[,channel_name...]
+#
+#
+# Examples:
+# canale5-mediaset=canale 5
+# epg data from "canale 5" provider "mediaset" will be copied to "canale 5" (every provider)
+#
+# canale5-mediaset=canale 5,canale cinque,canale5
+# epg data from "canale 5" provider "mediaset" will be copied to "canale 5" (every provider) and
+# to "canale cinque" (every provider) and to "canale5" (same name as source but different provider than "mediaset")
+#
+# 0002-1770-0110=canale 5
+# epg data from sid "0002:00820000:1770:0110:1:0" will be copied to "canale 5" (every provider)
+#
+# 0002-1770-0110=canale 5,canale cinque,canale5
+# epg data from "0002:00820000:1770:0110:1:0"  will be copied to "canale 5" (every provider) and
+# to "canale cinque" (every provider) and to "canale5" (every provider)
+#
+#
+#
+# note 1: channel_name and provider_name are case insensitive
+#
+# note 2: SID/TSID/ONID can be read using remote control MENU->INFORMATION->CURRENT CHANNEL INFORMATION
+#         ServiceReference looks like 
+#         1:0:19:106A:2008:FBFF:820000:0:0: 
+#         the format is
+#         1:0:19:SID :TSID:ONID:820000:0:0:
+#         so the SOURCE will be: 
+#         106A-2008-FBFF=.......
+
+
+# ALIASES configuration section
+[aliases]
+
+
+canale 5-mediaset=canale 5,canale5
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/alias/alias.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/alias/alias.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/alias/alias.py	(revision 8762)
@@ -0,0 +1,234 @@
+#!/usr/bin/python
+# alias.py  by Ambrosa http://www.ambrosa.net
+# this module is used for copy epg from a channel to another
+
+__author__ = "ambrosa http://www.ambrosa.net"
+__copyright__ = "Copyright (C) 2008-2011 Alessandro Ambrosini"
+__license__ = "CreativeCommons by-nc-sa http://creativecommons.org/licenses/by-nc-sa/3.0/"
+
+import os
+import sys
+import ConfigParser
+
+# import CrossEPG functions
+import crossepg
+
+# location of local python modules under "scripts/lib" dir.
+# add it to sys.path()
+crossepg_instroot = crossepg.epgdb_get_installroot()
+if crossepg_instroot == False:
+	sys.exit(1)
+libdir = os.path.join(crossepg_instroot , 'scripts/lib')
+sys.path.append(libdir)
+
+# import local modules
+import sgmllib
+import scriptlib
+
+
+class main:
+
+	# main config file
+	CONF_CONFIGFILENAME = "alias.conf"
+
+	# log text
+	CONF_LOG_SCRIPT_NAME = "ALIAS EPG"
+	CONF_LOG_PREFIX = "ALIAS "
+
+
+	def log(self,s,video=0):
+		self.logging.log(self.CONF_LOG_PREFIX + str(s))
+		if video == 1:
+			self.log2video(str(s))
+
+	def log2video(self,s):
+		self.logging.log2video_status(str(s))
+
+
+
+	def __init__(self,confdir,dbroot):
+
+		# initialize logging
+		self.logging = scriptlib.logging_class()
+		# write to video OSD the script name
+		self.logging.log2video_scriptname(self.CONF_LOG_SCRIPT_NAME)
+
+
+		CONF_FILE = os.path.join(confdir,self.CONF_CONFIGFILENAME)
+		if not os.path.exists(CONF_FILE) :
+			self.log("ERROR: %s not present" % CONF_FILE)
+			sys.exit(1)
+
+		config = ConfigParser.ConfigParser()
+		#config.optionxform = str  # needed to return case sensitive index
+		config.read(CONF_FILE)
+
+		# reading [aliases] section
+		temp=config.items("aliases");
+
+		self.CHANNELLIST = {}
+		# create a dictionary (Python array) with index = channel ID
+		for i in temp:
+			self.CHANNELLIST[i[0]] = unicode(i[1],'utf-8')
+
+		if len(self.CHANNELLIST) == 0 :
+			self.log("ERROR: [aliases] section empty ?")
+			sys.exit(1)
+
+
+# ----------------------------------------------------------------------
+
+
+	def do_epg_alias(self):
+		self.log("--- START PROCESSING ---")
+		self.log("Loading lamedb indexed by channel name")
+		lamedb = scriptlib.lamedb_class()
+
+		self.log("Initialize CrossEPG database")
+		crossdb = scriptlib.crossepg_db_class()
+		crossdb.open_db()
+
+		total_events = 0
+
+		for src_channel in self.CHANNELLIST :
+
+			dst_channels = self.CHANNELLIST[src_channel].split(',')
+
+			if src_channel.count('-') == 1 :
+				src_chname = src_channel.split('-')[0].strip(' \n\r').lower()
+				src_provname = src_channel.split('-')[1].strip(' \n\r').lower()
+
+				src_sidbyname = []
+				src_sidprovidbyname = lamedb.get_sidprovid_byname(src_chname)
+				for p in src_sidprovidbyname:
+					if p[1] == src_provname :
+						# a channel can have zero or more SID (different channel with same name)
+						# return the list [ 0e1f:00820000:0708:00c8:1:0 , 1d20:00820000:2fa8:013e:1:0 , ..... ]
+						# return [] if channel name is not in lamedb
+						src_sidbyname = p[0]
+						ch_sid = lamedb.convert_sid(src_sidbyname)
+						if len(ch_sid) == 0 :
+							self.log("SID \"%s\" invalid, try next" % src_sidbyname)
+							continue
+
+						src_epgdb_channel = crossepg.epgdb_channels_get_by_freq(ch_sid[2],ch_sid[1],ch_sid[0]);
+						if not src_epgdb_channel :
+							self.log('Source channel "%s" with SID "%s" has not entry in epgdb, try next' % (src_channel,src_sidbyname) )
+							continue
+						else:
+							break
+
+				# if not sid then exit, go ahead with next src_channel
+				if len(src_sidbyname) == 0:
+					self.log('Source channel "%s" has not SID in lamedb, skip it' % src_channel)
+					continue
+
+			elif src_channel.count('-') == 2 :
+				tmp = src_channel.split('-')
+				src_sidbyname = "%s:xxxxxxxx:%s:%s:x:x" %(tmp[0].strip(' \n\r'),tmp[1].strip(' \n\r'),tmp[2].strip(' \n\r'))
+
+			else:
+				self.log("Channel source \"%s\" invalid" % src_channel)
+				continue
+
+			# convert "0e1f:00820000:0708:00c8:1:0" to sid,tsid,onid
+			# return the list [sid,tsid,onid]
+			src_sid = lamedb.convert_sid(src_sidbyname)
+			if len(src_sid) == 0 :
+				self.log("SID \"%s\" invalid, try next" % src_sidbyname)
+				continue
+
+			src_epgdb_channel = crossepg.epgdb_channels_get_by_freq(src_sid[2],src_sid[1],src_sid[0]);
+			if not src_epgdb_channel :
+				self.log('Source channel "%s" with SID "%s" has not entry in epgdb, skip it' % (src_channel,src_sidbyname) )
+				continue
+
+			self.log('Source channel "%s" with SID "%s" found in epgdb, using it' % (src_channel,src_sidbyname) )
+
+			for dst in dst_channels:
+				dst = dst.strip(' \n\r').lower()
+				dst_sidbyname = lamedb.get_sid_byname(dst)
+				if len(dst_sidbyname) == 0:
+					self.log('   dest. channel "%s" has not SID in lamedb, skip it' % dst)
+					continue
+
+				for dsid in dst_sidbyname:
+
+					# convert "0e1f:00820000:0708:00c8:1:0" to sid,tsid,onid
+					# return the list [sid,tsid,onid]
+					dst_sid = lamedb.convert_sid(dsid)
+
+					if dst_sid == src_sid:
+						# skip if source=destination
+						self.log('   dest. channel "%s" is eq. to source, skip it' % dst)
+						continue
+
+					num_events = 0
+					self.log('   copying EPG data from "%s" to "%s" sid "%s")' % (src_channel,dst,dsid) )
+					self.log2video("%s -> %s (%d/%d)" % (src_channel,dst,num_events,total_events))
+
+
+					# add channel into db
+					# doesn't matter if the channel already exist... epgdb do all the work
+					# this make a reference to the dest. channel
+					crossdb.add_channel(dst_sid)
+
+					title = src_epgdb_channel.title_first;
+
+					while (title != None) :
+						#print str(title.start_time)
+						#print str(title.length)
+						#print str(crossepg.epgdb_read_description(title))
+						#print str(crossepg.epgdb_read_long_description(title))
+						#print "-----------------------------------"
+
+						e_starttime = int(title.start_time)
+						e_length = int(title.length)
+						e_title = crossepg.epgdb_read_description(title).encode('utf-8')
+						e_summarie = crossepg.epgdb_read_long_description(title).encode('utf-8')
+						e_countrycode = "%c%c%c" % (title.iso_639_1, title.iso_639_2, title.iso_639_3)
+
+						# add_event(start_time , duration , title , summarie , ISO639_language_code , strings_encoded_with_UTF-8)
+						crossdb.add_event(e_starttime, e_length, e_title, e_summarie, e_countrycode, True )
+						num_events += 1
+						title = title.next
+
+						if (num_events % 25) == 0:
+							self.log2video("%s -> %s (%d/%d)" % (src_channel,dst,num_events,total_events))
+
+
+					total_events += num_events
+					self.log("   copied %d events" % num_events)
+
+		self.log2video("end: copied %d events" % (total_events))
+		# end process, close CrossEPG DB saving data
+		crossdb.close_db()
+		self.log("Copied %d events" % total_events)
+		self.log("--- END ---")
+
+
+
+# ****************************************************************************************************************************
+
+# MAIN CODE: SCRIPT START HERE
+
+SCRIPT_DIR = 'scripts/alias/'
+
+# get CrossEPG installation dir.
+crossepg_instroot = crossepg.epgdb_get_installroot()
+if crossepg_instroot == False:
+	sys.exit(1)
+scriptlocation = os.path.join(crossepg_instroot , SCRIPT_DIR)
+
+# get where CrossEPG save data (dbroot) and use it as script cache repository
+crossepg_dbroot = crossepg.epgdb_get_dbroot()
+if crossepg_dbroot == False:
+	sys.exit(1)
+
+# initialize script class
+script_class = main(scriptlocation , crossepg_dbroot)
+
+# copy epg
+script_class.do_epg_alias()
+
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/example_script.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/example_script.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/example_script.py	(revision 8762)
@@ -0,0 +1,128 @@
+#!/usr/bin/python
+# Author: Skaman
+# Date: October 2010
+
+from crossepg import *
+
+def dump_title(title):
+	log_add("----------EVENT----------")
+	log_add("ID: %d" % title.event_id)
+	log_add("MJD: %d" % title.mjd)
+	log_add("START TIME: %d" % title.start_time)
+	log_add("DURATION: %d" % title.length)
+	log_add("GENRE ID: %d" % title.genre_id)
+	log_add("REVISION: %d" % title.revision)
+	log_add("ISO639: %c%c%c" % (title.iso_639_1, title.iso_639_2, title.iso_639_3))
+	log_add("IS UTF8: %d" % IS_UTF8(title.flags))
+	log_add("DESCRIPTION_CRC: 0x%x" % title.description_crc)
+	log_add("DESCRIPTION_SEEK: %d" % title.description_seek)
+	log_add("DESCRIPTION LENTH: %d" % title.description_length)
+	log_add("DESCRIPTION: %s" % epgdb_read_description(title))
+	log_add("LONG DESCRIPTION CRC: 0x%x" % title.long_description_crc)
+	log_add("LONG DESCRIPTION SEEK: %d" % title.long_description_seek)
+	log_add("LONG DESCRIPTION LENTH: %d" % title.long_description_length)
+	log_add("LONG DESCRIPTION: %s" % epgdb_read_long_description(title))
+
+def main():
+	# get dbroot path
+	dbroot = epgdb_get_dbroot()
+
+	# open epgdb
+	if epgdb_open(dbroot):
+		log_add("EPGDB opened (root=%s)" % dbroot);
+	else:
+		log_add("Error opening EPGDB");
+		epgdb_close();
+		return
+
+	# load indexes and hashes in memory
+	epgdb_load();
+
+	####################
+	# WRITE OPERATIONS #
+	####################
+
+	# add an event into db
+	log_add("TEST: add an event into db")
+	nid = 0x01		# original network id
+	tsid = 0x01		# transport service id
+	sid = 0x01		# service id
+					# the 3 values above identify the channel
+
+	channel = epgdb_channels_add(nid, tsid, sid)	# add channel into db and get a reference to the structure
+													# doesn't matter if the channel already exist... epgdb do all the work
+
+	title = epgdb_title_alloc()							# alloc title structure in memory
+	title.event_id = 1									# event id.. it's unique inside a channel
+	title.start_time = 1293840000						# 1/1/2011 timestamp.. it's always referred to gmt+0 without daylight saving
+	title.mjd = epgdb_calculate_mjd(title.start_time)	# Modified Julian Date.. if you don't know it you can calulate it with epgdb_calculate_mjd()
+	title.length = 600									# ten minutes.. event duration in seconds
+	title.iso_639_1 = ord('e')							# ISO 639 language code.. http://en.wikipedia.org/wiki/ISO_639
+	title.iso_639_2 = ord('n')
+	title.iso_639_3 = ord('g')
+
+	title.flags = SET_UTF8(title.flags)		# necessary only if description and/or long description have utf-8 charset
+
+	title = epgdb_titles_add(channel, title)	# add event in epgdb and return back a reference to the structure
+												# remember to use always the new structure reference
+												# if the event already exist epgdb update it and automatically destroy the new structure
+
+	# now the event structure is already in epgdb
+	# but we still need to add descriptions
+	epgdb_titles_set_description (title, "our custom event short description");
+	epgdb_titles_set_long_description (title, "our custom event long description");
+
+	###################
+	# READ OPERATIONS #
+	###################
+
+	# walk inside channels and events
+	log_add("TEST: walk inside channels and events")
+	channel_count = 0
+	channel = epgdb_channels_get_first();
+	while channel != None:
+		log_add("---------CHANNEL---------")
+		log_add("NID: 0x%x" % channel.nid)
+		log_add("TSID: 0x%x" % channel.tsid)
+		log_add("SID: 0x%x" % channel.sid)
+		title_count = 0
+		title = channel.title_first;
+		while title != None:
+			dump_title(title)
+			title = title.next
+			title_count += 1
+			if title_count == 2:		# it's only a test so we halt the loop after 2 titles
+				break
+
+		channel = channel.next
+		channel_count += 1
+		if channel_count == 3:		# it's only a test so we halt the loop after 3 channels
+			break
+
+	# get a channel by nid, tsid, sid
+	log_add("TEST: get a channel by nid, tsid, sid")
+	channel = epgdb_channels_get_by_freq(nid, tsid, sid);
+	if channel:
+		# get an event by channel and timestamp
+		log_add("TEST: get an event by channel and timestamp")
+		title = epgdb_titles_get_by_time (channel, 1293840000); # exist also the api epgdb_titles_get_by_id_and_mjd(channel, event_id, mjd_time)
+		if title:
+			dump_title(title)
+		else:
+			log_add("Title not found")
+	else:
+		log_add("Channel not found")
+
+	# saving data
+	# it's necessary only if you add new events
+	if epgdb_save(None):
+		log_add("Data saved");
+	else:
+		log_add("Error saving data");
+
+	# close epgdb and clean memory
+	epgdb_close()
+	epgdb_clean()
+	log_add("EPGDB closed");
+
+main()
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/__init__.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/__init__.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/__init__.py	(revision 8762)
@@ -0,0 +1,2 @@
+# empty file
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/markupbase.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/markupbase.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/markupbase.py	(revision 8762)
@@ -0,0 +1,392 @@
+"""Shared support for scanning document type declarations in HTML and XHTML.
+
+This module is used as a foundation for the HTMLParser and sgmllib
+modules (indirectly, for htmllib as well).  It has no documented
+public API and should not be used directly.
+
+"""
+
+import re
+
+_declname_match = re.compile(r'[a-zA-Z][-_.a-zA-Z0-9]*\s*').match
+_declstringlit_match = re.compile(r'(\'[^\']*\'|"[^"]*")\s*').match
+_commentclose = re.compile(r'--\s*>')
+_markedsectionclose = re.compile(r']\s*]\s*>')
+
+# An analysis of the MS-Word extensions is available at
+# http://www.planetpublish.com/xmlarena/xap/Thursday/WordtoXML.pdf
+
+_msmarkedsectionclose = re.compile(r']\s*>')
+
+del re
+
+
+class ParserBase:
+    """Parser base class which provides some common support methods used
+    by the SGML/HTML and XHTML parsers."""
+
+    def __init__(self):
+        if self.__class__ is ParserBase:
+            raise RuntimeError(
+                "markupbase.ParserBase must be subclassed")
+
+    def error(self, message):
+        raise NotImplementedError(
+            "subclasses of ParserBase must override error()")
+
+    def reset(self):
+        self.lineno = 1
+        self.offset = 0
+
+    def getpos(self):
+        """Return current line number and offset."""
+        return self.lineno, self.offset
+
+    # Internal -- update line number and offset.  This should be
+    # called for each piece of data exactly once, in order -- in other
+    # words the concatenation of all the input strings to this
+    # function should be exactly the entire input.
+    def updatepos(self, i, j):
+        if i >= j:
+            return j
+        rawdata = self.rawdata
+        nlines = rawdata.count("\n", i, j)
+        if nlines:
+            self.lineno = self.lineno + nlines
+            pos = rawdata.rindex("\n", i, j) # Should not fail
+            self.offset = j-(pos+1)
+        else:
+            self.offset = self.offset + j-i
+        return j
+
+    _decl_otherchars = ''
+
+    # Internal -- parse declaration (for use by subclasses).
+    def parse_declaration(self, i):
+        # This is some sort of declaration; in "HTML as
+        # deployed," this should only be the document type
+        # declaration ("<!DOCTYPE html...>").
+        # ISO 8879:1986, however, has more complex
+        # declaration syntax for elements in <!...>, including:
+        # --comment--
+        # [marked section]
+        # name in the following list: ENTITY, DOCTYPE, ELEMENT,
+        # ATTLIST, NOTATION, SHORTREF, USEMAP,
+        # LINKTYPE, LINK, IDLINK, USELINK, SYSTEM
+        rawdata = self.rawdata
+        j = i + 2
+        assert rawdata[i:j] == "<!", "unexpected call to parse_declaration"
+        if rawdata[j:j+1] == ">":
+            # the empty comment <!>
+            return j + 1
+        if rawdata[j:j+1] in ("-", ""):
+            # Start of comment followed by buffer boundary,
+            # or just a buffer boundary.
+            return -1
+        # A simple, practical version could look like: ((name|stringlit) S*) + '>'
+        n = len(rawdata)
+        if rawdata[j:j+2] == '--': #comment
+            # Locate --.*-- as the body of the comment
+            return self.parse_comment(i)
+        elif rawdata[j] == '[': #marked section
+            # Locate [statusWord [...arbitrary SGML...]] as the body of the marked section
+            # Where statusWord is one of TEMP, CDATA, IGNORE, INCLUDE, RCDATA
+            # Note that this is extended by Microsoft Office "Save as Web" function
+            # to include [if...] and [endif].
+            return self.parse_marked_section(i)
+        else: #all other declaration elements
+            decltype, j = self._scan_name(j, i)
+        if j < 0:
+            return j
+        if decltype == "doctype":
+            self._decl_otherchars = ''
+        while j < n:
+            c = rawdata[j]
+            if c == ">":
+                # end of declaration syntax
+                data = rawdata[i+2:j]
+                if decltype == "doctype":
+                    self.handle_decl(data)
+                else:
+                    self.unknown_decl(data)
+                return j + 1
+            if c in "\"'":
+                m = _declstringlit_match(rawdata, j)
+                if not m:
+                    return -1 # incomplete
+                j = m.end()
+            elif c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ":
+                name, j = self._scan_name(j, i)
+            elif c in self._decl_otherchars:
+                j = j + 1
+            elif c == "[":
+                # this could be handled in a separate doctype parser
+                if decltype == "doctype":
+                    j = self._parse_doctype_subset(j + 1, i)
+                elif decltype in ("attlist", "linktype", "link", "element"):
+                    # must tolerate []'d groups in a content model in an element declaration
+                    # also in data attribute specifications of attlist declaration
+                    # also link type declaration subsets in linktype declarations
+                    # also link attribute specification lists in link declarations
+                    self.error("unsupported '[' char in %s declaration" % decltype)
+                else:
+                    self.error("unexpected '[' char in declaration")
+            else:
+                self.error(
+                    "unexpected %r char in declaration" % rawdata[j])
+            if j < 0:
+                return j
+        return -1 # incomplete
+
+    # Internal -- parse a marked section
+    # Override this to handle MS-word extension syntax <![if word]>content<![endif]>
+    def parse_marked_section(self, i, report=1):
+        rawdata= self.rawdata
+        assert rawdata[i:i+3] == '<![', "unexpected call to parse_marked_section()"
+        sectName, j = self._scan_name( i+3, i )
+        if j < 0:
+            return j
+        if sectName in ("temp", "cdata", "ignore", "include", "rcdata"):
+            # look for standard ]]> ending
+            match= _markedsectionclose.search(rawdata, i+3)
+        elif sectName in ("if", "else", "endif"):
+            # look for MS Office ]> ending
+            match= _msmarkedsectionclose.search(rawdata, i+3)
+        else:
+            self.error('unknown status keyword %r in marked section' % rawdata[i+3:j])
+        if not match:
+            return -1
+        if report:
+            j = match.start(0)
+            self.unknown_decl(rawdata[i+3: j])
+        return match.end(0)
+
+    # Internal -- parse comment, return length or -1 if not terminated
+    def parse_comment(self, i, report=1):
+        rawdata = self.rawdata
+        if rawdata[i:i+4] != '<!--':
+            self.error('unexpected call to parse_comment()')
+        match = _commentclose.search(rawdata, i+4)
+        if not match:
+            return -1
+        if report:
+            j = match.start(0)
+            self.handle_comment(rawdata[i+4: j])
+        return match.end(0)
+
+    # Internal -- scan past the internal subset in a <!DOCTYPE declaration,
+    # returning the index just past any whitespace following the trailing ']'.
+    def _parse_doctype_subset(self, i, declstartpos):
+        rawdata = self.rawdata
+        n = len(rawdata)
+        j = i
+        while j < n:
+            c = rawdata[j]
+            if c == "<":
+                s = rawdata[j:j+2]
+                if s == "<":
+                    # end of buffer; incomplete
+                    return -1
+                if s != "<!":
+                    self.updatepos(declstartpos, j + 1)
+                    self.error("unexpected char in internal subset (in %r)" % s)
+                if (j + 2) == n:
+                    # end of buffer; incomplete
+                    return -1
+                if (j + 4) > n:
+                    # end of buffer; incomplete
+                    return -1
+                if rawdata[j:j+4] == "<!--":
+                    j = self.parse_comment(j, report=0)
+                    if j < 0:
+                        return j
+                    continue
+                name, j = self._scan_name(j + 2, declstartpos)
+                if j == -1:
+                    return -1
+                if name not in ("attlist", "element", "entity", "notation"):
+                    self.updatepos(declstartpos, j + 2)
+                    self.error(
+                        "unknown declaration %r in internal subset" % name)
+                # handle the individual names
+                meth = getattr(self, "_parse_doctype_" + name)
+                j = meth(j, declstartpos)
+                if j < 0:
+                    return j
+            elif c == "%":
+                # parameter entity reference
+                if (j + 1) == n:
+                    # end of buffer; incomplete
+                    return -1
+                s, j = self._scan_name(j + 1, declstartpos)
+                if j < 0:
+                    return j
+                if rawdata[j] == ";":
+                    j = j + 1
+            elif c == "]":
+                j = j + 1
+                while j < n and rawdata[j].isspace():
+                    j = j + 1
+                if j < n:
+                    if rawdata[j] == ">":
+                        return j
+                    self.updatepos(declstartpos, j)
+                    self.error("unexpected char after internal subset")
+                else:
+                    return -1
+            elif c.isspace():
+                j = j + 1
+            else:
+                self.updatepos(declstartpos, j)
+                self.error("unexpected char %r in internal subset" % c)
+        # end of buffer reached
+        return -1
+
+    # Internal -- scan past <!ELEMENT declarations
+    def _parse_doctype_element(self, i, declstartpos):
+        name, j = self._scan_name(i, declstartpos)
+        if j == -1:
+            return -1
+        # style content model; just skip until '>'
+        rawdata = self.rawdata
+        if '>' in rawdata[j:]:
+            return rawdata.find(">", j) + 1
+        return -1
+
+    # Internal -- scan past <!ATTLIST declarations
+    def _parse_doctype_attlist(self, i, declstartpos):
+        rawdata = self.rawdata
+        name, j = self._scan_name(i, declstartpos)
+        c = rawdata[j:j+1]
+        if c == "":
+            return -1
+        if c == ">":
+            return j + 1
+        while 1:
+            # scan a series of attribute descriptions; simplified:
+            #   name type [value] [#constraint]
+            name, j = self._scan_name(j, declstartpos)
+            if j < 0:
+                return j
+            c = rawdata[j:j+1]
+            if c == "":
+                return -1
+            if c == "(":
+                # an enumerated type; look for ')'
+                if ")" in rawdata[j:]:
+                    j = rawdata.find(")", j) + 1
+                else:
+                    return -1
+                while rawdata[j:j+1].isspace():
+                    j = j + 1
+                if not rawdata[j:]:
+                    # end of buffer, incomplete
+                    return -1
+            else:
+                name, j = self._scan_name(j, declstartpos)
+            c = rawdata[j:j+1]
+            if not c:
+                return -1
+            if c in "'\"":
+                m = _declstringlit_match(rawdata, j)
+                if m:
+                    j = m.end()
+                else:
+                    return -1
+                c = rawdata[j:j+1]
+                if not c:
+                    return -1
+            if c == "#":
+                if rawdata[j:] == "#":
+                    # end of buffer
+                    return -1
+                name, j = self._scan_name(j + 1, declstartpos)
+                if j < 0:
+                    return j
+                c = rawdata[j:j+1]
+                if not c:
+                    return -1
+            if c == '>':
+                # all done
+                return j + 1
+
+    # Internal -- scan past <!NOTATION declarations
+    def _parse_doctype_notation(self, i, declstartpos):
+        name, j = self._scan_name(i, declstartpos)
+        if j < 0:
+            return j
+        rawdata = self.rawdata
+        while 1:
+            c = rawdata[j:j+1]
+            if not c:
+                # end of buffer; incomplete
+                return -1
+            if c == '>':
+                return j + 1
+            if c in "'\"":
+                m = _declstringlit_match(rawdata, j)
+                if not m:
+                    return -1
+                j = m.end()
+            else:
+                name, j = self._scan_name(j, declstartpos)
+                if j < 0:
+                    return j
+
+    # Internal -- scan past <!ENTITY declarations
+    def _parse_doctype_entity(self, i, declstartpos):
+        rawdata = self.rawdata
+        if rawdata[i:i+1] == "%":
+            j = i + 1
+            while 1:
+                c = rawdata[j:j+1]
+                if not c:
+                    return -1
+                if c.isspace():
+                    j = j + 1
+                else:
+                    break
+        else:
+            j = i
+        name, j = self._scan_name(j, declstartpos)
+        if j < 0:
+            return j
+        while 1:
+            c = self.rawdata[j:j+1]
+            if not c:
+                return -1
+            if c in "'\"":
+                m = _declstringlit_match(rawdata, j)
+                if m:
+                    j = m.end()
+                else:
+                    return -1    # incomplete
+            elif c == ">":
+                return j + 1
+            else:
+                name, j = self._scan_name(j, declstartpos)
+                if j < 0:
+                    return j
+
+    # Internal -- scan a name token and the new position and the token, or
+    # return -1 if we've reached the end of the buffer.
+    def _scan_name(self, i, declstartpos):
+        rawdata = self.rawdata
+        n = len(rawdata)
+        if i == n:
+            return None, -1
+        m = _declname_match(rawdata, i)
+        if m:
+            s = m.group()
+            name = s.strip()
+            if (i + len(s)) == n:
+                return None, -1  # end of buffer
+            return name.lower(), m.end()
+        else:
+            self.updatepos(declstartpos, i)
+            self.error("expected name token at %r"
+                       % rawdata[declstartpos:declstartpos+20])
+
+    # To be overridden -- handlers for unknown objects
+    def unknown_decl(self, data):
+        pass
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/scriptlib.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/scriptlib.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/scriptlib.py	(revision 8762)
@@ -0,0 +1,366 @@
+#!/usr/bin/python
+# scriptlib.py  by Ambrosa http://www.ambrosa.net
+# derived from E2_LOADEPG
+# 12-Jan-2011
+
+__author__ = "ambrosa http://www.ambrosa.net"
+__copyright__ = "Copyright (C) 2008-2011 Alessandro Ambrosini"
+__license__ = "CreativeCommons by-nc-sa http://creativecommons.org/licenses/by-nc-sa/3.0/"
+
+
+import os
+import sys
+import time
+import codecs
+import crossepg
+
+# escape some incorrect chars from filename
+def fn_escape(s):
+	if type(s).__name__ == 'str':
+		s = s.decode('utf-8')
+
+	s = s.replace(' ','_')
+	s = s.replace('/','_')
+	s = s.replace(':','_')
+	s = s.replace('.','_')
+	s = s.replace('|','_')
+	s = s.replace('!','_')
+
+	return(s.encode('utf-8'))
+
+# logging class
+class logging_class:
+
+	def __init__(self):
+		# get where CrossEPG save data (dbroot) and use it for opening crossepg.log
+		dbroot = crossepg.epgdb_get_dbroot()
+		if dbroot == True:
+			crossepg.log_open(dbroot)
+
+	def log(self,s):
+		crossepg.log_add(str(s))
+
+	def log2video_status(self,s):
+		print("LOGTEXT " + str(s))
+
+	def log2video_scriptname(self,s):
+		print("TYPE RUNNING CSCRIPT " + str(s))
+
+
+
+# decompress gzipped data
+class zlib_class:
+	GZTMP_FILE = "gunzip_temp.gz"
+	UNGZTMP_FILE = "gunzip_temp"
+	BIN_GZUNZIP = "gunzip -c " + GZTMP_FILE
+
+	def gzuncompress(self,data):
+		fd = open(self.GZTMP_FILE,'w')
+		fd.write(data)
+		fd.close()
+
+		fd = os.popen(self.BIN_GZUNZIP)
+		data_ungz = fd.read()
+		fd.close()
+		os.unlink(self.GZTMP_FILE)
+		return(data_ungz)
+
+
+# removing old cached epg files **
+def cleanup_oldcachedfiles(cachedir, field_separator):
+	TODAY = time.strftime("%Y%m%d")
+
+	for cachedfile in os.listdir(cachedir):
+		# extract date from filename
+		if cachedfile.split(field_separator)[-1] < TODAY :
+			os.unlink(os.path.join(cachedir,cachedfile))
+
+
+# return LOCALTIME - GMTIME (with DST)
+# return negative number if timezone is east of GMT (like Italy)
+# return postive number if timezone is west of GMT (like USA)
+def delta_utc():
+	if time.localtime().tm_isdst == 0 :
+		# return localtime - gmtime (in seconds)
+		return time.timezone
+	else:
+		# return (localtime - gmtime - DST)
+		return time.altzone
+
+
+# return DST time difference (in seconds)
+def delta_dst():
+	if time.localtime().tm_isdst == 0 :
+		return 0
+	else:
+		# return DST difference
+		return abs(time.altzone - time.timezone)
+
+
+# manage channel list from lamedb
+class lamedb_class:
+
+	LAMEDB='/etc/enigma2/lamedb'
+
+	# initialize an empty dictionary (Python array) indexed by channel name
+	# format: { channel_name : [ (sid , provider) , (sid , provider) , .... ] }
+	INDEXBYCHNAME = True
+	lamedb_dict = {}
+
+	# lamedb indexed by provider name
+	# format: { provider_name : [ (sid , channel_name) , (sid , channel_name) , .... ] }
+	INDEXBYPROVID = False # if True, also create the array lamedb_dict_prov, usually false for saving memory
+	lamedb_provid_dict = {}
+
+	def __init__(self, index_by_chname = True, index_by_provid = False):
+		self.INDEXBYCHNAME = index_by_chname
+		self.INDEXBYPROVID = index_by_provid
+		self.read_lamedb()
+
+	# first of all try to decode a string using UTF-8, if it fails then try with ISO-8859-1
+	# always return an Unicode string
+	def decode_charset(self,s):
+		u = None
+		charset_list = ('utf-8','iso-8859-1','iso-8859-2','iso-8859-15')
+
+		for charset in charset_list:
+			try:
+				u = unicode(s,charset,"strict")
+			except:
+				pass
+			else:
+				break
+
+		if u == None:
+			print("CHARSET ERROR while decoding lamedb")
+			sys.exit(1)
+		else:
+			return(u)
+
+
+	def read_lamedb(self):
+		if not os.path.exists(self.LAMEDB):
+			print("ERROR ! \'%s\' NOT FOUND" % self.LAMEDB)
+			sys.exit(1)
+
+		# lamedb mix UTF-8 + iso-8859-* inside it
+		# need charset decoding line by line
+		fd = open(self.LAMEDB,"r")
+
+		# skip transponder section
+		# read lamedb until are found "end" and "services" lines
+		while True:
+			temp = self.decode_charset(fd.readline())
+			if temp == '' :
+				print("ERROR parsing lamedb, transponder section: end of file")
+				sys.exit(1)
+
+			temp = temp.strip(' \n\r')
+			if temp == u"end":
+				# next line should be "services"
+				temp = self.decode_charset(fd.readline())
+				temp = temp.strip(' \n\r')
+				if temp == u'services':
+					# reached end of transponder section, end loop and continue with parsing channel section
+					break
+				else:
+					print("ERROR parsing lamedb, transponder section: not found \"end + services\" lines")
+					sys.exit(1)
+
+		# parsing lamedb channel section
+		while True:
+			sid = self.decode_charset(fd.readline()) # read SID , it's the first line
+
+			if sid == '' :
+				print("ERROR parsing lamedb, channel_name section: end of file")
+				sys.exit(1)
+
+			sid = sid.strip(' \n\r')
+
+			if sid == u'end':
+				# reached end of channel section, end loop
+				break;
+
+			channel_name = self.decode_charset(fd.readline()) # read channel name, this is the second line
+
+			channel_name = channel_name.strip(' \n\r').lower() # force channel name lowercase
+
+			temp = self.decode_charset(fd.readline()) # read provider , this is the third line
+			temp = temp.strip(' \n\r').lower()
+
+			temp_P = temp.find('p:')
+			if temp_P == -1 :
+				print("ERROR parsing lamedb, channel_name section: provider name \'p:\' not present")
+				sys.exit(1)
+			else:
+				temp = temp[(temp_P + 2):]
+				temp = temp.split(',')[0]
+				temp = temp.strip(' \n\r')
+				if temp == '':
+					provider_name = u'noprovider'
+				else:
+					provider_name = temp.lower()
+
+			#channel_name=channel_name.encode('utf-8')
+			#provider_name=provider_name.encode('utf-8')
+
+			if self.INDEXBYCHNAME == True:
+				sp = (sid,provider_name)
+				if channel_name != '':
+					if self.lamedb_dict.has_key(channel_name):
+						self.lamedb_dict[channel_name].append(sp)
+					else:
+						self.lamedb_dict[channel_name]=[sp]
+
+			if self.INDEXBYPROVID == True:
+				sp = (sid,channel_name)
+				if self.lamedb_provid_dict.has_key(provider_name):
+					self.lamedb_provid_dict[provider_name].append(sp)
+				else:
+					self.lamedb_provid_dict[provider_name]=[sp]
+
+				
+
+		fd.close()
+
+		if len(self.lamedb_dict) == 0 :
+			print("ERROR lamedb empty ?")
+			sys.exit(1)
+
+
+	def get_sid_byname(self,channel_name):
+		sid_list = []
+
+		if self.lamedb_dict.has_key(channel_name) :
+			for v in self.lamedb_dict[channel_name]:
+				# (sid,provider_name)
+				sid_list.append(v[0])
+
+		return(sid_list)
+
+
+	def get_provid_byname(self,channel_name):
+		provid_list = []
+
+		if self.lamedb_dict.has_key(channel_name) :
+			for v in self.lamedb_dict[channel_name]:
+				# (sid,provider_name)
+				provid_list.append(v[1])
+
+		return(provid_list)
+
+	def get_sidprovid_byname(self,channel_name):
+		sidprov_list = []
+		if self.lamedb_dict.has_key(channel_name) :
+			# (sid,provider_name)
+			sidprov_list = self.lamedb_dict[channel_name]
+
+		return(sidprov_list)
+
+
+	def get_chnames_byprov(self,provider_name):
+		if self.INDEXBYPROVID == True:
+			if self.lamedb_provid_dict.has_key(provider_name) :
+				return self.lamedb_provid_dict[provider_name]
+			else:
+				return None
+		return None
+
+	def convert_sid(self,sid):
+		s=[]
+
+		# SID:ns:TSID:ONID:stype:unused
+
+		try:
+			tmp = sid.split(":")
+			s.append(int(tmp[0],0x10))  # SID
+			s.append(int(tmp[2],0X10))  # TSID
+			s.append(int(tmp[3],0X10))  # ONID
+		except:
+			pass
+
+		return(s)
+
+
+class crossepg_db_class:
+
+	db_channel_ref = ''
+	event_id = 1
+
+	title_ref = ''
+
+	def __init__(self):
+		pass
+
+	def open_db(self):
+		# get where CrossEPG save data (dbroot)
+		dbroot = crossepg.epgdb_get_dbroot()
+		# open CrossEPG database
+		if not crossepg.epgdb_open(dbroot):
+			print("ERROR opening CrossEPG database")
+			sys.exit(1)
+
+		# load database structures (index, ....)
+		crossepg.epgdb_load()
+
+	def close_db(self):
+		# save data
+		if crossepg.epgdb_save(None):
+			print("CrossEPG data saved")
+		else:
+			print("CrossEPG Error saving data")
+
+		# close epgdb and clean memory
+		crossepg.epgdb_close()
+		crossepg.epgdb_clean()
+
+
+	# add channel into db and get a reference to the structure
+	# doesn't matter if the channel already exist... epgdb do all the work
+	def add_channel(self,ch_sid):
+		# epgdb_channels_add(onid, tsid, sid)
+		self.db_channel_ref = crossepg.epgdb_channels_add(ch_sid[2], ch_sid[1], ch_sid[0])
+		self.event_id = 1
+
+	# add an EPG event
+	def add_event(self, start_time, duration, title=' ', summarie=' ', language='eng', utf8=False):
+		start_time = int(start_time)
+		duration = int(duration)
+
+		if (duration < 0) or (duration > 65535) :
+			# duration must be >= 0 or < 65536 , skip this event (it's an error)
+			print("DEBUG: length error %d" % duration)
+			return
+
+		event_ref = crossepg.epgdb_title_alloc() # alloc title structure in memory		
+		event_ref.event_id = self.event_id  # event_id is unique inside a channel
+		self.event_id += 1
+
+		event_ref.start_time = start_time	# Unix timestamp, always referred to gmt+0 without daylight saving
+		event_ref.mjd = crossepg.epgdb_calculate_mjd(event_ref.start_time)	# Modified Julian Date. if you don't know it you can calulate it with epgdb_calculate_mjd()
+	
+		# print("       title %s , starttime %s , duration %f" % (title, start_time, duration))
+		event_ref.length = duration  # event duration in seconds
+
+		# ISO 639 language code. http://en.wikipedia.org/wiki/ISO_639
+		event_ref.iso_639_1 = ord(language[0:1])
+		event_ref.iso_639_2 = ord(language[1:2])
+		event_ref.iso_639_3 = ord(language[2:3])
+
+		# add event in epgdb and return back a reference to the structure
+		# remember to use always the new structure reference
+		# if the event already exist epgdb update it and automatically destroy the new structure
+		event_ref = crossepg.epgdb_titles_add(self.db_channel_ref, event_ref)
+
+
+		#print("DEBUG , title DATA TYPE: \'%s\'" % type(title).__name__ )
+		#print("DEBUG , summarie DATA TYPE: \'%s\'" % type(summarie).__name__ )
+
+		if utf8 == False :
+			crossepg.epgdb_titles_set_description(event_ref, title);
+			crossepg.epgdb_titles_set_long_description(event_ref, summarie);
+		else:
+			crossepg.epgdb_titles_set_description_utf8(event_ref, title);
+			crossepg.epgdb_titles_set_long_description_utf8(event_ref, summarie);
+
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/sgmllib.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/sgmllib.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/sgmllib.py	(revision 8762)
@@ -0,0 +1,548 @@
+"""A parser for SGML, using the derived class as a static DTD."""
+
+# XXX This only supports those SGML features used by HTML.
+
+# XXX There should be a way to distinguish between PCDATA (parsed
+# character data -- the normal case), RCDATA (replaceable character
+# data -- only char and entity references and end tags are special)
+# and CDATA (character data -- only end tags are special).  RCDATA is
+# not supported at all.
+
+
+import markupbase
+import re
+
+__all__ = ["SGMLParser", "SGMLParseError"]
+
+# Regular expressions used for parsing
+
+interesting = re.compile('[&<]')
+incomplete = re.compile('&([a-zA-Z][a-zA-Z0-9]*|#[0-9]*)?|'
+                           '<([a-zA-Z][^<>]*|'
+                              '/([a-zA-Z][^<>]*)?|'
+                              '![^<>]*)?')
+
+entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]')
+charref = re.compile('&#([0-9]+)[^0-9]')
+
+starttagopen = re.compile('<[>a-zA-Z]')
+shorttagopen = re.compile('<[a-zA-Z][-.a-zA-Z0-9]*/')
+shorttag = re.compile('<([a-zA-Z][-.a-zA-Z0-9]*)/([^/]*)/')
+piclose = re.compile('>')
+endbracket = re.compile('[<>]')
+tagfind = re.compile('[a-zA-Z][-_.a-zA-Z0-9]*')
+attrfind = re.compile(
+    r'\s*([a-zA-Z_][-:.a-zA-Z_0-9]*)(\s*=\s*'
+    r'(\'[^\']*\'|"[^"]*"|[][\-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~\'"@]*))?')
+
+
+class SGMLParseError(RuntimeError):
+    """Exception raised for all parse errors."""
+    pass
+
+
+# SGML parser base class -- find tags and call handler functions.
+# Usage: p = SGMLParser(); p.feed(data); ...; p.close().
+# The dtd is defined by deriving a class which defines methods
+# with special names to handle tags: start_foo and end_foo to handle
+# <foo> and </foo>, respectively, or do_foo to handle <foo> by itself.
+# (Tags are converted to lower case for this purpose.)  The data
+# between tags is passed to the parser by calling self.handle_data()
+# with some data as argument (the data may be split up in arbitrary
+# chunks).  Entity references are passed by calling
+# self.handle_entityref() with the entity reference as argument.
+
+class SGMLParser(markupbase.ParserBase):
+    # Definition of entities -- derived classes may override
+    entity_or_charref = re.compile('&(?:'
+      '([a-zA-Z][-.a-zA-Z0-9]*)|#([0-9]+)'
+      ')(;?)')
+
+    def __init__(self, verbose=0):
+        """Initialize and reset this instance."""
+        self.verbose = verbose
+        self.reset()
+
+    def reset(self):
+        """Reset this instance. Loses all unprocessed data."""
+        self.__starttag_text = None
+        self.rawdata = ''
+        self.stack = []
+        self.lasttag = '???'
+        self.nomoretags = 0
+        self.literal = 0
+        markupbase.ParserBase.reset(self)
+
+    def setnomoretags(self):
+        """Enter literal mode (CDATA) till EOF.
+
+        Intended for derived classes only.
+        """
+        self.nomoretags = self.literal = 1
+
+    def setliteral(self, *args):
+        """Enter literal mode (CDATA).
+
+        Intended for derived classes only.
+        """
+        self.literal = 1
+
+    def feed(self, data):
+        """Feed some data to the parser.
+
+        Call this as often as you want, with as little or as much text
+        as you want (may include '\n').  (This just saves the text,
+        all the processing is done by goahead().)
+        """
+
+        self.rawdata = self.rawdata + data
+        self.goahead(0)
+
+    def close(self):
+        """Handle the remaining data."""
+        self.goahead(1)
+
+    def error(self, message):
+        raise SGMLParseError(message)
+
+    # Internal -- handle data as far as reasonable.  May leave state
+    # and data to be processed by a subsequent call.  If 'end' is
+    # true, force handling all data as if followed by EOF marker.
+    def goahead(self, end):
+        rawdata = self.rawdata
+        i = 0
+        n = len(rawdata)
+        while i < n:
+            if self.nomoretags:
+                self.handle_data(rawdata[i:n])
+                i = n
+                break
+            match = interesting.search(rawdata, i)
+            if match: j = match.start()
+            else: j = n
+            if i < j:
+                self.handle_data(rawdata[i:j])
+            i = j
+            if i == n: break
+            if rawdata[i] == '<':
+                if starttagopen.match(rawdata, i):
+                    if self.literal:
+                        self.handle_data(rawdata[i])
+                        i = i+1
+                        continue
+                    k = self.parse_starttag(i)
+                    if k < 0: break
+                    i = k
+                    continue
+                if rawdata.startswith("</", i):
+                    k = self.parse_endtag(i)
+                    if k < 0: break
+                    i = k
+                    self.literal = 0
+                    continue
+                if self.literal:
+                    if n > (i + 1):
+                        self.handle_data("<")
+                        i = i+1
+                    else:
+                        # incomplete
+                        break
+                    continue
+                if rawdata.startswith("<!--", i):
+                        # Strictly speaking, a comment is --.*--
+                        # within a declaration tag <!...>.
+                        # This should be removed,
+                        # and comments handled only in parse_declaration.
+                    k = self.parse_comment(i)
+                    if k < 0: break
+                    i = k
+                    continue
+                if rawdata.startswith("<?", i):
+                    k = self.parse_pi(i)
+                    if k < 0: break
+                    i = i+k
+                    continue
+                if rawdata.startswith("<!", i):
+                    # This is some sort of declaration; in "HTML as
+                    # deployed," this should only be the document type
+                    # declaration ("<!DOCTYPE html...>").
+                    k = self.parse_declaration(i)
+                    if k < 0: break
+                    i = k
+                    continue
+            elif rawdata[i] == '&':
+                if self.literal:
+                    self.handle_data(rawdata[i])
+                    i = i+1
+                    continue
+                match = charref.match(rawdata, i)
+                if match:
+                    name = match.group(1)
+                    self.handle_charref(name)
+                    i = match.end(0)
+                    if rawdata[i-1] != ';': i = i-1
+                    continue
+                match = entityref.match(rawdata, i)
+                if match:
+                    name = match.group(1)
+                    self.handle_entityref(name)
+                    i = match.end(0)
+                    if rawdata[i-1] != ';': i = i-1
+                    continue
+            else:
+                self.error('neither < nor & ??')
+            # We get here only if incomplete matches but
+            # nothing else
+            match = incomplete.match(rawdata, i)
+            if not match:
+                self.handle_data(rawdata[i])
+                i = i+1
+                continue
+            j = match.end(0)
+            if j == n:
+                break # Really incomplete
+            self.handle_data(rawdata[i:j])
+            i = j
+        # end while
+        if end and i < n:
+            self.handle_data(rawdata[i:n])
+            i = n
+        self.rawdata = rawdata[i:]
+        # XXX if end: check for empty stack
+
+    # Extensions for the DOCTYPE scanner:
+    _decl_otherchars = '='
+
+    # Internal -- parse processing instr, return length or -1 if not terminated
+    def parse_pi(self, i):
+        rawdata = self.rawdata
+        if rawdata[i:i+2] != '<?':
+            self.error('unexpected call to parse_pi()')
+        match = piclose.search(rawdata, i+2)
+        if not match:
+            return -1
+        j = match.start(0)
+        self.handle_pi(rawdata[i+2: j])
+        j = match.end(0)
+        return j-i
+
+    def get_starttag_text(self):
+        return self.__starttag_text
+
+    # Internal -- handle starttag, return length or -1 if not terminated
+    def parse_starttag(self, i):
+        self.__starttag_text = None
+        start_pos = i
+        rawdata = self.rawdata
+        if shorttagopen.match(rawdata, i):
+            # SGML shorthand: <tag/data/ == <tag>data</tag>
+            # XXX Can data contain &... (entity or char refs)?
+            # XXX Can data contain < or > (tag characters)?
+            # XXX Can there be whitespace before the first /?
+            match = shorttag.match(rawdata, i)
+            if not match:
+                return -1
+            tag, data = match.group(1, 2)
+            self.__starttag_text = '<%s/' % tag
+            tag = tag.lower()
+            k = match.end(0)
+            self.finish_shorttag(tag, data)
+            self.__starttag_text = rawdata[start_pos:match.end(1) + 1]
+            return k
+        # XXX The following should skip matching quotes (' or ")
+        # As a shortcut way to exit, this isn't so bad, but shouldn't
+        # be used to locate the actual end of the start tag since the
+        # < or > characters may be embedded in an attribute value.
+        match = endbracket.search(rawdata, i+1)
+        if not match:
+            return -1
+        j = match.start(0)
+        # Now parse the data between i+1 and j into a tag and attrs
+        attrs = []
+        if rawdata[i:i+2] == '<>':
+            # SGML shorthand: <> == <last open tag seen>
+            k = j
+            tag = self.lasttag
+        else:
+            match = tagfind.match(rawdata, i+1)
+            if not match:
+                self.error('unexpected call to parse_starttag')
+            k = match.end(0)
+            tag = rawdata[i+1:k].lower()
+            self.lasttag = tag
+        while k < j:
+            match = attrfind.match(rawdata, k)
+            if not match: break
+            attrname, rest, attrvalue = match.group(1, 2, 3)
+            if not rest:
+                attrvalue = attrname
+            else:
+                if (attrvalue[:1] == "'" == attrvalue[-1:] or
+                    attrvalue[:1] == '"' == attrvalue[-1:]):
+                    # strip quotes
+                    attrvalue = attrvalue[1:-1]
+                attrvalue = self.entity_or_charref.sub(
+                    self._convert_ref, attrvalue)
+            attrs.append((attrname.lower(), attrvalue))
+            k = match.end(0)
+        if rawdata[j] == '>':
+            j = j+1
+        self.__starttag_text = rawdata[start_pos:j]
+        self.finish_starttag(tag, attrs)
+        return j
+
+    # Internal -- convert entity or character reference
+    def _convert_ref(self, match):
+        if match.group(2):
+            return self.convert_charref(match.group(2)) or \
+                '&#%s%s' % match.groups()[1:]
+        elif match.group(3):
+            return self.convert_entityref(match.group(1)) or \
+                '&%s;' % match.group(1)
+        else:
+            return '&%s' % match.group(1)
+
+    # Internal -- parse endtag
+    def parse_endtag(self, i):
+        rawdata = self.rawdata
+        match = endbracket.search(rawdata, i+1)
+        if not match:
+            return -1
+        j = match.start(0)
+        tag = rawdata[i+2:j].strip().lower()
+        if rawdata[j] == '>':
+            j = j+1
+        self.finish_endtag(tag)
+        return j
+
+    # Internal -- finish parsing of <tag/data/ (same as <tag>data</tag>)
+    def finish_shorttag(self, tag, data):
+        self.finish_starttag(tag, [])
+        self.handle_data(data)
+        self.finish_endtag(tag)
+
+    # Internal -- finish processing of start tag
+    # Return -1 for unknown tag, 0 for open-only tag, 1 for balanced tag
+    def finish_starttag(self, tag, attrs):
+        try:
+            method = getattr(self, 'start_' + tag)
+        except AttributeError:
+            try:
+                method = getattr(self, 'do_' + tag)
+            except AttributeError:
+                self.unknown_starttag(tag, attrs)
+                return -1
+            else:
+                self.handle_starttag(tag, method, attrs)
+                return 0
+        else:
+            self.stack.append(tag)
+            self.handle_starttag(tag, method, attrs)
+            return 1
+
+    # Internal -- finish processing of end tag
+    def finish_endtag(self, tag):
+        if not tag:
+            found = len(self.stack) - 1
+            if found < 0:
+                self.unknown_endtag(tag)
+                return
+        else:
+            if tag not in self.stack:
+                try:
+                    method = getattr(self, 'end_' + tag)
+                except AttributeError:
+                    self.unknown_endtag(tag)
+                else:
+                    self.report_unbalanced(tag)
+                return
+            found = len(self.stack)
+            for i in range(found):
+                if self.stack[i] == tag: found = i
+        while len(self.stack) > found:
+            tag = self.stack[-1]
+            try:
+                method = getattr(self, 'end_' + tag)
+            except AttributeError:
+                method = None
+            if method:
+                self.handle_endtag(tag, method)
+            else:
+                self.unknown_endtag(tag)
+            del self.stack[-1]
+
+    # Overridable -- handle start tag
+    def handle_starttag(self, tag, method, attrs):
+        method(attrs)
+
+    # Overridable -- handle end tag
+    def handle_endtag(self, tag, method):
+        method()
+
+    # Example -- report an unbalanced </...> tag.
+    def report_unbalanced(self, tag):
+        if self.verbose:
+            print '*** Unbalanced </' + tag + '>'
+            print '*** Stack:', self.stack
+
+    def convert_charref(self, name):
+        """Convert character reference, may be overridden."""
+        try:
+            n = int(name)
+        except ValueError:
+            return
+        if not 0 <= n <= 255:
+            return
+        return self.convert_codepoint(n)
+
+    def convert_codepoint(self, codepoint):
+        return chr(codepoint)
+
+    def handle_charref(self, name):
+        """Handle character reference, no need to override."""
+        replacement = self.convert_charref(name)
+        if replacement is None:
+            self.unknown_charref(name)
+        else:
+            self.handle_data(replacement)
+
+    # Definition of entities -- derived classes may override
+    entitydefs = \
+            {'lt': '<', 'gt': '>', 'amp': '&', 'quot': '"', 'apos': '\''}
+
+    def convert_entityref(self, name):
+        """Convert entity references.
+
+        As an alternative to overriding this method; one can tailor the
+        results by setting up the self.entitydefs mapping appropriately.
+        """
+        table = self.entitydefs
+        if name in table:
+            return table[name]
+        else:
+            return
+
+    def handle_entityref(self, name):
+        """Handle entity references, no need to override."""
+        replacement = self.convert_entityref(name)
+        if replacement is None:
+            self.unknown_entityref(name)
+        else:
+            self.handle_data(self.convert_entityref(name))
+
+    # Example -- handle data, should be overridden
+    def handle_data(self, data):
+        pass
+
+    # Example -- handle comment, could be overridden
+    def handle_comment(self, data):
+        pass
+
+    # Example -- handle declaration, could be overridden
+    def handle_decl(self, decl):
+        pass
+
+    # Example -- handle processing instruction, could be overridden
+    def handle_pi(self, data):
+        pass
+
+    # To be overridden -- handlers for unknown objects
+    def unknown_starttag(self, tag, attrs): pass
+    def unknown_endtag(self, tag): pass
+    def unknown_charref(self, ref): pass
+    def unknown_entityref(self, ref): pass
+
+
+class TestSGMLParser(SGMLParser):
+
+    def __init__(self, verbose=0):
+        self.testdata = ""
+        SGMLParser.__init__(self, verbose)
+
+    def handle_data(self, data):
+        self.testdata = self.testdata + data
+        if len(repr(self.testdata)) >= 70:
+            self.flush()
+
+    def flush(self):
+        data = self.testdata
+        if data:
+            self.testdata = ""
+            print 'data:', repr(data)
+
+    def handle_comment(self, data):
+        self.flush()
+        r = repr(data)
+        if len(r) > 68:
+            r = r[:32] + '...' + r[-32:]
+        print 'comment:', r
+
+    def unknown_starttag(self, tag, attrs):
+        self.flush()
+        if not attrs:
+            print 'start tag: <' + tag + '>'
+        else:
+            print 'start tag: <' + tag,
+            for name, value in attrs:
+                print name + '=' + '"' + value + '"',
+            print '>'
+
+    def unknown_endtag(self, tag):
+        self.flush()
+        print 'end tag: </' + tag + '>'
+
+    def unknown_entityref(self, ref):
+        self.flush()
+        print '*** unknown entity ref: &' + ref + ';'
+
+    def unknown_charref(self, ref):
+        self.flush()
+        print '*** unknown char ref: &#' + ref + ';'
+
+    def unknown_decl(self, data):
+        self.flush()
+        print '*** unknown decl: [' + data + ']'
+
+    def close(self):
+        SGMLParser.close(self)
+        self.flush()
+
+
+def test(args = None):
+    import sys
+
+    if args is None:
+        args = sys.argv[1:]
+
+    if args and args[0] == '-s':
+        args = args[1:]
+        klass = SGMLParser
+    else:
+        klass = TestSGMLParser
+
+    if args:
+        file = args[0]
+    else:
+        file = 'test.html'
+
+    if file == '-':
+        f = sys.stdin
+    else:
+        try:
+            f = open(file, 'r')
+        except IOError, msg:
+            print file, ":", msg
+            sys.exit(1)
+
+    data = f.read()
+    if f is not sys.stdin:
+        f.close()
+
+    x = klass()
+    for c in data:
+        x.feed(c)
+    x.close()
+
+
+if __name__ == '__main__':
+    test()
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/webif.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/webif.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/lib/webif.py	(revision 8762)
@@ -0,0 +1,126 @@
+#!/usr/bin/python
+
+# webif.py  by Ambrosa http://www.ambrosa.net
+# this module is used for manage Web Interface
+# not tested with CrossEPG
+
+__author__ = "ambrosa http://www.ambrosa.net"
+__version__ = "0.53 beta E2_LOADEPG"
+__copyright__ = "Copyright (C) 2008-2009 Alessandro Ambrosini"
+__license__ = "CreativeCommons by-nc-sa http://creativecommons.org/licenses/by-nc-sa/3.0/"
+
+import time
+import string
+import urllib2
+from urllib import quote_plus
+from xml.dom import minidom
+
+
+class webif_class:
+    USE_WEBIF=1
+    USE_WEBIF_AUTH=0
+    WEBIF_AUTH_USER='root'
+    WEBIF_AUTH_PASSW='qboxhd'
+    WEBIF_AUTH_REALM='dm7025'
+    WEBIF_IP='127.0.0.1'
+    
+    def __init__(self,use,auth,auth_name,auth_passw,auth_realm,ip):
+        self.USE_WEBIF=use
+        self.USE_WEBIF_AUTH=auth
+        self.WEBIF_AUTH_USER=auth_name
+        self.WEBIF_AUTH_PASSW=auth_passw
+        self.WEBIF_AUTH_REALM=auth_realm
+        self.WEBIF_IP=ip
+
+
+    def get_use_webif(self):
+        return(self.USE_WEBIF)
+        
+        
+    # WebInterface routines
+    # see http://dream.reichholf.net/wiki/Enigma2:WebInterface    
+    def WI(self,command):   
+        
+        if self.USE_WEBIF_AUTH == 1 :    
+            auth_handler = urllib2.HTTPBasicAuthHandler()
+            auth_handler.add_password(self.WEBIF_AUTH_REALM, 'http://' + self.WEBIF_IP, self.WEBIF_AUTH_USER, self.WEBIF_AUTH_PASSW)
+            opener = urllib2.build_opener(auth_handler)
+            urllib2.install_opener(opener)
+            
+        try:
+            sock=urllib2.urlopen('http://' + self.WEBIF_IP + '/web/' + command)
+            data=sock.read()
+        except urllib2.URLError:
+            pass
+        except urllib2.HTTPError:
+            pass
+        except urllib2.httplib.BadStatusLine:
+            pass
+        else:
+            sock.close()
+            return(data)
+            
+    def standby(self):
+        current_sid=self.currentchannelsid()
+        if current_sid != None:
+            self.WI('powerstate?newstate=0')
+            time.sleep(5)
+        
+    def restartenigma(self):
+        self.WI('powerstate?newstate=3')
+        
+    def switchon(self):
+        current_sid=self.currentchannelsid()
+        if current_sid == None:
+            # DM appears switched off. Switch it on !
+        
+            # switch on emulating remote keypress
+            # 'powerstate?newstate=116' is not (?) working
+            #self.WI('remotecontrol?command=116')       
+            self.WI('powerstate?newstate=0')
+
+            time.sleep(5)
+            current_sid=self.currentchannelsid()
+        
+        return(current_sid)
+
+
+    def zap(self,channelsid):
+        self.WI('zap?sRef='+channelsid)
+
+    def reloadepgdat(self):
+        self.WI('powerstate?newstate=10')
+
+    def currentchannelsid(self):
+        # DM must be SWITCHED ON
+        # if DM is in standby mode, it return 'none'
+        data=self.WI('subservices')
+        
+        if data == None :
+            return(None)
+            
+        try:
+            xmldoc = minidom.parseString(data)
+        except:
+            return(None)
+        
+        r=xmldoc.getElementsByTagName('e2servicereference')[0].firstChild.data
+        if r == 'N/A':
+            return(None)
+            
+        return(r)
+
+    def is_recording(self):
+        data=self.WI("timerlist")
+        if data.find("<e2state>2</e2state>") == -1:
+            return(False) # not recording
+        else:
+            return(True) # recording
+
+    def message(self,txt,timeout=10,type=1):
+        is_on=self.currentchannelsid()
+        # WARNING: if DM is switched off, sending a message cause a lock/crash in the system
+        if is_on != None:
+            self.WI("message?text="+quote_plus("E2_LOADEPG - "+txt)+"&type="+str(type)+"&timeout="+str(timeout))
+        
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/mediaprem/example-mediaprem-minidom.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/mediaprem/example-mediaprem-minidom.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/mediaprem/example-mediaprem-minidom.py	(revision 8762)
@@ -0,0 +1,557 @@
+#!/usr/bin/python
+# mediaprem.py  by Ambrosa http://www.ambrosa.net
+# this module is used for download EPG data from Mediaset website
+# derived from E2_LOADEPG
+
+__author__ = "ambrosa http://www.ambrosa.net"
+__copyright__ = "Copyright (C) 2008-2011 Alessandro Ambrosini"
+__license__ = "CreativeCommons by-nc-sa http://creativecommons.org/licenses/by-nc-sa/3.0/"
+
+import gc
+import os
+import sys
+import time
+import codecs
+import socket
+import urllib
+import urllib2
+import ConfigParser
+from xml.dom import minidom
+
+# import CrossEPG functions
+import crossepg
+
+# location of local python modules under "scripts/lib" dir.
+# add it to sys.path()
+crossepg_instroot = crossepg.epgdb_get_installroot()
+if crossepg_instroot == False:
+	sys.exit(1)
+libdir = os.path.join(crossepg_instroot , 'scripts/lib')
+sys.path.append(libdir)
+
+# import local modules
+import sgmllib
+import scriptlib
+
+# =================================================================
+# HTML PARSER
+
+
+class Description_parser(sgmllib.SGMLParser):
+	def parse(self, s):
+		self.feed(s)
+		self.close()
+
+	def __init__(self, verbose=0):
+		sgmllib.SGMLParser.__init__(self, verbose)
+		self.start_div_box = False
+		self.start_div_boxtxt = False
+		self.description = ''
+
+
+	def start_div(self, attributes):
+		for name, value in attributes:
+			if name == "class":
+				if value == "box_Text":
+					self.start_div_box = True
+				elif value == "txtBox_cms":
+					self.start_div_boxtxt = True
+
+	def end_div(self):
+		if self.start_div_boxtxt == True:
+			self.start_div_box = False
+			self.start_div_boxtxt = False
+
+
+	def handle_data(self, data):
+		if self.start_div_boxtxt == True:
+			self.description += data.decode('iso-8859-1')
+
+	def get_descr(self):
+		return (self.description.strip(' \n\r') )
+
+# =================================================================
+
+
+class main:
+
+	# main config file
+	CONF_CONFIGFILENAME = "mediaprem.conf"
+
+	# Network socket timeout (in seconds)
+	CONF_SOCKET_TIMEOUT = 20
+
+	# log text
+	CONF_LOG_SCRIPT_NAME = "MediasetPremium (Italy)"
+	CONF_LOG_PREFIX = ""
+
+	# max chars in description
+	CONF_DLDESCMAXCHAR = 250
+
+	# retry number if HTTP error
+	HTTP_ERROR_RETRY = 3
+	# seconds to wait between retries
+	HTTP_ERROR_WAIT_RETRY = 5
+
+	# charset used in remote website epg data
+	REMOTE_EPG_CHARSET = 'utf-8'
+
+	TODAYMP = ''
+	DAYCACHEMP = []
+	FIELD_SEPARATOR = '###'
+	CHANNELLIST = {}
+
+
+	def log(self,s,video=0):
+		self.logging.log(self.CONF_LOG_PREFIX + str(s))
+		if video == 1:
+			self.log2video(str(s))
+
+	def log2video(self,s):
+		self.logging.log2video_status(str(s))
+
+	def convert_daymp(self,dmp):
+		daystandard = time.strftime("%Y%m%d",time.strptime(dmp,"%Y/%m/%d"))
+		return daystandard
+
+
+	def get_description(self,url):
+
+		if url[:7] != 'http://':
+			return('')
+
+		if (url[-5:] != '.html') and (url[-4:] != '.htm') :
+			return('')
+
+		self.log("   downloading description \'" + url + "\'")
+		url = str(urllib.quote(url,safe=":/"))
+
+		try:
+			sock = urllib2.urlopen(url)
+			data = sock.read()
+		except IOError, e:
+			serr = "unknown"
+			if hasattr(e, 'reason'):
+				serr = str(e.reason)
+			elif hasattr(e, 'code'):
+				serr = str(e.code)
+				if hasattr(e, 'msg'):
+					serr += " , " + str(e.msg)
+
+			self.log(url + "      error, reason: " + serr + ". Skip it.")
+			return('')
+
+		else:
+			sock.close()
+			dsparser = Description_parser()
+			dsparser.parse(data)
+			return(dsparser.get_descr())
+
+		return('')
+
+
+
+	def __init__(self,confdir,dbroot):
+
+		# initialize logging
+		self.logging = scriptlib.logging_class()
+		# write to video OSD the script name
+		self.logging.log2video_scriptname(self.CONF_LOG_SCRIPT_NAME)
+
+
+		# check swap memory available
+		osp = os.popen('free | awk \'/Swap/ { print $2 }\'','r')
+		ret = osp.readlines()
+		if len(ret) > 0:
+			try:
+				m = int(ret[0])/1024
+			except:
+				self.log("Error get SWAP value, abort",1)
+				time.sleep(10)
+				sys.exit(1)
+
+			if m < 60:
+				self.log("SWAP Not Enabled (<60MB), abort",1)
+				time.sleep(10)
+				sys.exit(1)
+		else:
+			self.log("Error get SWAP value, abort",1)
+			time.sleep(10)
+			sys.exit(1)
+
+		osp.close()
+
+
+		CONF_FILE = os.path.join(confdir,self.CONF_CONFIGFILENAME)
+		if not os.path.exists(CONF_FILE) :
+			self.log("ERROR: %s not present" % CONF_FILE,1)
+			sys.exit(1)
+
+		config = ConfigParser.ConfigParser()
+		#config.optionxform = str  # needed to return case sensitive index
+		config.read(CONF_FILE)
+
+		# reading [global] section options
+		self.CONF_DEFAULT_PROVIDER = config.get("global","DEFAULT_PROVIDER")
+		# save cache under dbroot
+		self.CONF_CACHEDIR = os.path.join(dbroot,config.get("global","CACHE_DIRNAME"))
+
+		self.CONF_DL_DESC = config.getint("global","DL_DESC")
+		self.CONF_MAX_DAY_EPG = config.getint("global","MAX_DAY_EPG")
+		self.CONF_URL = config.get("global","URL")
+
+		self.CONF_GMT_ZONE = config.get("global","GMT_ZONE")
+		if self.CONF_GMT_ZONE.strip(' ').lower() == 'equal':
+			#self.DELTA_UTC = -scriptlib.delta_utc() # return negative if timezone is east of GMT (like Italy), invert sign
+			self.DELTA_UTC = 0
+		else:
+			self.DELTA_UTC = float(self.CONF_GMT_ZONE)*3600.0
+			if self.DELTA_UTC >= 0:
+				self.DELTA_UTC = self.DELTA_UTC + scriptlib.delta_dst()
+			else:
+				self.DELTA_UTC = self.DELTA_UTC - scriptlib.delta_dst()
+
+		self.DELTA_UTC = int(self.DELTA_UTC)
+		#self.log("Website timezone - UTC = %d seconds" % self.DELTA_UTC)
+
+		if not os.path.exists(self.CONF_CACHEDIR):
+			self.log("Creating \'%s\' directory for caching" % self.CONF_CACHEDIR)
+			os.mkdir(self.CONF_CACHEDIR)
+
+		# reading [channels] section
+		temp = config.items("channels");
+
+		# create a dictionary (Python array) with index = channel ID
+		for i in temp:
+			self.CHANNELLIST[i[0].strip(' \n\r').lower()] = unicode(i[1].strip(' \n\r').lower(),'utf-8')
+
+		if len(self.CHANNELLIST) == 0 :
+			self.log("ERROR: [channels] section empty ?",1)
+			sys.exit(1)
+
+		# set network socket timeout
+		socket.setdefaulttimeout(self.CONF_SOCKET_TIMEOUT)
+
+		self.TODAYMP = time.strftime("%Y/%m/%d")
+		# create a list filled with dates (format AAAA/MM/DD) from today to today+ MAX_DAY_EPG
+		self.DAYCACHEMP=[self.TODAYMP]
+		for day in range(1,self.CONF_MAX_DAY_EPG):
+			self.DAYCACHEMP.append(time.strftime("%Y/%m/%d",time.localtime(time.time()+86400*day)))
+
+
+
+# ----------------------------------------------------------------------
+
+
+	def download_and_cache(self):
+		self.log("--- START DOWNLOAD AND CACHE DATA ---")
+		self.log2video("STARTING DOWNLOAD")
+
+		self.log("Removing old cached files")
+		scriptlib.cleanup_oldcachedfiles(self.CONF_CACHEDIR, self.FIELD_SEPARATOR)
+
+		chlist = self.CHANNELLIST
+
+		self.log("Start download XML data from \'" + self.CONF_URL+"\'")
+		self.log2video("downloading XML data ...")
+
+		i = self.HTTP_ERROR_RETRY
+		while i > 0:
+			try:
+				sock = urllib2.urlopen(self.CONF_URL)
+				data = sock.read()
+			except IOError, e:
+				serr = "unknown"
+				if hasattr(e, 'reason'):
+					serr = str(e.reason)
+				elif hasattr(e, 'code'):
+					serr = str(e.code)
+				if hasattr(e, 'msg'):
+					serr += " , " + str(e.msg)
+
+				self.log("\'" + self.CONF_URL + "\' connection error. Reason: "+serr+". Waiting "+str(self.HTTP_ERROR_WAIT_RETRY)+" sec. and retry ["+str(i)+"] ...")
+				time.sleep(self.HTTP_ERROR_WAIT_RETRY) # add sleep
+				i -= 1
+
+			else:
+				i = -99
+				sock.close()
+
+		if (i != -99):
+			self.log("Cannot retrieve data from \'" + self.CONF_URL + "\'. Abort script")
+			self.log2video("Error: cannot download XML data, abort")
+			time.sleep(5)
+			sys.exit(1)
+
+		self.log("End download XML data, now processing XML code.")
+		self.log2video("preprocessing XML data, wait ...")
+		try:
+			xmldoc = minidom.parseString(data)
+		except:
+			self.log("Warning ! Data are not in a valid XML format. Abort script")
+			self.log2video("Error: no valid XML data, abort")
+			time.sleep(5)
+			sys.exit(1)
+
+
+		self.log("End process XML data")
+		self.log2video("end process XML data")
+
+		# days list
+		xmlref_giorno = xmldoc.getElementsByTagName('giorno')
+		for xml_gg in xmlref_giorno:
+			gg = xml_gg.attributes["data"].value
+			if gg not in self.DAYCACHEMP :
+				continue
+
+			xmlref_canale = xml_gg.getElementsByTagName('canale')
+			for xml_ch in xmlref_canale:
+				chid = xml_ch.attributes["id"].value.strip(' \n\r').lower()
+				if not chlist.has_key(chid) :
+						self.log("Warning: new channel \"id=%s name=%s\" found in XML data" % (xml_ch.attributes["id"].value,xml_ch.attributes["description"]))
+						continue
+
+				clist = [chid]
+				if self.CHANNELLIST.has_key(chid + '+1'):
+					clist.append(chid + '+1')
+
+				for c in clist:
+
+					# get cache option
+					#  0 : don't download/cache
+					#  1 : download and cache (optional 1,new_name )
+					#  2 : always download overwriting existing files (optional 2,new_name )
+					#  3 : always download overwriting existing files only for TODAY (optional 3,new_name )
+
+					cacheopt = int(chlist[c].split(",")[0])
+
+					# if cacheopt == 0, do nothing
+					if cacheopt == 0:
+						continue
+
+					channel_name = ''
+					if len(chlist[c].split(",")) > 1 :
+						if chlist[c].split(",")[1] != '' :
+							# channel renamed, new name provided by user
+							channel_name = chlist[c].split(",")[1].strip(' \n\r').lower()
+
+					# if channel name is not present as option, quit with error
+					if channel_name == '':
+						self.log("ERROR ! ID=%s channel name not present" % c)
+						sys.exit(1)
+
+					channel_provider = self.CONF_DEFAULT_PROVIDER
+					if len(chlist[c].split(",")) > 2 :
+						if chlist[c].split(",")[2] != '' :
+							channel_provider = chlist[c].split(",")[2].strip(' \n\r').lower()
+
+					# if channel name is not present as option in channel_list.conf , quit with error
+					if channel_name == '':
+						self.log("ERROR ! ID=" + str(c) + " channel name not present. Skip !")
+						continue
+
+					# download only if file doesn't exist or cacheopt == 2 (always download),
+					# using open(...,"w") files will be overwritten (saving a delete + create)
+
+					day = str(self.convert_daymp(gg))
+					eventfilename = scriptlib.fn_escape(str(c) + self.FIELD_SEPARATOR + channel_name + self.FIELD_SEPARATOR + day)
+					eventfilepath = os.path.join(self.CONF_CACHEDIR, eventfilename)
+					if (cacheopt == 1) and os.path.exists(eventfilepath):
+						continue
+					if (cacheopt == 3) and os.path.exists(eventfilepath) and (gg != self.TODAYMP):
+						continue
+					if (cacheopt != 1) and (cacheopt != 2) and (cacheopt != 3):
+						self.log("Warning: unknown cache option " + str(cacheopt))
+						exit_for_loop = True
+						continue
+
+					num_events = 0
+					self.log("  Writing in cache \'" + eventfilename + "\'",2)
+					self.log2video(" extracting \"%s\" [%d] (%s)" % (channel_name, num_events, day))
+
+					fd=codecs.open(eventfilepath,"w",'utf-8')
+
+					fd.write(str(c) + self.FIELD_SEPARATOR + channel_name + self.FIELD_SEPARATOR + channel_provider + self.FIELD_SEPARATOR + day + '\n')
+					fd.write("Local Time (human readeable)###Unix GMT Time###Event Title###Event Description\n")
+
+					xmlref_events = xml_ch.getElementsByTagName('prg')
+					for xml_ee in xmlref_events:
+						orainiz = xml_ee.attributes["orainizio"].value
+
+						if (orainiz >='00:00') and (orainiz <= '05:59') :
+							nextdayevent = 86400
+						else:
+							nextdayevent = 0
+
+						event_starttime = gg + " " + orainiz
+
+						if c == (chid + '+1'):
+							# manage channel "+1"
+							event_startime_unix_gmt = str(int(time.mktime(time.strptime(event_starttime,"%Y/%m/%d %H:%M"))) - self.DELTA_UTC + 3600 + nextdayevent)
+						else:
+							# normal channel, not "+1"
+							event_startime_unix_gmt = str(int(time.mktime(time.strptime(event_starttime,"%Y/%m/%d %H:%M"))) - self.DELTA_UTC + nextdayevent)
+
+
+						event_title = unicode(xml_ee.getElementsByTagName('titolo')[0].firstChild.data)
+						event_title = event_title.replace('\r','')
+						event_title = event_title.replace('\n','')
+						event_title = event_title.strip(u' ')
+
+						event_description = ''
+						if self.CONF_DL_DESC == 1 :
+							url_desc = xml_ee.getElementsByTagName('linkScheda')[0].firstChild.data
+							event_description = unicode(self.get_description(url_desc.strip(' \n\r'))[:self.CONF_DLDESCMAXCHAR])
+							event_description = event_description.replace('\r','')
+							event_description = event_description.replace('\n',u' ')
+							event_description = event_description.strip(u' ')
+
+						fd.write(event_starttime + self.FIELD_SEPARATOR + event_startime_unix_gmt + self.FIELD_SEPARATOR + event_title + self.FIELD_SEPARATOR + event_description + '\n')
+						num_events += 1
+						self.log2video(" extracting \"%s\" [%d] (%s)" % (channel_name, num_events, day))
+
+
+					fd.close()
+
+		del xmldoc
+
+# ----------------------------------------------------------------------
+
+
+	def process_cache(self):
+		self.log("--- START PROCESSING CACHE ---")
+		self.log2video("START PROCESSING CACHE")
+		if not os.path.exists(self.CONF_CACHEDIR):
+			self.log("ERROR: %s not present" % self.CONF_CACHEDIR,1)
+			sys.exit(1)
+
+		self.log("Loading lamedb")
+		lamedb = scriptlib.lamedb_class()
+
+		self.log("Initialize CrossEPG database")
+		crossdb = scriptlib.crossepg_db_class()
+		crossdb.open_db()
+
+		events = []
+		previous_id = ''
+		channels_name = ''
+		total_events = 0
+
+		self.log("Start data processing")
+		filelist = sorted(os.listdir(self.CONF_CACHEDIR))
+		filelist.append('***END***')
+
+		for f in filelist :
+			id = f.split(self.FIELD_SEPARATOR)[0]
+			if previous_id == '':
+				previous_id = id
+
+			if id != previous_id :
+				total_events += len(events)
+				self.log("  ...processing \'%s\' , nr. events %d" % (previous_id,len(events)))
+				self.log2video("processed %d events ..." % total_events )
+
+				for c in channels_name:
+					# a channel can have zero or more SID (different channel with same name)
+					# return the list [0e1f:00820000:0708:00c8:1:0 , 1d20:00820000:2fa8:013e:1:0 , ..... ]
+					# return [] if channel name is not in lamedb
+					sidbyname = lamedb.get_sid_byname(c.strip(' \n').lower())
+
+					# process every SID
+					for s in sidbyname:
+						# convert "0e1f:00820000:0708:00c8:1:0" to sid,tsid,onid
+						# return the list [sid,tsid,onid]
+						ch_sid = lamedb.convert_sid(s)
+						if len(ch_sid) == 0:
+							continue
+
+						# add channel into db
+						# doesn't matter if the channel already exist... epgdb do all the work
+						crossdb.add_channel(ch_sid)
+
+						i = 0
+						L = len(events) - 1
+
+						# process events
+						for e in events:
+
+							items = e.split(self.FIELD_SEPARATOR)
+							e_starttime = int(items[1])
+
+							if i < L :
+								e_length = int(events[i+1].split(self.FIELD_SEPARATOR)[1]) - e_starttime
+							else:
+								# last event, dummy length 90 min.
+								e_length = 5400
+							i += 1
+
+							# extract title and encode Python Unicode with UTF-8
+							e_title = items[2].encode('utf-8')
+
+							# extract summarie and encode Python Unicode with UTF-8
+							e_summarie = items[3].encode('utf-8')
+
+							# add_event(start_time , duration , title , summarie , ISO639_language_code , strings_encoded_with_UTF-8)
+							crossdb.add_event(e_starttime, e_length, e_title, e_summarie, 'ita', True )
+
+				if f == '***END***':
+					break
+
+				events = []
+				previous_id = id
+				channels_name = ''
+
+			if id == previous_id:
+				self.log("Reading  \'%s\'" % f)
+				# read events from cache file using UTF-8 and insert them in events list
+				fd = codecs.open(os.path.join(self.CONF_CACHEDIR, f),"r","utf-8")
+				lines = fd.readlines()
+				fd.close()
+				if channels_name == '':
+					# first line has channel data (id,name,provider,date)
+					channels_name = lines[0].split(self.FIELD_SEPARATOR)[1].split('|')
+				# the second line is only a remark
+				# add events starting from third line
+				events.extend(lines[2:])
+
+		# end process, close CrossEPG DB saving data
+		crossdb.close_db()
+		self.log("TOTAL EPG EVENTS PROCESSED: %d" % total_events)
+		self.log("--- END ---")
+		self.log2video("END , events processed: %d" % total_events)
+
+
+
+# ****************************************************************************************************************************
+
+# MAIN CODE: SCRIPT START HERE
+
+# increase this process niceness (other processes have higher priority)
+os.nice(10)
+
+# set Garbage Collector to do a "generational jump" more frequently than default 700
+# memory saving: about 50% (!!), some performance loss (obviously)
+gc.set_threshold(50,10,10)
+
+SCRIPT_DIR = 'scripts/mediaprem/'
+
+# get CrossEPG installation dir.
+crossepg_instroot = crossepg.epgdb_get_installroot()
+if crossepg_instroot == False:
+	sys.exit(1)
+scriptlocation = os.path.join(crossepg_instroot , SCRIPT_DIR)
+
+# get where CrossEPG save data (dbroot) and use it as script cache repository
+crossepg_dbroot = crossepg.epgdb_get_dbroot()
+if crossepg_dbroot == False:
+	sys.exit(1)
+
+# initialize script class
+script_class = main(scriptlocation , crossepg_dbroot)
+
+# download data and cache them
+script_class.download_and_cache()
+
+# read cached data and inject into CrossEPG database
+script_class.process_cache()
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/mediaprem/mediaprem.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/mediaprem/mediaprem.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/mediaprem/mediaprem.conf	(revision 8762)
@@ -0,0 +1,124 @@
+# mediaprem.conf by ambrosa http://www.ambrosa.net
+# configuration file
+# 
+
+# ==================================================================================================
+# GLOBAL configuration section
+[global]
+
+# default provider used for searching channel name in lamedb
+DEFAULT_PROVIDER=mediaset
+
+# download event description (slow ! for every event it needs to download and parse e a web page)
+# DL_DESC=1 download description
+# DL_DESC=0 don't download description
+# default DL_DESC=1
+DL_DESC=1
+
+# cache dir name
+# default CACHE_DIRNAME=script_mediaprem_cache
+CACHE_DIRNAME=script_mediaprem_cache
+
+# GMT zone used in remote website (NOT in receiver)
+# positive if east GMT (like Italy) , i.e. GMT_ZONE=1
+# negative if west GMT (like USA) , i.e. GMT_ZONE=-6
+# 'equal' if receiver time is equal to remote website (same timezone)
+# default GMT_ZONE=equal
+GMT_ZONE=equal
+
+# number of days in the future for downloading EPG
+# MAX_DAY_EPG=1 means "download only today"
+# MAX_DAY_EPG=2 means "download today and tomorrow"
+# ....
+# default MAX_DAY_EPG=7
+MAX_DAY_EPG=7
+
+# MEDIASET EPG HTML repository
+# default URL=http://www.mediasetpremium.mediaset.it/export/palinsesto.xml
+URL=http://www.mediasetpremium.mediaset.it/export/palinsesto.xml
+
+
+# ==================================================================================================
+# CHANNEL configuration section
+[channels]
+
+#
+# YOU must configure every channel ID
+#
+# id=0                       EPG will not be downloaded
+# id=1,LAMEDB_channel_name   EPG will be downloaded and cached
+# id=2,LAMEDB_channel_name   EPG will be downloaded every time
+# id=3,LAMEDB_channel_name   EPG will be downloaded and cached (like '1') but only TODAY will be forced downloading (like '2')
+#
+# Examples:
+# KE=0                  channel id 'KE' (Premium Cinema) EPG will NOT be dowloaded
+# KE=1,PremiumCinema    'KE' EPG will be dowloaded and cached and it's name in lamedb is 'PremiumCinema'
+# KE=2,Premium Cinema   'KE' EPG will be dowloaded every time and it's name in lamedb is 'Premium Cinema'
+#
+# note 1: channel name is case insensitive
+# note 2: you can add many channel name using '|' character as separator (epg will be copied for all these channels)
+#          i.e.  KE=1,PremiumCinema|Premium Cinema|CinemaPremium
+#
+
+# Premium Cinema , id=KE
+KE=1,Premium Cinema
+
+# Premium Cinema Emotion , id=KO
+KO=1,Premium Emotion
+
+# Premium Cinema Energy , id=KG
+KG=1,Premium Energy
+
+# Premium Extra , id=K8
+K8=1,Premium Extra 1
+
+# Premium Extra 2 , id=K9
+K9=1,Premium Extra 2
+
+# Studio Universal , id=KR
+KR=1,Studio Universal - Premium
+
+# Joi , id=KJ
+KJ=1,Joi - Premium
+
+# Mya , id=KD
+KD=1,Mya - Premium
+
+# Steel , id=KS
+KS=1,Steel - Premium
+
+# Disney , id=DY
+DY=0,Disney Channel - Premium
+
+# Playhouse , id=KP
+KP=0,Playhouse Disney - Premium
+
+# Cartoon Network , id=KN
+KN=0,Cartoon Network - Premium
+
+# Hiro , id=KU
+KU=0,Hiro - Premium
+
+# Premium Calcio , id=KC
+KC=0,Premium Calcio
+
+# Premium Calcio 1 , id=K1
+K1=0,Premium Calcio 1
+
+# Premium Calcio 2 , id=K2
+K2=0,Premium Calcio 2
+
+# Premium Calcio 3 , id=K3
+K3=0,Premium Calcio 3
+
+# Premium Calcio 4 , id=K4
+K4=0,Premium Calcio 4
+
+# Premium Calcio 5 , id=K5
+K5=0,Premium Calcio 5
+
+# Premium Calcio 6 , id=K6
+K6=0,Premium Calcio 6
+
+
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/mediaprem/mediaprem.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/mediaprem/mediaprem.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/mediaprem/mediaprem.py	(revision 8762)
@@ -0,0 +1,593 @@
+#!/usr/bin/python
+# mediaprem.py  by Ambrosa http://www.ambrosa.net
+# this module is used for download EPG data from Mediaset website
+# derived from E2_LOADEPG
+
+__author__ = "ambrosa http://www.ambrosa.net"
+__copyright__ = "Copyright (C) 2008-2011 Alessandro Ambrosini"
+__license__ = "CreativeCommons by-nc-sa http://creativecommons.org/licenses/by-nc-sa/3.0/"
+
+import gc
+import os
+import sys
+import time
+import codecs
+import socket
+import urllib
+import urllib2
+import ConfigParser
+#from xml.dom import minidom
+
+# import CrossEPG functions
+import crossepg
+
+# location of local python modules under "scripts/lib" dir.
+# add it to sys.path()
+crossepg_instroot = crossepg.epgdb_get_installroot()
+if crossepg_instroot == False:
+	sys.exit(1)
+libdir = os.path.join(crossepg_instroot , 'scripts/lib')
+sys.path.append(libdir)
+
+# import local modules
+import sgmllib
+import scriptlib
+
+# =================================================================
+# HTML PARSER used for parsing description
+
+
+class Description_parser(sgmllib.SGMLParser):
+	def parse(self, s):
+		self.feed(s)
+		self.close()
+
+	def __init__(self, verbose=0):
+		sgmllib.SGMLParser.__init__(self, verbose)
+		self.start_div_box = False
+		self.start_div_boxtxt = False
+		self.description = ''
+
+
+	def start_div(self, attributes):
+		for name, value in attributes:
+			if name == "class":
+				if value == "box_Text":
+					self.start_div_box = True
+				elif value == "txtBox_cms":
+					self.start_div_boxtxt = True
+
+	def end_div(self):
+		if self.start_div_boxtxt == True:
+			self.start_div_box = False
+			self.start_div_boxtxt = False
+
+
+	def handle_data(self, data):
+		if self.start_div_boxtxt == True:
+			self.description += data.decode('iso-8859-1')
+
+	def get_descr(self):
+		return (self.description.strip(' \n\r') )
+
+
+
+# =================================================================
+
+
+class main(sgmllib.SGMLParser):
+
+	# main config file
+	CONF_CONFIGFILENAME = "mediaprem.conf"
+
+	# Network socket timeout (in seconds)
+	CONF_SOCKET_TIMEOUT = 20
+
+	# log text
+	CONF_LOG_SCRIPT_NAME = "MediasetPremium (Italy)"
+	CONF_LOG_PREFIX = ""
+
+	# max chars in description
+	CONF_DLDESCMAXCHAR = 250
+
+	# retry number if HTTP error
+	HTTP_ERROR_RETRY = 3
+	# seconds to wait between retries
+	HTTP_ERROR_WAIT_RETRY = 5
+
+	# charset used in remote website epg data
+	REMOTE_EPG_CHARSET = 'utf-8'
+
+	TODAYMP = ''
+	DAYCACHEMP = []
+	FIELD_SEPARATOR = '###'
+	CHANNELLIST = {}
+
+	DESCRIPTIONS_WEBCACHE = {}
+
+
+# -------- xml processing using SGMLLIB -----------
+# best way is use xml.minidom but it's very memory hungry (about 40MB memory for 2 MB XML file)
+# sgmllib can simple parse xml data
+	SGML_PALINSESTO_INSIDE = False
+	SGML_TITOLO_INSIDE = False
+	SGML_LINKSCHEDA_INSIDE = False
+
+	SGML_GIORNOMP = None
+	SGML_CHID = None
+	SGML_FD = None
+	SGML_TOTAL_EVENTS = 0
+
+	SGML_EVENT_STARTHOUR = None
+	SGML_EVENT_TITLE = None
+	SGML_EVENT_SUMMARIE = None
+
+	def parse(self, s):
+			self.feed(s)
+			self.close()
+
+	def start_palinsesto(self, attr):
+		self.SGML_PALINSESTO_INSIDE = True
+
+	def end_palinsesto(self):
+		self.SGML_PALINSESTO_INSIDE = False
+		self.SGML_GIORNOMP = None
+		self.log("extracted %d events" % self.SGML_TOTAL_EVENTS)
+
+	def start_giorno(self,attr):
+		if self.SGML_PALINSESTO_INSIDE == True :
+			self.SGML_GIORNOMP = None
+			for name,value in attr:
+				if name == "data":
+					if str(value).strip(' \n\r') in self.DAYCACHEMP :
+						self.SGML_GIORNOMP = str(value).strip(' \n\r')
+					break
+
+	def end_giorno(self):
+		self.SGML_GIORNOMP = None
+
+	def start_canale(self,attr):
+		if self.SGML_GIORNOMP != None:
+			for name,value in attr:
+				if name == "id":
+					self.SGML_CHID = str(value).strip(' \n\r').lower()
+
+					if not self.CHANNELLIST.has_key(self.SGML_CHID) :
+							self.log("Warning: new channel id=%s found in XML data" % self.SGML_CHID )
+							break
+
+					# get cache option
+					#  0 : don't download/cache
+					#  1 : download and cache (optional 1,new_name )
+					#  2 : always download overwriting existing files (optional 2,new_name )
+					#  3 : always download overwriting existing files only for TODAY (optional 3,new_name )
+
+					cacheopt = int(self.CHANNELLIST[self.SGML_CHID].split(",")[0])
+
+					# if cacheopt == 0, do nothing
+					if cacheopt == 0:
+						break
+
+					channel_name = ''
+					if len(self.CHANNELLIST[self.SGML_CHID].split(",")) > 1 :
+						if self.CHANNELLIST[self.SGML_CHID].split(",")[1] != '' :
+							# channel renamed, new name provided by user
+							channel_name = self.CHANNELLIST[self.SGML_CHID].split(",")[1].strip(' \n\r').lower()
+
+					# if channel name is not present as option, quit with error
+					if channel_name == '':
+						self.log("ERROR ! ID=%s channel name not present" % self.SGML_CHID)
+						sys.exit(1)
+
+					channel_provider = self.CONF_DEFAULT_PROVIDER
+					if len(self.CHANNELLIST[self.SGML_CHID].split(",")) > 2 :
+						if self.CHANNELLIST[self.SGML_CHID].split(",")[2] != '' :
+							channel_provider = self.CHANNELLIST[self.SGML_CHID].split(",")[2].strip(' \n\r').lower()
+
+					# if channel name is not present as option in channel_list.conf , quit with error
+					if channel_name == '':
+						self.log("ERROR ! ID=" + self.SGML_CHID + " channel name not present. Skip !")
+						break
+
+					day = str(self.convert_daymp(self.SGML_GIORNOMP))
+					eventfilename = scriptlib.fn_escape(self.SGML_CHID + self.FIELD_SEPARATOR + channel_name + self.FIELD_SEPARATOR + day)
+					eventfilepath = os.path.join(self.CONF_CACHEDIR, eventfilename)
+					if (cacheopt == 1) and os.path.exists(eventfilepath):
+						break
+					if (cacheopt == 3) and os.path.exists(eventfilepath) and (self.SGML_GIORNOMP != self.TODAYMP):
+						break
+					if (cacheopt != 1) and (cacheopt != 2) and (cacheopt != 3):
+						self.log("Warning: unknown cache option " + str(cacheopt))
+						break
+
+					self.log("  Writing in cache \'" + eventfilename + "\'",2)
+					self.log2video(" extracting \"%s\" (%s)" % (channel_name, day))
+
+					self.SGML_FD = codecs.open(eventfilepath,"w",'utf-8')
+
+					self.SGML_FD.write(self.SGML_CHID + self.FIELD_SEPARATOR + channel_name + self.FIELD_SEPARATOR + channel_provider + self.FIELD_SEPARATOR + day + '\n')
+					self.SGML_FD.write("Local Time (human readeable)###Unix GMT Time###Event Title###Event Description\n")
+
+					break
+
+	def end_canale(self):
+		if self.SGML_FD != None:
+			self.SGML_FD.close()
+		self.SGML_FD = None
+		self.SGML_CHID = None
+
+	def start_prg(self,attr):
+		if self.SGML_FD != None :
+			self.SGML_EVENT_STARTHOUR = None
+			for name,value in attr:
+				if name == "orainizio":
+					self.SGML_EVENT_STARTHOUR = str(value).strip(' \n\r')
+					break
+
+	def end_prg(self):
+		if self.SGML_FD != None :
+
+			if (self.SGML_EVENT_STARTHOUR >='00:00') and (self.SGML_EVENT_STARTHOUR <= '05:59') :
+				nextdayevent = 86400
+			else:
+				nextdayevent = 0
+
+			event_starttime = self.SGML_GIORNOMP + '_' + self.SGML_EVENT_STARTHOUR
+			event_startime_unix_gmt = str(int(time.mktime(time.strptime(event_starttime,"%Y/%m/%d_%H:%M"))) - self.DELTA_UTC + nextdayevent)
+
+			event_title = unicode(self.SGML_EVENT_TITLE)
+			event_title = event_title.replace('\r','')
+			event_title = event_title.replace('\n','')
+			event_title = event_title.strip(u' ')
+
+			event_description = ''
+			if self.CONF_DL_DESC == 1 :
+				event_description = unicode(self.get_description(self.SGML_EVENT_SUMMARIE_LINK.strip(' \n\r'), self.CONF_DLDESCMAXCHAR) )
+				event_description = event_description.replace('\r','')
+				event_description = event_description.replace('\n',u' ')
+				event_description = event_description.strip(u' ')
+
+			self.SGML_FD.write(event_starttime + self.FIELD_SEPARATOR + event_startime_unix_gmt + self.FIELD_SEPARATOR + event_title + self.FIELD_SEPARATOR + event_description + '\n')
+			self.SGML_TOTAL_EVENTS += 1
+
+	def start_titolo(self,attr):
+		if self.SGML_FD != None:
+			self.SGML_TITOLO_INSIDE = True
+
+	def end_titolo(self):
+		if self.SGML_FD != None:
+			self.SGML_TITOLO_INSIDE = False
+
+	def start_linkscheda(self,attr):
+		if self.SGML_FD != None:
+			self.SGML_LINKSCHEDA_INSIDE = True
+
+	def end_linkscheda(self):
+		if self.SGML_FD != None:
+			self.SGML_LINKSCHEDA_INSIDE = False
+
+
+	def handle_data(self, data):
+		if self.SGML_TITOLO_INSIDE == True:
+			self.SGML_EVENT_TITLE = data.encode('utf-8')
+			self.SGML_EVENT_TITLE = self.SGML_EVENT_TITLE.strip(' \n\r')
+
+		if self.SGML_LINKSCHEDA_INSIDE == True:
+			self.SGML_EVENT_SUMMARIE_LINK = data.encode('utf-8')
+			self.SGML_EVENT_SUMMARIE_LINK = self.SGML_EVENT_SUMMARIE_LINK.strip(' \n\r')
+
+
+# -----------------------------------------------
+
+	def log(self,s,video=0):
+		self.logging.log(self.CONF_LOG_PREFIX + str(s))
+		if video == 1:
+			self.log2video(str(s))
+
+	def log2video(self,s):
+		self.logging.log2video_status(str(s))
+
+	def convert_daymp(self,dmp):
+		daystandard = time.strftime("%Y%m%d",time.strptime(dmp,"%Y/%m/%d"))
+		return daystandard
+
+
+	def get_description(self,url,maxchar=128):
+
+		if url[:7] != 'http://':
+			return('')
+
+		if (url[-5:] != '.html') and (url[-4:] != '.htm') :
+			return('')
+
+		url_hash = hash(url)
+		if self.DESCRIPTIONS_WEBCACHE.has_key(url_hash):
+			self.log("   cached description " + url)
+			return(self.DESCRIPTIONS_WEBCACHE[url_hash])
+
+		self.log("   downloading description " + url )
+		url_enc = str(urllib.quote(url,safe=":/"))
+		try:
+			sock = urllib2.urlopen(url_enc)
+			data = sock.read()
+		except IOError, e:
+			serr = "unknown"
+			if hasattr(e, 'reason'):
+				serr = str(e.reason)
+			elif hasattr(e, 'code'):
+				serr = str(e.code)
+				if hasattr(e, 'msg'):
+					serr += " , " + str(e.msg)
+
+			self.log("      error, reason: " + serr + ". Skip it.")
+			return('')
+
+		else:
+			sock.close()
+			dsparser = Description_parser()
+			dsparser.parse(data)
+			self.DESCRIPTIONS_WEBCACHE[url_hash] = dsparser.get_descr()[:maxchar]
+			return(self.DESCRIPTIONS_WEBCACHE[url_hash])
+
+		return('')
+
+
+
+	def __init__(self, confdir, dbroot):
+
+		# initialize SGMLLIB
+		sgmllib.SGMLParser.__init__(self, 0)
+
+		# initialize logging
+		self.logging = scriptlib.logging_class()
+		# write to video OSD the script name
+		self.logging.log2video_scriptname(self.CONF_LOG_SCRIPT_NAME)
+
+		CONF_FILE = os.path.join(confdir,self.CONF_CONFIGFILENAME)
+		if not os.path.exists(CONF_FILE) :
+			self.log("ERROR: %s not present" % CONF_FILE,1)
+			sys.exit(1)
+
+		config = ConfigParser.ConfigParser()
+		#config.optionxform = str  # needed to return case sensitive index
+		config.read(CONF_FILE)
+
+		# reading [global] section options
+		self.CONF_DEFAULT_PROVIDER = config.get("global","DEFAULT_PROVIDER")
+		# save cache under dbroot
+		self.CONF_CACHEDIR = os.path.join(dbroot,config.get("global","CACHE_DIRNAME"))
+
+		self.CONF_DL_DESC = config.getint("global","DL_DESC")
+		self.CONF_MAX_DAY_EPG = config.getint("global","MAX_DAY_EPG")
+		self.CONF_URL = config.get("global","URL")
+
+		self.CONF_GMT_ZONE = config.get("global","GMT_ZONE")
+		if self.CONF_GMT_ZONE.strip(' ').lower() == 'equal':
+			#self.DELTA_UTC = -scriptlib.delta_utc() # return negative if timezone is east of GMT (like Italy), invert sign
+			self.DELTA_UTC = 0
+		else:
+			self.DELTA_UTC = float(self.CONF_GMT_ZONE)*3600.0
+			if self.DELTA_UTC >= 0:
+				self.DELTA_UTC = self.DELTA_UTC + scriptlib.delta_dst()
+			else:
+				self.DELTA_UTC = self.DELTA_UTC - scriptlib.delta_dst()
+
+		self.DELTA_UTC = int(self.DELTA_UTC)
+		#self.log("Website timezone - UTC = %d seconds" % self.DELTA_UTC)
+
+		if not os.path.exists(self.CONF_CACHEDIR):
+			self.log("Creating \'%s\' directory for caching" % self.CONF_CACHEDIR)
+			os.mkdir(self.CONF_CACHEDIR)
+
+		# reading [channels] section
+		temp = config.items("channels");
+
+		# create a dictionary (Python array) with index = channel ID
+		for i in temp:
+			self.CHANNELLIST[i[0].strip(' \n\r').lower()] = unicode(i[1].strip(' \n\r').lower(),'utf-8')
+
+		if len(self.CHANNELLIST) == 0 :
+			self.log("ERROR: [channels] section empty ?",1)
+			sys.exit(1)
+
+		# set network socket timeout
+		socket.setdefaulttimeout(self.CONF_SOCKET_TIMEOUT)
+
+		self.TODAYMP = time.strftime("%Y/%m/%d")
+		# create a list filled with dates (format AAAA/MM/DD) from today to today+ MAX_DAY_EPG
+		self.DAYCACHEMP=[]
+		for day in range(0,self.CONF_MAX_DAY_EPG):
+			self.DAYCACHEMP.append(time.strftime("%Y/%m/%d",time.localtime(time.time()+86400*day)))
+
+
+
+# ----------------------------------------------------------------------
+
+
+	def download_and_cache(self):
+		self.log("--- START DOWNLOAD AND CACHE DATA ---")
+		self.log2video("STARTING DOWNLOAD")
+
+		self.log("Removing old cached files")
+		scriptlib.cleanup_oldcachedfiles(self.CONF_CACHEDIR, self.FIELD_SEPARATOR)
+
+
+		self.log("Start download XML data from \'" + self.CONF_URL+"\'")
+		self.log2video("downloading XML data ...")
+
+		i = self.HTTP_ERROR_RETRY
+		while i > 0:
+			try:
+				sock = urllib2.urlopen(self.CONF_URL)
+				data = sock.read()
+			except IOError, e:
+				serr = "unknown"
+				if hasattr(e, 'reason'):
+					serr = str(e.reason)
+				elif hasattr(e, 'code'):
+					serr = str(e.code)
+				if hasattr(e, 'msg'):
+					serr += " , " + str(e.msg)
+
+				self.log("\'" + self.CONF_URL + "\' connection error. Reason: "+serr+". Waiting "+str(self.HTTP_ERROR_WAIT_RETRY)+" sec. and retry ["+str(i)+"] ...")
+				time.sleep(self.HTTP_ERROR_WAIT_RETRY) # add sleep
+				i -= 1
+
+			else:
+				i = -99
+				sock.close()
+
+		if (i != -99):
+			self.log("Cannot retrieve data from \'" + self.CONF_URL + "\'. Abort script")
+			self.log2video("Error: cannot download XML data, abort")
+			time.sleep(5)
+			sys.exit(1)
+
+		self.log("end download XML data, now processing")
+		self.log2video("processing XML data, wait ...")
+
+		# start SGMLLIB parsing
+		self.parse(data)
+
+		self.log("end process XML data",1)
+
+# ----------------------------------------------------------------------
+
+
+	def process_cache(self):
+		self.log("--- START PROCESSING CACHE ---")
+		self.log2video("START PROCESSING CACHE")
+		if not os.path.exists(self.CONF_CACHEDIR):
+			self.log("ERROR: %s not present" % self.CONF_CACHEDIR,1)
+			sys.exit(1)
+
+		self.log("Loading lamedb")
+		lamedb = scriptlib.lamedb_class()
+
+		self.log("Initialize CrossEPG database")
+		crossdb = scriptlib.crossepg_db_class()
+		crossdb.open_db()
+
+		events = []
+		previous_id = ''
+		channels_name = ''
+		total_events = 0
+
+		self.log("Start data processing")
+		filelist = sorted(os.listdir(self.CONF_CACHEDIR))
+		filelist.append('***END***')
+
+		for f in filelist :
+			id = f.split(self.FIELD_SEPARATOR)[0]
+			if previous_id == '':
+				previous_id = id
+
+			if id != previous_id :
+				total_events += len(events)
+				self.log("  ...processing \'%s\' , nr. events %d" % (previous_id,len(events)))
+				self.log2video("processed %d events ..." % total_events )
+
+				for c in channels_name:
+					# a channel can have zero or more SID (different channel with same name)
+					# return the list [0e1f:00820000:0708:00c8:1:0 , 1d20:00820000:2fa8:013e:1:0 , ..... ]
+					# return [] if channel name is not in lamedb
+					sidbyname = lamedb.get_sid_byname(c.strip(' \n').lower())
+
+					# process every SID
+					for s in sidbyname:
+						# convert "0e1f:00820000:0708:00c8:1:0" to sid,tsid,onid
+						# return the list [sid,tsid,onid]
+						ch_sid = lamedb.convert_sid(s)
+						if len(ch_sid) == 0:
+							continue
+
+						# add channel into db
+						# doesn't matter if the channel already exist... epgdb do all the work
+						crossdb.add_channel(ch_sid)
+
+						i = 0
+						L = len(events) - 1
+
+						# process events
+						for e in events:
+
+							items = e.split(self.FIELD_SEPARATOR)
+							e_starttime = int(items[1])
+
+							if i < L :
+								e_length = int(events[i+1].split(self.FIELD_SEPARATOR)[1]) - e_starttime
+							else:
+								# last event, dummy length 90 min.
+								e_length = 5400
+							i += 1
+
+							# extract title and encode Python Unicode with UTF-8
+							e_title = items[2].encode('utf-8')
+
+							# extract summarie and encode Python Unicode with UTF-8
+							e_summarie = items[3].encode('utf-8')
+
+							# add_event(start_time , duration , title , summarie , ISO639_language_code , strings_encoded_with_UTF-8)
+							crossdb.add_event(e_starttime, e_length, e_title, e_summarie, 'ita', True )
+
+				if f == '***END***':
+					break
+
+				events = []
+				previous_id = id
+				channels_name = ''
+
+			if id == previous_id:
+				self.log("Reading  \'%s\'" % f)
+				# read events from cache file using UTF-8 and insert them in events list
+				fd = codecs.open(os.path.join(self.CONF_CACHEDIR, f),"r","utf-8")
+				lines = fd.readlines()
+				fd.close()
+				if channels_name == '':
+					# first line has channel data (id,name,provider,date)
+					channels_name = lines[0].split(self.FIELD_SEPARATOR)[1].split('|')
+				# the second line is only a remark
+				# add events starting from third line
+				events.extend(lines[2:])
+
+		# end process, close CrossEPG DB saving data
+		crossdb.close_db()
+		self.log("TOTAL EPG EVENTS PROCESSED: %d" % total_events)
+		self.log("--- END ---")
+		self.log2video("END , events processed: %d" % total_events)
+
+
+
+# ****************************************************************************************************************************
+
+# MAIN CODE: SCRIPT START HERE
+
+# increase this process niceness (other processes have higher priority)
+os.nice(10)
+
+# set Garbage Collector to do a "generational jump" more frequently than default 700
+# memory saving: about 50% (!!), some performance loss (obviously)
+gc.set_threshold(50,10,10)
+
+SCRIPT_DIR = 'scripts/mediaprem/'
+
+# get CrossEPG installation dir.
+crossepg_instroot = crossepg.epgdb_get_installroot()
+if crossepg_instroot == False:
+	sys.exit(1)
+scriptlocation = os.path.join(crossepg_instroot , SCRIPT_DIR)
+
+# get where CrossEPG save data (dbroot) and use it as script cache repository
+crossepg_dbroot = crossepg.epgdb_get_dbroot()
+if crossepg_dbroot == False:
+	sys.exit(1)
+
+# initialize script class
+script_class = main(scriptlocation , crossepg_dbroot)
+
+# download data and cache them
+script_class.download_and_cache()
+
+# read cached data and inject into CrossEPG database
+script_class.process_cache()
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/rai/rai.conf
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/rai/rai.conf	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/rai/rai.conf	(revision 8762)
@@ -0,0 +1,109 @@
+# rai.conf by ambrosa http://www.ambrosa.net
+# configuration file
+# 
+
+# ==================================================================================================
+# GLOBAL configuration section
+[global]
+
+# default provider used for searching channel name in lamedb
+DEFAULT_PROVIDER=rai
+
+# cache dir name
+# default CACHE_DIRNAME=script_rai_cache
+CACHE_DIRNAME=script_rai_cache
+
+# GMT zone used in remote website (NOT in receiver)
+# positive if east GMT (like Italy) , i.e. GMT_ZONE=1
+# negative if west GMT (like USA) , i.e. GMT_ZONE=-6
+# 'equal' if receiver time is equal to remote website (same timezone)
+# default GMT_ZONE=equal
+GMT_ZONE=equal
+
+# number of days in the future for downloading EPG
+# MAX_DAY_EPG=1 means "download only today"
+# MAX_DAY_EPG=2 means "download today and tomorrow"
+# ....
+# default MAX_DAY_EPG=7
+MAX_DAY_EPG=7
+
+# RAI EPG HTML repository
+# default URL=http://www.rai.it//dl/portale/GuidaProgrammiAcc.html
+URL=http://www.rai.it//dl/portale/GuidaProgrammiAcc.html
+
+
+# ==================================================================================================
+# CHANNEL configuration section
+[channels]
+
+#
+# YOU must configure every channel ID
+#
+# id=0                       EPG will not be downloaded
+# id=1,LAMEDB_channel_name   EPG will be downloaded and cached
+# id=2,LAMEDB_channel_name   EPG will be downloaded every time
+# id=3,LAMEDB_channel_name   EPG will be downloaded and cached (like '1') but only TODAY will be forced downloading (like '2')
+#
+# Examples:
+# RaiUno=0             channel id 'RaiUno' EPG will NOT be dowloaded
+# RaiUno=1,rai 1       'RaiUno' EPG will be dowloaded and cached and it's name in lamedb is 'rai 1'
+# RaiUno=2,rai1        'RaiUno' EPG will be dowloaded every time and it's name in lamedb is 'rai1'
+#
+# note 1: channel name is case insensitive
+# note 2: you can add many channel name using '|' character as separator (epg will be copied for all these channels)
+#          i.e.  RaiTre=1,rai3|rai 3|rai tre lombardia
+#
+
+
+# BE AWARE : rai channel ID are CASE SENSITIVE , don't change them
+
+
+# RAI1 , id=RaiUno
+RaiUno=0,rai1|rai 1|rai hd|rai test hd
+
+# RAI2 , id=RaiDue
+RaiDue=0,rai2|rai 2
+
+# RAI3 , id=RaiTre
+RaiTre=0,rai3|rai 3|rai 3 tgr lombardia
+
+# RAI4 , id=Rai4
+Rai4=1,rai 4
+
+# Rai5, id=Extra
+Extra=1,rai 5
+
+# Rai Sport 1 , id=RaiSport1
+RaiSport1=0,rai sport 1
+
+# Rai Sport 2 , id=RaiSport2
+RaiSport2=0,rai sport 2
+
+# Rai Scuola , id=RaiEducational
+RaiEducational=0,rai scuola
+
+# Rai Premium, id=Premium
+Premium=1,rai premium
+
+# Rai YoYo, id=Yoyo
+Yoyo=1,rai yoyo
+
+# Rai Movie, id=CinemaWorld
+CinemaWorld=1,rai movie
+
+# Rai Gulp, id=RaiGulp
+RaiGulp=1,rai gulp
+
+# Rai EDU2, id=RaiEDU2
+RaiEDU2=1,rai storia
+
+# RADIO1 , id=RadioUno
+RadioUno=0,rai radio1
+
+# RADIO2 , id=RadioDue
+RadioDue=0,rai radio2
+
+# RADIO3 , id=RadioTre
+RadioTre=0,rai radio3
+
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/rai/rai.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/rai/rai.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/rai/rai.py	(revision 8762)
@@ -0,0 +1,498 @@
+#!/usr/bin/python
+# rai.py  by Ambrosa http://www.ambrosa.net
+# this module is used for download EPG data from Rai website
+# derived from E2_LOADEPG
+
+__author__ = "ambrosa http://www.ambrosa.net"
+__copyright__ = "Copyright (C) 2008-2011 Alessandro Ambrosini"
+__license__ = "CreativeCommons by-nc-sa http://creativecommons.org/licenses/by-nc-sa/3.0/"
+
+import os
+import sys
+import time
+import codecs
+import socket
+import string
+import random
+import urllib2
+import ConfigParser
+
+# import CrossEPG functions
+import crossepg
+
+# location of local python modules under "scripts/lib" dir.
+# add it to sys.path()
+crossepg_instroot = crossepg.epgdb_get_installroot()
+if crossepg_instroot == False:
+	sys.exit(1)
+libdir = os.path.join(crossepg_instroot , 'scripts/lib')
+sys.path.append(libdir)
+
+# import local modules
+import sgmllib
+import scriptlib
+
+# =================================================================
+# HTML PARSER
+
+class Titolo_parser(sgmllib.SGMLParser):
+
+	def parse(self, s):
+		self.feed(s)
+		self.close()
+
+	def __init__(self, day_get, verbose=0):
+		sgmllib.SGMLParser.__init__(self, verbose)
+		self.daynow = day_get
+		self.daynext = time.strftime("%Y%m%d",time.localtime(time.mktime(time.strptime(day_get,"%Y%m%d"))+86400))
+		self.day = self.daynow
+		self.guidatoday = []
+		self.guidatomorrow = []
+		self.sera = False
+		self.tomorrow = False
+		self.start_orario = False
+		self.start_titolo = False
+		self.inside_a_titolo = False
+		self.inside_palinsesto = False
+
+
+	def start_div(self,attributes):
+		for name,value in attributes:
+			if name == "class":
+				if value == "intG":
+					self.inside_palinsesto = True
+
+	def start_span(self, attributes):
+		if self.inside_palinsesto == True:
+			for name, value in attributes:
+				if name == "class":
+					if value == "ora":
+						self.start_orario = True
+					if value == "info":
+						self.start_titolo = True
+
+	def start_a(self,attributes):
+		if self.inside_palinsesto == True:
+			if self.start_titolo == True:
+				self.inside_a_titolo = True
+
+	def handle_data(self, data):
+		if self.inside_palinsesto == True:
+
+			if self.start_orario == True:
+
+				# if time < 06:00 is a next day event
+				if int(time.strftime("%H",time.strptime(data,"%H:%M"))) < 6 :
+					self.day = self.daynext
+					self.tomorrow = True
+				else:
+					if self.tomorrow == True:
+						self.inside_a_titolo = False
+						self.start_titolo = False
+						self.inside_palinsesto = False
+						return
+
+				self.dataoraevento = time.strftime("%Y-%m-%d %H:%M",time.strptime(self.day+'-'+data,"%Y%m%d-%H:%M"))
+				self.start_orario = False
+
+			if self.inside_a_titolo == True:
+				if self.tomorrow == False:
+					self.guidatoday.append((self.dataoraevento,data.strip()))
+				else:
+					self.guidatomorrow.append((self.dataoraevento,data.strip()))
+
+				self.inside_a_titolo = False
+				self.start_titolo = False
+				self.inside_palinsesto = False
+
+
+	def get_guida(self):
+		return ((self.guidatoday,self.guidatomorrow))
+
+
+# =================================================================
+
+
+class main:
+
+	# main config file
+	CONF_CONFIGFILENAME = "rai.conf"
+
+	# Network socket timeout (in seconds)
+	CONF_SOCKET_TIMEOUT = 20
+
+	# log text
+	CONF_LOG_SCRIPT_NAME = "RAI (Italy)"
+	CONF_LOG_PREFIX = "RAI: "
+
+	# retry number if HTTP error
+	HTTP_ERROR_RETRY = 3
+	# seconds to wait between retries
+	HTTP_ERROR_WAIT_RETRY = 5
+
+	# random time delay (in seconds) between access to remote web pages
+	CONF_RANDOM_MIN = 0.0
+	CONF_RANDOM_MAX = 2.0
+
+	# charset used in remote website epg data
+	REMOTE_EPG_CHARSET = 'utf-8'
+
+	TODAY = ''
+	DAYCACHE = []
+	FIELD_SEPARATOR = '###'
+	CHANNELLIST = {}
+
+
+	def log(self,s,video=0):
+		self.logging.log(self.CONF_LOG_PREFIX + str(s))
+		if video == 1:
+			self.log2video(str(s))
+
+	def log2video(self,s):
+		self.logging.log2video_status(str(s))
+
+
+	def __init__(self,confdir,dbroot):
+
+		# initialize logging
+		self.logging = scriptlib.logging_class()
+		# write to video OSD the script name
+		self.logging.log2video_scriptname(self.CONF_LOG_SCRIPT_NAME)
+
+
+		CONF_FILE = os.path.join(confdir,self.CONF_CONFIGFILENAME)
+		if not os.path.exists(CONF_FILE) :
+			self.log("ERROR: %s not present" % CONF_FILE,1)
+			sys.exit(1)
+
+		config = ConfigParser.ConfigParser()
+		config.optionxform = str  # needed to return case sensitive index
+		config.read(CONF_FILE)
+
+		# reading [global] section options
+		self.CONF_DEFAULT_PROVIDER = config.get("global","DEFAULT_PROVIDER")
+		# save cache under dbroot
+		self.CONF_CACHEDIR = os.path.join(dbroot,config.get("global","CACHE_DIRNAME"))
+
+		self.CONF_MAX_DAY_EPG = config.getint("global","MAX_DAY_EPG")
+		self.CONF_URL = config.get("global","URL")
+
+		self.CONF_GMT_ZONE = config.get("global","GMT_ZONE")
+		if self.CONF_GMT_ZONE.strip(' ').lower() == 'equal':
+			#self.DELTA_UTC = -scriptlib.delta_utc() # return negative if timezone is east of GMT (like Italy), invert sign
+			self.DELTA_UTC = 0
+		else:
+			self.DELTA_UTC = float(self.CONF_GMT_ZONE)*3600.0
+			if self.DELTA_UTC >= 0:
+				self.DELTA_UTC = self.DELTA_UTC + scriptlib.delta_dst()
+			else:
+				self.DELTA_UTC = self.DELTA_UTC - scriptlib.delta_dst()
+
+		self.DELTA_UTC = int(self.DELTA_UTC)
+		#self.log("Website timezone - UTC = %d seconds" % self.DELTA_UTC)
+
+		if not os.path.exists(self.CONF_CACHEDIR):
+			self.log("Creating \'%s\' directory for caching" % self.CONF_CACHEDIR)
+			os.mkdir(self.CONF_CACHEDIR)
+
+		# reading [channels] section
+		temp=config.items("channels");
+
+		# create a dictionary (Python array) with index = channel ID
+		for i in temp:
+			self.CHANNELLIST[i[0]] = unicode(i[1],'utf-8')
+
+		if len(self.CHANNELLIST) == 0 :
+			self.log("ERROR: [channels] section empty ?",1)
+			sys.exit(1)
+
+		# set network socket timeout
+		socket.setdefaulttimeout(self.CONF_SOCKET_TIMEOUT)
+
+		# initialize random generator
+		random.seed()
+
+		# today date (format AAAAMMDD)
+		self.TODAY = time.strftime("%Y%m%d")
+
+		# create a list filled with dates (format AAAAMMDD) from today to today+MAX_DAY_EPG
+		self.DAYCACHE=[self.TODAY]
+		for day in range(1,self.CONF_MAX_DAY_EPG):
+			self.DAYCACHE.append(time.strftime("%Y%m%d",time.localtime(time.time()+86400*day)))
+
+
+# ----------------------------------------------------------------------
+
+
+	def download_and_cache(self):
+		self.log("--- START DOWNLOAD AND CACHE DATA ---")
+		self.log2video("STARTING DOWNLOAD")
+
+		self.log("Removing old cached files")
+		scriptlib.cleanup_oldcachedfiles(self.CONF_CACHEDIR, self.FIELD_SEPARATOR)
+
+		#self.log("Start downloading HTML data from \'%s\'" % self.CONF_URL)
+
+		chlist = self.CHANNELLIST
+
+		# get remote XML files
+		#   chid format: channel id , 0|1|2(,new name)
+		#   i.e. ("101" , "1,SkyCinema1")
+		for c in sorted(chlist.keys()):
+			self.guidatoday = []
+			self.guidatomorrow = []
+
+			# get cache option
+			#  0 : don't download/cache
+			#  1 : download and cache (optional 1,new_name )
+			#  2 : always download overwriting existing files (optional 2,new_name )
+			#  3 : always download overwriting existing files only for TODAY (optional 3,new_name )
+
+			cacheopt = int(string.split(chlist[c],",")[0])
+
+			# if cacheopt == 0, do nothing
+			if cacheopt == 0:
+				continue
+
+			channel_name = ''
+			if len(chlist[c].split(",")) > 1 :
+				if chlist[c].split(",")[1] != '' :
+					# channel renamed, new name provided by user
+					channel_name = chlist[c].split(",")[1].strip(' ').lower()
+
+			# if channel name is not present as option, quit with error
+			if channel_name == '':
+				self.log("ERROR ! ID=%s channel name not present" % c, 1)
+				sys.exit(1)
+
+			channel_provider = self.CONF_DEFAULT_PROVIDER
+			if len(chlist[c].split(",")) > 2 :
+				if chlist[c].split(",")[2] != '' :
+					channel_provider = chlist[c].split(",")[2].strip(' ').lower()
+
+			exit_for_loop = False
+			for day in self.DAYCACHE:
+				if exit_for_loop == True:
+					break
+
+				day_get = time.strftime("%Y_%m_%d",time.strptime(day,"%Y%m%d"))
+				xmlfile = "?%s_%s" % (c,day_get)
+
+				# download only if file doesn't exist or cacheopt == 2 (always download),
+				# using open(...,"w") files will be overwritten (saving a delete + create)
+
+				eventfilename = scriptlib.fn_escape(str(c) + self.FIELD_SEPARATOR + channel_name + self.FIELD_SEPARATOR + day)
+				eventfilepath = os.path.join(self.CONF_CACHEDIR, eventfilename)
+				if (cacheopt == 1) and os.path.exists(eventfilepath):
+					continue
+				if (cacheopt == 3) and os.path.exists(eventfilepath) and (day != self.TODAY):
+					continue
+				if (cacheopt != 1) and (cacheopt != 2) and (cacheopt != 3):
+					self.log("Warning: unknown cache option " + str(cacheopt))
+					exit_for_loop = True
+					continue
+
+				self.log("Download HTML data from \'%s\'" % (self.CONF_URL + xmlfile))
+				self.log2video("Download " + c)
+
+				i = self.HTTP_ERROR_RETRY
+				while i > 0  :
+					#  wait randomly to avoid overloading website
+					time.sleep(random.uniform(self.CONF_RANDOM_MIN, self.CONF_RANDOM_MAX))
+
+					try:
+						sock=urllib2.urlopen(self.CONF_URL + xmlfile)
+						data=sock.read()
+
+					except IOError, e:
+						serr="unknown"
+						if hasattr(e, 'reason'):
+							serr=str(e.reason)
+						elif hasattr(e, 'code'):
+							serr=str(e.code)
+							if hasattr(e, 'msg'):
+								serr+=" , "+str(e.msg)
+
+						self.log("\'%s\' connection error. Reason: %s. Waiting %d sec. and retry [%d] ..." % (self.CONF_URL + xmlfile, serr, self.HTTP_ERROR_WAIT_RETRY, i))
+						time.sleep(self.HTTP_ERROR_WAIT_RETRY) # add sleep
+						i -= 1
+
+					else:
+						i = 0 # force quit WHILE loop
+						sock.close()
+
+						dtparser = Titolo_parser(day)
+						dtparser.parse(data)
+						self.guida = self.guidatomorrow
+						(self.guidatoday, self.guidatomorrow) = dtparser.get_guida()
+
+						# if no data, quit for loop and stop downloading
+						if len(self.guidatoday) == 0:
+							exit_for_loop = True
+							break
+
+						self.guida = self.guida + self.guidatoday
+
+						self.log("  writing in cache \'%s\'" % eventfilename)
+						# write data in cache file using UTF-8 encoding
+						fd = codecs.open(eventfilepath, "w", 'utf-8')
+						fd.write(str(c) + self.FIELD_SEPARATOR + channel_name + self.FIELD_SEPARATOR + channel_provider + self.FIELD_SEPARATOR + day + '\n')
+						fd.write("Local Time (human readeable)###Unix GMT Time###Event Title###Event Description\n")
+
+						# extract all events and put in eventfile
+						for event in self.guida:
+							(dataora,titolo) = event
+							event_starttime = dataora
+							# time.mktime return Unix time inside GMT timezone
+							event_startime_unix_gmt = str(int(time.mktime(time.strptime(event_starttime,"%Y-%m-%d %H:%M"))) - self.DELTA_UTC )
+							#event_startime_unix_gmt = str(int(time.mktime(time.strptime(event_starttime,"%Y-%m-%d %H:%M")))  )
+							#self.log(event_starttime + " , " + str(self.DELTA_UTC) + " , " + str(int(time.mktime(time.strptime(event_starttime,"%Y-%m-%d %H:%M")))) + " , " + event_startime_unix_gmt )
+
+							# convert remote data (RAI website use UTF-8) in Python Unicode (UCS2)
+							event_title = unicode(titolo,self.REMOTE_EPG_CHARSET)
+
+							event_title = event_title.replace('\r','')
+							event_title = event_title.replace('\n',u' ')
+							event_title = event_title.strip(u' ')
+
+							event_description = u''
+
+							fd.write(event_starttime + self.FIELD_SEPARATOR + event_startime_unix_gmt + self.FIELD_SEPARATOR + event_title + self.FIELD_SEPARATOR + event_description + '\n')
+
+						fd.close()
+
+
+# ----------------------------------------------------------------------
+
+
+	def process_cache(self):
+		self.log("--- START PROCESSING CACHE ---")
+		self.log2video("START PROCESSING CACHE")
+		if not os.path.exists(self.CONF_CACHEDIR):
+			self.log("ERROR: %s not present" % self.CONF_CACHEDIR,1)
+			sys.exit(1)
+
+		self.log("Loading lamedb")
+		lamedb = scriptlib.lamedb_class()
+
+		self.log("Initialize CrossEPG database")
+		crossdb = scriptlib.crossepg_db_class()
+		crossdb.open_db()
+
+		events = []
+		previous_id = ''
+		channels_name = ''
+		total_events = 0
+
+		self.log("Start data processing")
+		filelist = sorted(os.listdir(self.CONF_CACHEDIR))
+		filelist.append('***END***')
+
+		for f in filelist :
+			id = f.split(self.FIELD_SEPARATOR)[0]
+			if previous_id == '':
+				previous_id = id
+
+			if id != previous_id :
+				total_events += len(events)
+				self.log("  ...processing \'%s\' , nr. events %d" % (previous_id,len(events)))
+				self.log2video("processed %d events ..." % total_events )
+
+				for c in channels_name:
+					# a channel can have zero or more SID (different channel with same name)
+					# return the list [0e1f:00820000:0708:00c8:1:0 , 1d20:00820000:2fa8:013e:1:0 , ..... ]
+					# return [] if channel name is not in lamedb
+					sidbyname = lamedb.get_sid_byname(c.strip(' \n').lower())
+
+					# process every SID
+					for s in sidbyname:
+						# convert "0e1f:00820000:0708:00c8:1:0" to sid,tsid,onid
+						# return the list [sid,tsid,onid]
+						ch_sid = lamedb.convert_sid(s)
+						if len(ch_sid) == 0:
+							continue
+
+						# add channel into db
+						# doesn't matter if the channel already exist... epgdb do all the work
+						crossdb.add_channel(ch_sid)
+
+						i = 0
+						L = len(events) - 1
+
+						# process events
+						for e in events:
+
+							e_starttime = int(e.split(self.FIELD_SEPARATOR)[1])
+
+							if i < L :
+								e_length = int(events[i+1].split(self.FIELD_SEPARATOR)[1]) - e_starttime
+							else:
+								# last event, dummy length 90 min.
+								e_length = 5400
+							i += 1
+
+							# extract title and encode Python Unicode with UTF-8
+							e_title = e.split(self.FIELD_SEPARATOR)[2].encode('utf-8')
+
+							# RAI website HAVE NOT long description. (bleah !).
+							e_summarie = u' '
+							# encode Python Unicode in UTF-8
+							e_summarie = e_summarie.encode('utf-8')
+
+							# add_event(start_time , duration , title , summarie , ISO639_language_code , strings_encoded_with_UTF-8)
+							crossdb.add_event(e_starttime, e_length, e_title, e_summarie, 'ita', True )
+
+				if f == '***END***':
+					break
+
+				events = []
+				previous_id = id
+				channels_name = ''
+
+			if id == previous_id:
+				self.log("Reading  \'%s\'" % f)
+				# read events from cache file using UTF-8 and insert them in events list
+				fd = codecs.open(os.path.join(self.CONF_CACHEDIR, f),"r","utf-8")
+				lines = fd.readlines()
+				fd.close()
+				if channels_name == '':
+					# first line has channel data (id,name,provider,date)
+					channels_name = lines[0].split(self.FIELD_SEPARATOR)[1].split('|')
+				# the second line is only a remark
+				# add events starting from third line
+				events.extend(lines[2:])
+
+		# end process, close CrossEPG DB saving data
+		crossdb.close_db()
+		self.log("TOTAL EPG EVENTS PROCESSED: %d" % total_events)
+		self.log("--- END ---")
+		self.log2video("END , events processed: %d" % total_events)
+
+
+
+# ****************************************************************************************************************************
+
+# MAIN CODE: SCRIPT START HERE
+
+SCRIPT_DIR = 'scripts/rai/'
+
+# get CrossEPG installation dir.
+crossepg_instroot = crossepg.epgdb_get_installroot()
+if crossepg_instroot == False:
+	sys.exit(1)
+scriptlocation = os.path.join(crossepg_instroot , SCRIPT_DIR)
+
+# get where CrossEPG save data (dbroot) and use it as script cache repository
+crossepg_dbroot = crossepg.epgdb_get_dbroot()
+if crossepg_dbroot == False:
+	sys.exit(1)
+
+# initialize script class
+script_class = main(scriptlocation , crossepg_dbroot)
+
+# download data and cache them
+script_class.download_and_cache()
+
+# read cached data and inject into CrossEPG database
+script_class.process_cache()
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/test.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/test.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/crossepg/scripts/test.py	(revision 8762)
@@ -0,0 +1,75 @@
+#!/usr/bin/python
+# above is Python interpreter location
+
+# ambrosa 08-Jan-2011 http://www.ambrosa.net
+# this test.py program simply do nothing
+
+
+import os
+import sys
+
+# import CrossEPG module
+import crossepg
+
+# python local modules under "scripts/lib" directory
+# and add it to sys.path()
+crossepg_instroot = crossepg.epgdb_get_installroot()
+if crossepg_instroot == False:
+	print "ERROR: cannot find CrossEPG installation directory"
+	sys.exit(1)
+libdir = os.path.join(crossepg_instroot , 'scripts/lib')
+sys.path.append(libdir)
+
+# import local modules under 'scripts/lib'
+import scriptlib
+
+# -------------------------------------------------
+# this is the main function
+def main():
+
+	# log_add() print to stdout a text message
+	crossepg.log_add("---- START EXAMPLE TEST SCRIPT ----")
+
+	# get installation dir
+	instdir = crossepg.epgdb_get_installroot()
+	if instdir == False:
+		crossepg.log_add("ERROR: cannot find CrossEPG installation directory")
+		sys.exit(1)
+
+	crossepg.log_add("Installation dir : %s" % instdir)
+
+
+	# get dbroot path
+	dbroot = crossepg.epgdb_get_dbroot()
+	if dbroot == False:
+		crossepg.log_add("ERROR: cannot find CrossEPG database directory")
+		sys.exit(1)
+
+	crossepg.log_add("Database dir : %s" % dbroot)
+
+
+	# open CrossEPG internal database
+	if crossepg.epgdb_open(dbroot):
+		crossepg.log_add("EPGDB opened successfully (root = %s)" % dbroot);
+	else:
+		crossepg.log_add("Error opening EPGDB");
+		crossepg.epgdb_close();
+		sys.exit(1)
+
+	crossepg.log_add("Closing EPGDB");
+	crossepg.epgdb_close();
+
+
+	delta_timezone = scriptlib.delta_utc()
+	crossepg.log_add("GMT vs. LocalTime difference (in seconds): %d" % delta_timezone)
+	delta_daylight = scriptlib.delta_dst()
+	crossepg.log_add("DayLight Saving (DST) difference now: %d" % delta_daylight)
+	
+	
+
+	crossepg.log_add("---- END EXAMPLE TEST SCRIPT ----")
+
+# -------------------------------------------------
+# run main() function
+main()
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_about.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_about.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_about.py	(revision 8762)
@@ -0,0 +1,77 @@
+from enigma import getDesktop
+
+from Screens.Screen import Screen
+
+from Components.Label import Label
+from Components.Button import Button
+from Components.Pixmap import Pixmap
+from Components.ActionMap import ActionMap
+
+from Tools.LoadPixmap import LoadPixmap
+
+from crossepglib import *
+from crossepg_locale import _
+
+import os
+import sys
+
+class CrossEPG_About(Screen):
+	def __init__(self, session):
+		self.session = session
+		if (getDesktop(0).size().width() < 800):
+			skin = "%s/skins/about_sd.xml" % (os.path.dirname(sys.modules[__name__].__file__))
+		else:
+			skin = "%s/skins/about_hd.xml" % (os.path.dirname(sys.modules[__name__].__file__))
+		f = open(skin, "r")
+		self.skin = f.read()
+		f.close()
+
+		Screen.__init__(self, session)
+		
+		self.config = CrossEPG_Config()
+		self.config.load()
+		
+		self["about"] = Label("")
+		self["rytec_pix"] = Pixmap()
+		self["rytec_text"] = Label("")
+		self["krkadoni_pix"] = Pixmap()
+		self["krkadoni_text"] = Label("")
+
+		self["actions"] = ActionMap(["SetupActions", "ColorActions"],
+		{
+			"red": self.quit,
+			"cancel": self.quit
+		}, -2)
+		
+		self["key_red"] = Button(_("Back"))
+		self["key_green"] = Button("")
+		self["key_yellow"] = Button("")
+		self["key_blue"] = Button("")
+
+		try:
+			from version import version
+		except Exception, e:
+			version = "unknow version"
+
+		credit = "SIFTeam CrossEPG %s (c) 2009-2010 Sandro Cavazzoni\n" % version
+		credit += "http://code.google.com/p/crossepg/\n\n"
+		credit += "Application credits:\n"
+		credit += "- Sandro Cavazzoni aka skaman (main developer)\n"
+		credit += "- Ambrosa (scripts developer)\n"
+		credit += "- Spaeleus (italian translations)\n"
+		credit += "- Bodyan (ukrainian translations)\n\n"
+		credit += "Sources credits:\n"
+		credit += "- Rytec http://www.rytec.be (xmltv providers for many countries)\n"
+		credit += "- Krkadoni http://www.krkadoni.com/ (xmltv provider for Ex Yugoslavia and various xepgdb sources maintainer)\n"
+		credit += "- Bodyan and dillinger http://linux-sat.tv/ (xmltv provider for ex USSR channels)"
+		self["about"].setText(credit)
+
+		self.onFirstExecBegin.append(self.setImages)
+
+	def setImages(self):
+		self["rytec_pix"].instance.setPixmapFromFile("%s/images/rytec.png" % (os.path.dirname(sys.modules[__name__].__file__)))
+		self["krkadoni_pix"].instance.setPixmapFromFile("%s/images/krkadoni.png" % (os.path.dirname(sys.modules[__name__].__file__)))
+
+	def quit(self):
+		self.close()
+	
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_auto.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_auto.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_auto.py	(revision 8762)
@@ -0,0 +1,298 @@
+from enigma import * #, quitMainloop
+from Components.ServiceEventTracker import ServiceEventTracker
+from Tools.Directories import fileExists
+from crossepglib import *
+from crossepg_downloader import CrossEPG_Downloader
+from crossepg_converter import CrossEPG_Converter
+from crossepg_loader import CrossEPG_Loader
+from crossepg_importer import CrossEPG_Importer
+from crossepg_locale import _
+from Screens.Screen import Screen
+
+from time import *
+
+import os
+
+class CrossEPG_Auto(Screen):
+	POLL_TIMER = 1800000	# poll every 30 minutes
+	#POLL_TIMER = 18000
+	POLL_TIMER_FAST = 10000	# poll every 10 seconds
+	POLL_TIMER_BOOT = 60000	# poll every 1 minute
+
+	def __init__(self):
+		self.session = None
+
+		self.timer = eTimer()
+		self.standbyTimer = eTimer()
+		self.delayedInitTimer = eTimer()
+
+		self.timer.callback.append(self.poll)
+		self.standbyTimer.callback.append(self.backToStandby)
+		self.delayedInitTimer.callback.append(self.init)
+
+		self.config = CrossEPG_Config()
+		self.patchtype = getEPGPatchType()
+
+		self.pdownloader = None
+		self.pimporter = None
+		self.pconverter = None
+		self.ploader = None
+
+		self.osd = False
+		self.ontune = False
+		self.lock = False
+
+		if fileExists("/tmp/crossepg.standby"):
+			os.system("rm -f /tmp/crossepg.standby")
+			print "[CrossEPG_Auto] coming back in standby in 30 seconds"
+			self.standbyTimer.start(30000, 1)
+			
+		self.config.load()
+		
+		if self.config.force_load_on_boot:
+			self.loader()
+
+	def init(self, session = None):
+		if session != None:
+			self.session = session
+			
+		if time() < 1262325600:		# if before 2010 probably the clock isn't yet updated
+			self.delayedInitTimer.start(60000, 1)	#initialization delayed of 1 minute
+			return
+			
+		self.resetDailyDownloadDateCache()
+		self.timer.start(self.POLL_TIMER_BOOT, 1)
+
+	def forcePoll(self):
+		self.timer.stop()
+		self.resetDailyDownloadDateCache()
+		self.timer.start(self.POLL_TIMER_FAST, 1)
+		
+	def resetDailyDownloadDateCache(self):
+		self.config.load()
+		now = time()
+		ttime = localtime(now)
+		ltime = (ttime[0], ttime[1], ttime[2], self.config.download_daily_hours, self.config.download_daily_minutes, 0, ttime[6], ttime[7], ttime[8])
+		stime = mktime(ltime)
+		if stime < now:
+			ttime = localtime(stime+86400)	# 24 hours in future
+
+		# to avoid problems with internal clock (big changes on date/time)
+		# we step forward of 24 hours until the new time is greater than now
+		while ttime < now:
+			ttime = ttime+86400	# 24 hours in future
+		
+		self.cacheYear = ttime[0]
+		self.cacheMonth = ttime[1]
+		self.cacheDay = ttime[2]
+			
+	def poll(self):
+		from Screens.Standby import inStandby
+		self.config.load()
+
+		if self.lock:
+			print "[CrossEPG_Auto] poll"
+			self.timer.start(self.POLL_TIMER_FAST, 1)
+		elif self.session.nav.RecordTimer.isRecording() or abs(self.session.nav.RecordTimer.getNextRecordingTime() - time()) <= 900 or abs(self.session.nav.RecordTimer.getNextZapTime() - time()) <= 900:
+			print "[CrossEPG_Auto] poll"
+			self.timer.start(self.POLL_TIMER, 1)
+		elif self.config.download_standby_enabled and inStandby:
+			self.providers = []
+			now = time()
+
+			if self.config.last_full_download_timestamp <= now - (24*60*60):
+				self.config.last_full_download_timestamp = now
+				self.config.last_partial_download_timestamp = now
+				self.config.save()
+				self.providers = self.config.providers
+			elif self.config.last_partial_download_timestamp <= now - (60*60): # skip xmltv... we download it only one time a day
+				self.config.last_partial_download_timestamp = now
+				self.config.save()
+				providers = self.config.getAllProviders()
+				i = 0
+				for provider in providers[0]:
+					if self.config.providers.count(provider) > 0:
+						if providers[2][i] == "opentv":
+							self.providers.append(provider)
+						else:
+							print "[CrossEPG_Auto] is not OpenTV : skip provider %s (we download it only one time a day)" % provider
+					i += 1
+
+			if len(self.providers) == 0:
+				print "[CrossEPG_Auto] poll"
+				self.timer.start(self.POLL_TIMER, 1)
+			else:
+				print "[CrossEPG_Auto] automatic download in standby"
+				self.osd = False
+				self.ontune = False
+				self.config.deleteLog()
+				self.download(self.providers)
+		elif self.config.download_daily_enabled:
+			now = time()
+			ttime = localtime(now)
+			ltime = (self.cacheYear, self.cacheMonth, self.cacheDay, self.config.download_daily_hours, self.config.download_daily_minutes, 0, ttime[6], ttime[7], ttime[8])
+			stime = mktime(ltime)
+			if stime < now and self.config.last_full_download_timestamp != stime:
+				from Screens.Standby import inStandby
+				self.osd = (inStandby == None)
+				self.ontune = False
+				self.config.last_full_download_timestamp = stime
+				self.config.last_partial_download_timestamp = stime
+				self.config.save()
+				ttime = localtime(stime+86400)	# 24 hours in future
+				# to avoid problems with internal clock (big changes on date/time)
+				# we step forward of 24 hours until the new time is greater than now
+				while ttime < now:
+					ttime = ttime+86400	# 24 hours in future
+				self.cacheYear = ttime[0]
+				self.cacheMonth = ttime[1]
+				self.cacheDay = ttime[2]
+				self.config.deleteLog()
+				self.download(self.config.providers)
+			elif stime < now + (self.POLL_TIMER / 1000) and self.config.last_full_download_timestamp != stime:
+				print "[CrossEPG_Auto] poll"
+				delta = int(stime - now);
+				self.timer.start((delta + 5)*1000, 1)	# 5 seconds offset
+			else:
+				print "[CrossEPG_Auto] poll"
+				self.timer.start(self.POLL_TIMER, 1)
+		elif self.config.download_tune_enabled:
+			now = time()
+			if self.config.last_partial_download_timestamp <= now - (60*60):
+				providerok = None
+				sservice = self.session.nav.getCurrentlyPlayingServiceReference()
+				if sservice:
+					service = sservice.toString()
+
+					providers = self.config.getAllProviders()
+					i = 0
+					for provider in providers[0]:
+						if providers[2][i] == "opentv":
+							if self.config.getChannelID(provider) == service:
+								providerok = provider
+								break;
+						i += 1
+
+				if providerok:
+					print "[CrossEPG_Auto] automatic download on tune"
+					self.osd = False
+					self.ontune = True
+					self.config.last_partial_download_timestamp = now
+					self.config.save()
+					self.config.deleteLog()
+					self.download([provider,])
+				else:
+					print "[CrossEPG_Auto] poll"
+					self.timer.start(self.POLL_TIMER, 1)
+			else:
+				print "[CrossEPG_Auto] poll"
+				self.timer.start(self.POLL_TIMER, 1)
+		else:
+			print "[CrossEPG_Auto] poll"
+			self.timer.start(self.POLL_TIMER, 1)
+
+	def download(self, providers):
+		print "[CrossEPG_Auto] providers selected for download:"
+		for provider in providers:
+			print "[CrossEPG_Auto] %s" % provider
+		if self.osd:
+			self.session.openWithCallback(self.downloadCallback, CrossEPG_Downloader, providers)
+		else:
+			self.pdownloader = CrossEPG_Downloader(self.session, providers, self.downloadCallback, True)
+
+	def downloadCallback(self, ret):
+		self.pdownloader = None
+
+		from Screens.Standby import inStandby
+		if inStandby: # if in standby force service stop
+			self.session.nav.stopService()
+
+		if ret:
+			if self.config.csv_import_enabled == 1 and not self.ontune:
+				self.importer()
+			else:
+				if self.patchtype != 3:
+					self.converter()
+				else:
+					self.loader()
+		else:
+			self.timer.start(self.POLL_TIMER, 1)
+
+	def importer(self):
+		print "[CrossEPG_Auto] start csv import"
+		if self.osd:
+			self.session.openWithCallback(self.importerCallback, CrossEPG_Importer)
+		else:
+			self.pimporter = CrossEPG_Importer(self.session, self.importerCallback, True)
+
+	def importerCallback(self, ret):
+		self.pimporter = None
+
+		if ret:
+			if self.patchtype != 3:
+				self.converter()
+			else:
+				self.loader()
+		else:
+			self.timer.start(self.POLL_TIMER, 1)
+
+	def converter(self):
+		print "[CrossEPG_Auto] start epg.dat conversion"
+		if self.osd:
+			self.session.openWithCallback(self.converterCallback, CrossEPG_Converter)
+		else:
+			self.pconverter = CrossEPG_Converter(self.session, self.converterCallback, True)
+
+	def converterCallback(self, ret):
+		self.pconverter = None
+
+		if ret:
+			if self.patchtype != -1:
+				self.loader()
+			else:
+				if self.config.download_daily_reboot:
+					from Screens.Standby import inStandby
+					if inStandby:
+						os.system("touch /tmp/crossepg.standby")
+					else:
+						os.system("rm /tmp/crossepg.standby")
+					print "[CrossEPG_Auto] rebooting"
+					from Screens.Standby import TryQuitMainloop
+					self.session.open(TryQuitMainloop, 3)
+				else:
+					self.timer.start(self.POLL_TIMER, 1)
+		else:
+			self.timer.start(self.POLL_TIMER, 1)
+
+	def loader(self):
+		if self.osd:
+			self.session.openWithCallback(self.loaderCallback, CrossEPG_Loader)
+		else:
+			self.ploader = CrossEPG_Loader(self.session, self.loaderCallback, True)
+
+	def loaderCallback(self, ret):
+		self.ploader = None
+		self.timer.start(self.POLL_TIMER, 1)
+
+	def stop(self):
+		if self.pdownloader:
+			self.pdownloader.quit()
+			self.pdownloader = None
+		if self.pimporter:
+			self.pimporter.quit()
+			self.pimporter = None
+		if self.pconverter:
+			self.pconverter.quit()
+			self.pconverter = None
+		if self.ploader:
+			self.ploader.quit()
+			self.ploader = None
+
+	def backToStandby(self):
+		from Screens.Standby import inStandby
+		if inStandby == None:
+			print "[CrossEPG_Auto] coming back in standby"
+			from Screens.Standby import Standby
+			self.session.open(Standby)
+
+crossepg_auto = CrossEPG_Auto()
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_converter.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_converter.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_converter.py	(revision 8762)
@@ -0,0 +1,130 @@
+from enigma import getDesktop, eTimer
+
+from Components.Label import Label
+from Components.Pixmap import Pixmap
+from Components.ProgressBar import ProgressBar
+from Components.ActionMap import NumberActionMap
+
+from Screens.Screen import Screen
+from Screens.MessageBox import MessageBox
+
+from crossepglib import *
+from crossepg_locale import _
+
+import os
+import sys
+
+class CrossEPG_Converter(Screen):
+	def __init__(self, session, pcallback = None, noosd = False):
+		self.session = session
+		if (getDesktop(0).size().width() < 800):
+			skin = "%s/skins/downloader_sd.xml" % os.path.dirname(sys.modules[__name__].__file__)
+			self.isHD = 0
+		else:
+			skin = "%s/skins/downloader_hd.xml" % os.path.dirname(sys.modules[__name__].__file__)
+			self.isHD = 1
+		f = open(skin, "r")
+		self.skin = f.read()
+		f.close()
+		Screen.__init__(self, session)
+		
+		self["background"] = Pixmap()
+		self["action"] = Label(_("Starting converter"))
+		self["status"] = Label("")
+		self["progress"] = ProgressBar()
+		self["progress"].hide()
+		self["actions"] = NumberActionMap(["WizardActions", "InputActions"],
+		{
+			"back": self.quit
+		}, -1)
+		
+		self.retValue = True	
+		self.config = CrossEPG_Config()
+		self.config.load()
+		self.lamedb = self.config.lamedb
+		self.db_root = self.config.db_root
+		if not pathExists(self.db_root):
+			if not createDir(self.db_root):
+				self.db_root = "/hdd/crossepg"
+				
+		self.pcallback = pcallback
+		
+		self.wrapper = CrossEPG_Wrapper()
+		self.wrapper.addCallback(self.wrapperCallback)
+		
+		self.hideprogress = eTimer()
+		self.hideprogress.callback.append(self["progress"].hide)
+		
+		self.pcallbacktimer = eTimer()
+		self.pcallbacktimer.callback.append(self.doCallback)
+
+		if noosd:
+			self.wrappertimer = eTimer()
+			self.wrappertimer.callback.append(self.startWrapper)
+			self.wrappertimer.start(100, 1)
+		else:
+			self.onFirstExecBegin.append(self.firstExec)
+
+	def firstExec(self):
+		if self.isHD:
+			self["background"].instance.setPixmapFromFile("%s/images/background_hd.png" % (os.path.dirname(sys.modules[__name__].__file__)))
+		else:
+			self["background"].instance.setPixmapFromFile("%s/images/background.png" % (os.path.dirname(sys.modules[__name__].__file__)))
+		self.startWrapper()
+
+	def startWrapper(self):
+		self.wrapper.init(CrossEPG_Wrapper.CMD_CONVERTER, self.db_root)
+		
+	def wrapperCallback(self, event, param):
+		if event == CrossEPG_Wrapper.EVENT_READY:
+			self.wrapper.epgdat("%s/ext.epg.dat" % (self.db_root))
+			self.wrapper.lamedb("/etc/enigma2/%s" % (self.lamedb))
+			self.wrapper.convert()
+			
+		elif event == CrossEPG_Wrapper.EVENT_END:
+			self.wrapper.delCallback(self.wrapperCallback)
+			self.wrapper.quit()
+			self.closeAndCallback(self.retValue)
+				
+		elif event == CrossEPG_Wrapper.EVENT_ACTION:
+			self["action"].text = param
+			
+		elif event == CrossEPG_Wrapper.EVENT_STATUS:
+			self["status"].text = param
+			
+		elif event == CrossEPG_Wrapper.EVENT_PROGRESS:
+			self["progress"].setValue(param)
+			
+		elif event == CrossEPG_Wrapper.EVENT_PROGRESSONOFF:
+			if param:
+				self.hideprogress.stop()
+				self["progress"].setValue(0)
+				self["progress"].show()
+			else:
+				self["progress"].setValue(100)
+				self.hideprogress.start(500, 1)
+				
+		elif event == CrossEPG_Wrapper.EVENT_QUIT:
+			self.closeAndCallback(self.retValue)
+			
+		elif event == CrossEPG_Wrapper.EVENT_ERROR:
+			self.session.open(MessageBox, _("CrossEPG error: %s") % (param), type = MessageBox.TYPE_INFO, timeout = 20)
+			self.retValue = False
+			self.quit()
+			
+	def quit(self):
+		if self.wrapper.running():
+			self.retValue = False
+			self.wrapper.quit()
+		else:
+			self.closeAndCallback(False)
+
+	def closeAndCallback(self, ret):
+		self.retValue = ret
+		self.close(ret)
+		self.pcallbacktimer.start(0, 1)
+
+	def doCallback(self):
+		if self.pcallback:
+			self.pcallback(self.retValue)
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_downloader.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_downloader.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_downloader.py	(revision 8762)
@@ -0,0 +1,196 @@
+from enigma import getDesktop, iPlayableService, eTimer, eServiceReference
+
+from Components.Label import Label
+from Components.Pixmap import Pixmap
+from Components.ProgressBar import ProgressBar
+from Components.ServiceEventTracker import ServiceEventTracker
+from Components.ActionMap import NumberActionMap
+
+from Screens.Screen import Screen
+from Screens.MessageBox import MessageBox
+
+from crossepglib import *
+from crossepg_locale import _
+
+import os
+import sys
+
+class CrossEPG_Downloader(Screen):
+	def __init__(self, session, providers, pcallback = None, noosd = False):
+		if (getDesktop(0).size().width() < 800):
+			skin = "%s/skins/downloader_sd.xml" % os.path.dirname(sys.modules[__name__].__file__)
+			self.isHD = 0
+		else:
+			skin = "%s/skins/downloader_hd.xml" % os.path.dirname(sys.modules[__name__].__file__)
+			self.isHD = 1
+		f = open(skin, "r")
+		self.skin = f.read()
+		f.close()
+		Screen.__init__(self, session)
+
+		self.session = session
+		
+		self["background"] = Pixmap()
+		self["action"] = Label(_("Starting downloader"))
+		self["status"] = Label("")
+		self["progress"] = ProgressBar()
+		self["progress"].hide()
+		self["actions"] = NumberActionMap(["WizardActions", "InputActions"],
+		{
+			"back": self.quit
+		}, -1)
+		
+		self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+		{
+			iPlayableService.evTunedIn: self.tuned,
+		})
+		
+		self.retValue = True
+		self.provider_index = 0
+		self.status = 0
+		self.open = False
+		self.saved = False
+		self.tune_enabled = False
+		self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
+		self.config = CrossEPG_Config()
+		self.config.load()
+		self.providers = providers
+		self.pcallback = pcallback
+		
+		self.wrapper = CrossEPG_Wrapper()
+		self.wrapper.addCallback(self.wrapperCallback)
+		
+		self.timeout = eTimer()
+		self.timeout.callback.append(self.quit)
+		
+		self.hideprogress = eTimer()
+		self.hideprogress.callback.append(self["progress"].hide)
+		
+		self.pcallbacktimer = eTimer()
+		self.pcallbacktimer.callback.append(self.doCallback)
+
+		self.wrappertimer = eTimer()
+		self.wrappertimer.callback.append(self.initWrapper)
+
+		if noosd:
+			self.wrappertimer.start(100, 1)
+		else:
+			self.onFirstExecBegin.append(self.firstExec)
+			
+	def firstExec(self):
+		if self.isHD:
+			self["background"].instance.setPixmapFromFile("%s/images/background_hd.png" % (os.path.dirname(sys.modules[__name__].__file__)))
+		else:
+			self["background"].instance.setPixmapFromFile("%s/images/background.png" % (os.path.dirname(sys.modules[__name__].__file__)))
+		self.wrappertimer.start(100, 1)
+
+	def initWrapper(self):
+		if len(self.providers) == 0:
+			self.closeAndCallback(True)
+		else:
+			self.wrapper.init(CrossEPG_Wrapper.CMD_DOWNLOADER, self.config.db_root)
+	
+	def download(self):
+		if self.config.getChannelProtocol(self.providers[self.provider_index]) != "script":
+			if not self.open:
+				self.wrapper.open()
+				self.open = True
+				self.saved = False
+		else:
+			if self.open:
+				self.wrapper.save()
+				self.saved = True
+				self.provider_index -= 1
+				return
+			
+		service = self.config.getChannelID(self.providers[self.provider_index])
+		try:
+			cservice = self.session.nav.getCurrentlyPlayingServiceReference().toString()
+		except Exception, e:
+			cservice = None
+			
+		if service:
+			print "[CrossEPG_Downloader] %s service is %s" % (self.providers[self.provider_index], service)
+			if service == cservice:
+				self.wrapper.download(self.providers[self.provider_index])
+			else:
+				self.tune_enabled = True
+				self.wrapper.wait()
+				self.timeout.start(60000, 1)
+				self.session.nav.playService(eServiceReference(service))
+		else:
+			self.wrapper.download(self.providers[self.provider_index])
+	
+	def wrapperCallback(self, event, param):
+		if event == CrossEPG_Wrapper.EVENT_READY:
+			self.download()
+			
+		elif event == CrossEPG_Wrapper.EVENT_END:
+			if self.saved and self.open:
+				self.wrapper.close()
+				self.open = False
+				
+			if self.status == 0:
+				self.provider_index += 1
+				if self.provider_index < len(self.providers):
+					self.download()
+				else:
+					self.status = 1
+					if self.oldService:
+						self.session.nav.playService(self.oldService)
+					if self.open:
+						self.wrapper.save()
+					else:
+						self.wrapper.quit()
+			else:
+				if self.open:
+					self.wrapper.close()
+				self.wrapper.quit()
+				
+		elif event == CrossEPG_Wrapper.EVENT_ACTION:
+			self["action"].text = param
+			self["status"].text = ""
+			
+		elif event == CrossEPG_Wrapper.EVENT_STATUS or event == CrossEPG_Wrapper.EVENT_URL:
+			self["status"].text = param
+
+		elif event == CrossEPG_Wrapper.EVENT_PROGRESS:
+			self["progress"].setValue(param)
+			
+		elif event == CrossEPG_Wrapper.EVENT_PROGRESSONOFF:
+			if param:
+				self.hideprogress.stop()
+				self["progress"].setValue(0)
+				self["progress"].show()
+			else:
+				self["progress"].setValue(100)
+				self.hideprogress.start(500, 1)
+		elif event == CrossEPG_Wrapper.EVENT_QUIT:
+			self.closeAndCallback(self.retValue)
+		elif event == CrossEPG_Wrapper.EVENT_ERROR:
+			self.session.open(MessageBox, _("CrossEPG error: %s") % (param), type = MessageBox.TYPE_INFO, timeout = 20)
+			self.retValue = False
+			self.quit()
+			
+	def tuned(self):
+		if self.tune_enabled:
+			self.timeout.stop()
+			self.wrapper.download(self.providers[self.provider_index])
+			self.tune_enabled = False
+			
+	def quit(self):
+		if self.wrapper.running():
+			self.retValue = False
+			self.wrapper.quit()
+		else:
+			self.closeAndCallback(False)
+
+	def closeAndCallback(self, ret):
+		self.retValue = ret
+		self.pcallbacktimer.start(0, 1)
+		self.close(ret)
+
+	def doCallback(self):
+		if self.pcallback:
+			self.pcallback(self.retValue)
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_importer.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_importer.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_importer.py	(revision 8762)
@@ -0,0 +1,142 @@
+from enigma import getDesktop, eTimer
+
+from Components.Label import Label
+from Components.Pixmap import Pixmap
+from Components.ProgressBar import ProgressBar
+from Components.ActionMap import NumberActionMap
+
+from Screens.Screen import Screen
+from Screens.MessageBox import MessageBox
+
+from crossepglib import *
+from crossepg_locale import _
+
+import os
+import sys
+
+class CrossEPG_Importer(Screen):
+	def __init__(self, session, pcallback = None, noosd = False):
+		self.session = session
+		if (getDesktop(0).size().width() < 800):
+			skin = "%s/skins/downloader_sd.xml" % os.path.dirname(sys.modules[__name__].__file__)
+			self.isHD = 0
+		else:
+			skin = "%s/skins/downloader_hd.xml" % os.path.dirname(sys.modules[__name__].__file__)
+			self.isHD = 1
+		f = open(skin, "r")
+		self.skin = f.read()
+		f.close()
+		Screen.__init__(self, session)
+		
+		self["background"] = Pixmap()
+		self["action"] = Label(_("Starting importer"))
+		self["status"] = Label("")
+		self["progress"] = ProgressBar()
+		self["progress"].hide()
+		self["actions"] = NumberActionMap(["WizardActions", "InputActions"],
+		{
+			"back": self.quit
+		}, -1)
+		
+		self.retValue = True	
+		self.config = CrossEPG_Config()
+		self.config.load()
+		self.lamedb = self.config.lamedb
+		self.db_root = self.config.db_root
+		if not pathExists(self.db_root):
+			if not createDir(self.db_root):
+				self.db_root = "/hdd/crossepg"
+				
+		self.pcallback = pcallback
+		
+		self.wrapper = CrossEPG_Wrapper()
+		self.wrapper.addCallback(self.wrapperCallback)
+		
+		self.hideprogress = eTimer()
+		self.hideprogress.callback.append(self["progress"].hide)
+		
+		self.pcallbacktimer = eTimer()
+		self.pcallbacktimer.callback.append(self.doCallback)
+
+		self.status = 0
+
+		if noosd:
+			self.wrappertimer = eTimer()
+			self.wrappertimer.callback.append(self.startWrapper)
+			self.wrappertimer.start(100, 1)
+		else:
+			self.onFirstExecBegin.append(self.firstExec)
+
+	def firstExec(self):
+		if self.isHD:
+			self["background"].instance.setPixmapFromFile("%s/images/background_hd.png" % (os.path.dirname(sys.modules[__name__].__file__)))
+		else:
+			self["background"].instance.setPixmapFromFile("%s/images/background.png" % (os.path.dirname(sys.modules[__name__].__file__)))
+		self.startWrapper()
+
+	def startWrapper(self):
+		self.wrapper.init(CrossEPG_Wrapper.CMD_IMPORTER, self.db_root)
+	
+	def wrapperCallback(self, event, param):
+		if event == CrossEPG_Wrapper.EVENT_READY:
+			self.wrapper.importx()
+			
+		elif event == CrossEPG_Wrapper.EVENT_END:
+			if self.status == 0:
+				self.status += 1
+				self.wrapper.save()
+			else:
+				self.wrapper.delCallback(self.wrapperCallback)
+				self.wrapper.quit()
+				self.closeAndCallback(self.retValue)
+				
+		elif event == CrossEPG_Wrapper.EVENT_FILE:
+			self["action"].text = _("Parsing")
+			self["status"].text = param
+			
+		elif event == CrossEPG_Wrapper.EVENT_URL:
+			self["action"].text = _("Downloading")
+			self["status"].text = param
+			
+		elif event == CrossEPG_Wrapper.EVENT_ACTION:
+			self["action"].text = param
+			
+		elif event == CrossEPG_Wrapper.EVENT_STATUS:
+			self["status"].text = param
+			
+		elif event == CrossEPG_Wrapper.EVENT_PROGRESS:
+			self["progress"].setValue(param)
+			
+		elif event == CrossEPG_Wrapper.EVENT_PROGRESSONOFF:
+			if param:
+				self.hideprogress.stop()
+				self["progress"].setValue(0)
+				self["progress"].show()
+			else:
+				self["progress"].setValue(100)
+				self.hideprogress.start(500, 1)
+				
+		elif event == CrossEPG_Wrapper.EVENT_QUIT:
+			self.closeAndCallback(self.retValue)
+			
+		elif event == CrossEPG_Wrapper.EVENT_ERROR:
+			self.session.open(MessageBox, _("CrossEPG error: %s") % (param), type = MessageBox.TYPE_INFO, timeout = 20)
+			self.retValue = False
+			self.quit()
+			
+	def quit(self):
+		if self.wrapper.running():
+			self.retValue = False
+			self.wrapper.quit()
+		else:
+			self.closeAndCallback(False)
+
+	def closeAndCallback(self, ret):
+		self.retValue = ret
+		self.close(ret)
+		self.pcallbacktimer.start(0, 1)
+
+	def doCallback(self):
+		if self.pcallback:
+			self.pcallback(self.retValue)
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_info.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_info.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_info.py	(revision 8762)
@@ -0,0 +1,84 @@
+from enigma import getDesktop
+
+from Screens.Screen import Screen
+
+from Components.Label import Label
+from Components.Button import Button
+from Components.ActionMap import ActionMap
+
+from crossepglib import *
+from crossepg_locale import _
+
+import os
+import sys
+
+class CrossEPG_Info(Screen):
+	def __init__(self, session):
+		self.session = session
+		if (getDesktop(0).size().width() < 800):
+			skin = "%s/skins/info_sd.xml" % (os.path.dirname(sys.modules[__name__].__file__))
+		else:
+			skin = "%s/skins/info_hd.xml" % (os.path.dirname(sys.modules[__name__].__file__))
+		f = open(skin, "r")
+		self.skin = f.read()
+		f.close()
+
+		Screen.__init__(self, session)
+		
+		self.config = CrossEPG_Config()
+		self.config.load()
+		
+		self["version"] = Label("")
+		self["create"] = Label("")
+		self["last_update"] = Label("")
+		self["headersdb_size"] = Label("")
+		self["descriptorsdb_size"] = Label("")
+		self["indexesdb_size"] = Label("")
+		self["aliasesdb_size"] = Label("")
+		self["total_size"] = Label("")
+		self["channels_count"] = Label("")
+		self["events_count"] = Label("")
+		self["hashes_count"] = Label("")
+		self["actions"] = ActionMap(["SetupActions", "ColorActions"],
+		{
+			"red": self.quit,
+			"cancel": self.quit
+		}, -2)
+		
+		self["key_red"] = Button(_("Back"))
+		self["key_green"] = Button("")
+		self["key_yellow"] = Button("")
+		self["key_blue"] = Button("")
+		
+		self.wrapper = CrossEPG_Wrapper()
+		self.wrapper.addCallback(self.__wrapperCallback)
+		self.wrapper.init(CrossEPG_Wrapper.CMD_INFO, self.config.db_root)
+			
+	def quit(self):
+		if not self.wrapper.running():
+			self.close()
+	
+	def __wrapperCallback(self, event, param):
+		if event == CrossEPG_Wrapper.INFO_HEADERSDB_SIZE:
+			self["headersdb_size"].text = _("Headers db size: %s") % (param)
+		elif event == CrossEPG_Wrapper.INFO_DESCRIPTORSDB_SIZE:
+			self["descriptorsdb_size"].text = _("Descriptors db size: %s") % (param)
+		elif event == CrossEPG_Wrapper.INFO_INDEXESDB_SIZE:
+			self["indexesdb_size"].text = _("Indexes db size: %s") % (param)
+		elif event == CrossEPG_Wrapper.INFO_ALIASESDB_SIZE:
+			self["aliasesdb_size"].text = _("Aliases db size: %s") % (param)
+		elif event == CrossEPG_Wrapper.INFO_TOTAL_SIZE:
+			self["total_size"].text = _("Total size: %s") % (param)
+		elif event == CrossEPG_Wrapper.INFO_CHANNELS_COUNT:
+			self["channels_count"].text = _("Channels count: %s") % (param)
+		elif event == CrossEPG_Wrapper.INFO_EVENTS_COUNT:
+			self["events_count"].text = _("Events count: %s") % (param)
+		elif event == CrossEPG_Wrapper.INFO_HASHES_COUNT:
+			self["hashes_count"].text = _("Hashes count: %s") % (param)
+		elif event == CrossEPG_Wrapper.INFO_CREATION_TIME:
+			self["create"].text = _("Creation time: %s") % (param)
+		elif event == CrossEPG_Wrapper.INFO_UPDATE_TIME:
+			self["last_update"].text = _("Last update time: %s") % (param)
+		elif event == CrossEPG_Wrapper.INFO_VERSION:
+			self["version"].text = _("Version: %s") % (param)
+			
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_loader.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_loader.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_loader.py	(revision 8762)
@@ -0,0 +1,226 @@
+from enigma import getDesktop, eTimer
+
+from Components.config import config
+from Components.Label import Label
+from Components.Pixmap import Pixmap
+from Components.ProgressBar import ProgressBar
+from Components.ActionMap import NumberActionMap
+
+from Screens.Screen import Screen
+from Screens.MessageBox import MessageBox
+
+from crossepglib import *
+from crossepg_locale import _
+
+import _enigma
+import os
+import sys
+
+class CrossEPG_Loader(Screen):
+	def __init__(self, session, pcallback = None, noosd = False):
+		self.session = session
+		if (getDesktop(0).size().width() < 800):
+			skin = "%s/skins/downloader_sd.xml" % os.path.dirname(sys.modules[__name__].__file__)
+			self.isHD = 0
+		else:
+			skin = "%s/skins/downloader_hd.xml" % os.path.dirname(sys.modules[__name__].__file__)
+			self.isHD = 1
+		f = open(skin, "r")
+		self.skin = f.read()
+		f.close()
+		Screen.__init__(self, session)
+
+		self["background"] = Pixmap()
+		self["action"] = Label(_("Loading data"))
+		self["status"] = Label("")
+		self["progress"] = ProgressBar()
+		self["progress"].hide()
+		
+		self.retValue = True	
+		self.config = CrossEPG_Config()
+		self.config.load()
+		self.db_root = self.config.db_root
+		if not pathExists(self.db_root):
+			if not createDir(self.db_root):
+				self.db_root = "/hdd/crossepg"
+				
+		self.pcallback = pcallback
+		self.wrapper = None
+
+		self.pcallbacktimer = eTimer()
+		self.pcallbacktimer.callback.append(self.doCallback)
+		
+		if pathExists("/usr/crossepg"):
+			self.home_directory = "/usr/crossepg"
+		elif pathExists("/var/crossepg"):
+			self.home_directory = "/var/crossepg"
+		else:
+			print "[CrossEPG_Config] ERROR!! CrossEPG binaries non found"
+		
+		# check for common patches
+		try:
+			self.xepgpatch = new.instancemethod(_enigma.eEPGCache_crossepgImportEPGv21,None,eEPGCache)
+			print "[CrossEPG_Loader] patch crossepg v2.1 found"
+		except Exception, e:
+			self.xepgpatch = None
+			
+		try:
+			self.epgpatch = new.instancemethod(_enigma.eEPGCache_load,None,eEPGCache)
+			print "[CrossEPG_Loader] patch epgcache.load() found"
+		except Exception, e:
+			self.epgpatch = None
+			
+		try:
+			self.edgpatch = new.instancemethod(_enigma.eEPGCache_reloadEpg,None,eEPGCache)
+			print "[CrossEPG_Loader] patch EDG NEMESIS found"
+		except Exception, e:
+			self.edgpatch = None
+			
+		try:
+			self.oudeispatch = new.instancemethod(_enigma.eEPGCache_importEvent,None,eEPGCache)
+			print "[CrossEPG_Loader] patch Oudeis found"
+		except Exception, e:
+			self.oudeispatch = None
+		
+		if self.xepgpatch:
+			self.timer = eTimer()
+			self.timer.callback.append(self.loadEPG2)
+			self.timer.start(200, 1)
+
+		elif self.epgpatch:
+			self.timer = eTimer()
+			self.timer.callback.append(self.loadEPG)
+			self.timer.start(200, 1)
+			
+		elif self.edgpatch:
+			self.timer = eTimer()
+			self.timer.callback.append(self.loadEDG)
+			self.timer.start(200, 1)
+			
+		elif self.oudeispatch:
+			self["actions"] = NumberActionMap(["WizardActions", "InputActions"],
+			{
+				"back": self.quit
+			}, -1)
+			
+			self.wrapper = CrossEPG_Wrapper()
+			self.wrapper.addCallback(self.wrapperCallback)
+			
+			self.timeout = eTimer()
+			self.timeout.callback.append(self.quit)
+			
+			self.hideprogress = eTimer()
+			self.hideprogress.callback.append(self["progress"].hide)
+			
+			self.epg_channel = None;
+			self.epg_tuple = ()
+			self.epg_starttime = 0
+			self.epg_length = 0
+			self.epg_name = ""
+			
+			self.wrapper.init(CrossEPG_Wrapper.CMD_CONVERTER, self.db_root)
+		else:
+			print "No patch found... please reboot enigma2 manually"
+			self.closeAndCallback(True)
+
+		if not noosd:
+			self.onFirstExecBegin.append(self.firstExec)
+
+	def firstExec(self):
+		if self.isHD:
+			self["background"].instance.setPixmapFromFile("%s/images/background_hd.png" % (os.path.dirname(sys.modules[__name__].__file__)))
+		else:
+			self["background"].instance.setPixmapFromFile("%s/images/background.png" % (os.path.dirname(sys.modules[__name__].__file__)))
+
+	def loadEPG2(self):
+		print "[CrossEPG_Loader] loading data with crossepg patch v2"
+		self.xepgpatch(eEPGCache.getInstance(), self.db_root)
+		self.closeAndCallback(True)
+	
+	def loadEPG(self):
+		cmd = "%s/crossepg_epgcopy %s/ext.epg.dat /hdd/epg.dat" % (self.home_directory, self.db_root)
+		print "[CrossEPG_Loader] %s" % (cmd)
+		os.system(cmd)
+		self.epgpatch(eEPGCache.getInstance())
+		self.closeAndCallback(True)
+		
+	def loadEDG(self):
+		cmd = "%s/crossepg_epgcopy %s/ext.epg.dat %s/epg.dat" % (self.home_directory, self.db_root, config.nemepg.path.value)
+		print "[CrossEPG_Loader] %s" % (cmd)
+		os.system(cmd)
+		self.edgpatch(eEPGCache.getInstance())
+		self.closeAndCallback(True)
+		
+	def wrapperCallback(self, event, param):
+		if event == CrossEPG_Wrapper.EVENT_READY:
+			self.wrapper.text()
+			
+		elif event == CrossEPG_Wrapper.EVENT_END:
+			self.wrapper.quit()
+			
+		elif event == CrossEPG_Wrapper.EVENT_ACTION:
+			self["action"].text = param
+			
+		elif event == CrossEPG_Wrapper.EVENT_STATUS:
+			self["status"].text = param
+			
+		elif event == CrossEPG_Wrapper.EVENT_PROGRESS:
+			self["progress"].setValue(param)
+			
+		elif event == CrossEPG_Wrapper.EVENT_CHANNEL:
+			if self.epg_channel:
+				if len(self.epg_tuple) > 0:
+					self.oudeispatch(eEPGCache.getInstance(), self.epg_channel, self.epg_tuple)
+					self.epg_tuple = ()
+			self.epg_channel = param
+			
+		elif event == CrossEPG_Wrapper.EVENT_STARTTIME:
+			self.epg_starttime = param
+			
+		elif event == CrossEPG_Wrapper.EVENT_LENGTH:
+			self.epg_length = param
+			
+		elif event == CrossEPG_Wrapper.EVENT_NAME:
+			self.epg_name = param
+			
+		elif event == CrossEPG_Wrapper.EVENT_DESCRIPTION:
+			if self.epg_channel:
+				self.epg_tuple += ((self.epg_starttime, self.epg_length, self.epg_name, self.epg_name, param, 0),)
+			
+		elif event == CrossEPG_Wrapper.EVENT_PROGRESSONOFF:
+			if param:
+				self.hideprogress.stop()
+				self["progress"].setValue(0)
+				self["progress"].show()
+			else:
+				self["progress"].setValue(100)
+				self.hideprogress.start(500, 1)
+		elif event == CrossEPG_Wrapper.EVENT_QUIT:
+			if self.epg_channel:
+				if len(self.epg_tuple) > 0:
+					self.oudeispatch(eEPGCache.getInstance(), self.epg_channel, self.epg_tuple)
+			self.closeAndCallback(self.retValue)
+			
+		elif event == CrossEPG_Wrapper.EVENT_ERROR:
+			self.session.open(MessageBox, _("CrossEPG error: %s") % (param), type = MessageBox.TYPE_INFO, timeout = 20)
+			self.retValue = False
+			self.quit()
+			
+	def quit(self):
+		if self.wrapper:
+			if self.wrapper.running():
+				self.retValue = False
+				self.wrapper.quit()
+				return
+
+		self.closeAndCallback(False)
+
+	def closeAndCallback(self, ret):
+		self.retValue = ret
+		self.close(ret)
+		self.pcallbacktimer.start(0, 1)
+
+	def doCallback(self):
+		if self.pcallback:
+			self.pcallback(self.retValue)
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_locale.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_locale.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_locale.py	(revision 8762)
@@ -0,0 +1,25 @@
+from Components.Language import language
+from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_LANGUAGE
+
+import os,gettext
+
+PluginLanguageDomain = "CrossEPG"
+PluginLanguagePath = "SystemPlugins/CrossEPG/po"
+
+def localeInit():
+	lang = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
+	os.environ["LANGUAGE"] = lang # Enigma doesn't set this (or LC_ALL, LC_MESSAGES, LANG). gettext needs it!
+	print "[CrossEPG] set language to ", lang
+	gettext.bindtextdomain(PluginLanguageDomain, resolveFilename(SCOPE_PLUGINS, PluginLanguagePath))
+	gettext.bindtextdomain('enigma2', resolveFilename(SCOPE_LANGUAGE, ""))
+
+def _(txt):
+	t = gettext.dgettext(PluginLanguageDomain, txt)
+	if t == txt:
+		#print "[CrossEPG] fallback to default translation for", txt
+		t = gettext.dgettext('enigma2', txt)
+	return t
+
+
+localeInit()
+language.addCallback(localeInit)
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_main.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_main.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_main.py	(revision 8762)
@@ -0,0 +1,86 @@
+from enigma import *
+from Screens.MessageBox import MessageBox
+
+from crossepglib import *
+from crossepg_downloader import CrossEPG_Downloader
+from crossepg_importer import CrossEPG_Importer
+from crossepg_converter import CrossEPG_Converter
+from crossepg_loader import CrossEPG_Loader
+from crossepg_setup import CrossEPG_Setup
+from crossepg_menu import CrossEPG_Menu
+from crossepg_auto import crossepg_auto
+
+class CrossEPG_Main:
+	def __init__(self):
+		self.config = CrossEPG_Config()
+		self.patchtype = getEPGPatchType()
+		
+	def downloader(self, session, **kwargs):
+		self.session = session
+		crossepg_auto.lock = True
+		crossepg_auto.stop()
+		self.config.load()
+		if self.config.configured == 0:
+			self.session.open(MessageBox, _("Please configure crossepg before start downloader"), type = MessageBox.TYPE_ERROR)
+		else:
+			self.config.deleteLog()
+			self.session.openWithCallback(self.downloadCallback, CrossEPG_Downloader, self.config.providers)
+
+	def downloadCallback(self, ret):
+		if ret:
+			if self.config.csv_import_enabled == 1:
+				self.importer()
+			else:
+				if self.patchtype != 3:
+					self.converter()
+				else:
+					self.loader()
+		else:
+			crossepg_auto.lock = False
+
+	def importer(self):
+		self.session.openWithCallback(self.importerCallback, CrossEPG_Importer)
+
+	def importerCallback(self, ret):
+		if ret:
+			if self.patchtype != 3:
+				self.converter()
+			else:
+				self.loader()
+		else:
+			crossepg_auto.lock = False
+
+	def converter(self):
+		self.session.openWithCallback(self.converterCallback, CrossEPG_Converter)
+
+	def converterCallback(self, ret):
+		if ret:
+			if self.patchtype != -1:
+				self.loader()
+			else:
+				if self.config.download_manual_reboot:
+					from Screens.Standby import TryQuitMainloop
+					self.session.open(TryQuitMainloop, 3)
+				else:
+					crossepg_auto.lock = False
+		else:
+			crossepg_auto.lock = False
+
+	def loader(self):
+		self.session.openWithCallback(self.loaderCallback, CrossEPG_Loader)
+
+	def loaderCallback(self, ret):
+		crossepg_auto.lock = False
+
+	def setup(self, session, **kwargs):
+		crossepg_auto.lock = True
+		crossepg_auto.stop()
+		session.openWithCallback(self.setupCallback, CrossEPG_Menu)
+
+	def setupCallback(self):
+		crossepg_auto.lock = False
+
+	def autostart(self, reason, session):
+		crossepg_auto.init(session)
+		
+crossepg_main = CrossEPG_Main()
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_menu.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_menu.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_menu.py	(revision 8762)
@@ -0,0 +1,164 @@
+from enigma import *
+from crossepglib import *
+from crossepg_auto import crossepg_auto
+from crossepg_info import CrossEPG_Info
+from crossepg_about import CrossEPG_About
+from crossepg_providers import CrossEPG_Providers
+from crossepg_setup import CrossEPG_Setup
+from crossepg_downloader import CrossEPG_Downloader
+from crossepg_importer import CrossEPG_Importer
+from crossepg_converter import CrossEPG_Converter
+from crossepg_loader import CrossEPG_Loader
+from crossepg_ordering import CrossEPG_Ordering
+from crossepg_locale import _
+
+from Screens.Screen import Screen
+from Screens.MessageBox import MessageBox
+
+from Components.Label import Label
+from Components.Button import Button
+from Components.MenuList import MenuList
+from Components.Sources.List import List
+from Components.MultiContent import MultiContentEntryText
+from Components.Harddisk import harddiskmanager
+from Components.PluginComponent import plugins
+from Components.ActionMap import ActionMap
+from Tools.LoadPixmap import LoadPixmap
+from Tools.Directories import resolveFilename, SCOPE_PLUGINS
+from Plugins.Plugin import PluginDescriptor
+
+from time import *
+
+try:
+	from version import version
+except Exception, e:
+	pass
+
+import _enigma
+
+class CrossEPG_Menu(Screen):
+	def __init__(self, session):
+		if (getDesktop(0).size().width() < 800):
+			skin = "%s/skins/menu_sd.xml" % os.path.dirname(sys.modules[__name__].__file__)
+		else:
+			skin = "%s/skins/menu_hd.xml" % os.path.dirname(sys.modules[__name__].__file__)
+		f = open(skin, "r")
+		self.skin = f.read()
+		f.close()
+		Screen.__init__(self, session)
+
+		self.config = CrossEPG_Config()
+		self.config.load()
+		self.patchtype = getEPGPatchType()
+
+		l = []
+		l.append(self.buildListEntry(_("Configure"), "configure.png"))
+		l.append(self.buildListEntry(_("XMLTV providers"), "xmltv.png"))
+		l.append(self.buildListEntry(_("OpenTV providers"), "opentv.png"))
+		l.append(self.buildListEntry(_("XEPGDB providers"), "xepgdb.png"))
+		l.append(self.buildListEntry(_("Scripts providers"), "scripts.png"))
+		l.append(self.buildListEntry(_("Providers start order"), "reorder.png"))
+		l.append(self.buildListEntry(_("Download now"), "download.png"))
+		l.append(self.buildListEntry(_("Force csv import now"), "csv.png"))
+		l.append(self.buildListEntry(_("Force epg.dat conversion now"), "conversion.png"))
+		l.append(self.buildListEntry(_("Force epg reload"), "reload.png"))
+		l.append(self.buildListEntry(_("Info about database"), "dbinfo.png"))
+		l.append(self.buildListEntry(_("About"), "about.png"))
+
+		self["list"] = List(l)
+		self["setupActions"] = ActionMap(["SetupActions"],
+		{
+			"cancel": self.quit,
+			"ok": self.openSelected,
+		}, -2)
+
+		self.onFirstExecBegin.append(self.setTitleWithVerion)
+		
+		if self.config.configured == 0:
+			self.onFirstExecBegin.append(self.openSetup)
+
+	def buildListEntry(self, description, image):
+		pixmap = LoadPixmap(cached=True, path="%s/images/%s" % (os.path.dirname(sys.modules[__name__].__file__), image));
+		return((pixmap, description))
+
+	def openSetup(self):
+		self.session.open(CrossEPG_Setup)
+			
+	def setTitleWithVerion(self):
+		try:
+			global version
+			self.setTitle("CrossEPG - %s" % version)
+		except Exception, e:
+			self.setTitle("CrossEPG - unknow version")
+
+	def openSelected(self):
+		index = self["list"].getIndex()
+		if index == 0:
+			self.session.open(CrossEPG_Setup)
+		elif index == 1:
+			self.session.open(CrossEPG_Providers, "xmltv")
+		elif index == 2:
+			self.session.open(CrossEPG_Providers, "opentv")
+		elif index == 3:
+			self.session.open(CrossEPG_Providers, "xepgdb")
+		elif index == 4:
+			self.session.open(CrossEPG_Providers, "script")
+		elif index == 5:
+			self.session.open(CrossEPG_Ordering)
+		elif index == 6:
+			self.config.load()
+			self.config.deleteLog()
+			self.downloader()
+		elif index == 7:
+			self.importer()
+		elif index == 8:
+			self.converter()
+		elif index == 9:
+			self.loader()
+		elif index == 10:
+			self.session.open(CrossEPG_Info)
+		elif index == 11:
+			self.session.open(CrossEPG_About)
+		
+	def quit(self):
+		self.close()
+
+	def downloader(self):
+		self.config.load()
+		self.session.openWithCallback(self.downloadCallback, CrossEPG_Downloader, self.config.providers)
+
+	def downloadCallback(self, ret):
+		if ret:
+			if self.config.csv_import_enabled == 1:
+				self.importer()
+			else:
+				if self.patchtype != 3:
+					self.converter()
+				else:
+					self.loader()
+
+	def importer(self):
+		self.session.openWithCallback(self.importerCallback, CrossEPG_Importer)
+
+	def importerCallback(self, ret):
+		if ret:
+			if self.patchtype != 3:
+				self.converter()
+			else:
+				self.loader()
+
+	def converter(self):
+		self.session.openWithCallback(self.converterCallback, CrossEPG_Converter)
+
+	def converterCallback(self, ret):
+		if ret:
+			if self.patchtype != -1:
+				self.loader()
+			else:
+				if self.config.download_manual_reboot:
+					from Screens.Standby import TryQuitMainloop
+					session.open(TryQuitMainloop, 3)
+
+	def loader(self):
+		self.session.open(CrossEPG_Loader)
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_ordering.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_ordering.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_ordering.py	(revision 8762)
@@ -0,0 +1,116 @@
+from enigma import getDesktop
+
+from Screens.Screen import Screen
+
+from Components.Label import Label
+from Components.Button import Button
+from Components.ActionMap import ActionMap
+from Components.Sources.List import List
+
+from Tools.LoadPixmap import LoadPixmap
+
+from crossepg_locale import _
+
+from crossepglib import *
+
+class CrossEPG_Ordering(Screen):
+	def __init__(self, session):
+		if (getDesktop(0).size().width() < 800):
+			skin = "%s/skins/providers_sd.xml" % os.path.dirname(sys.modules[__name__].__file__)
+		else:
+			skin = "%s/skins/providers_hd.xml" % os.path.dirname(sys.modules[__name__].__file__)
+		f = open(skin, "r")
+		self.skin = f.read()
+		f.close()
+		Screen.__init__(self, session)
+
+		self.config = CrossEPG_Config()
+		self.config.load()
+		self.providers = self.config.getAllProviders()
+		self.list = []
+
+		self["list"] = List(self.list)
+		self["list"].onSelectionChanged.append(self.selectionChanged)
+		self["key_red"] = Button(_("Back"))
+		self["key_green"] = Button("")
+		self["key_yellow"] = Button("")
+		self["key_blue"] = Button("")
+		self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
+		{
+			"red": self.quit,
+			"cancel": self.quit,
+			"green": self.moveUp,
+			"yellow": self.moveDown,
+		}, -2)
+
+		self.buildList()
+		self.onFirstExecBegin.append(self.setCustomTitle)
+		self.onFirstExecBegin.append(self.selectionChanged)
+
+	def setCustomTitle(self):
+		self.setTitle(_("CrossEPG - Providers start order"))
+
+	def getProviderDescription(self, provider):
+		i = 0
+		for prv in self.providers[0]:
+			if prv == provider:
+				return self.providers[1][i]
+			i += 1
+			
+		return provider
+	
+	def buildList(self):
+		self.list = []
+		for provider in self.config.providers:
+			self.list.append(self.buildListEntry(provider, self.getProviderDescription(provider)))
+
+		self["list"].setList(self.list)
+
+	def buildListEntry(self, name, description):
+		return((description, None, name))
+		
+	def selectionChanged(self):
+		if len(self.list) <= 1:
+			return
+
+		index = self["list"].getIndex()
+		if index == 0:
+			self["key_green"].setText("")
+			self["key_yellow"].setText(_("Move down"))
+		elif index == len(self.list) - 1:
+			self["key_green"].setText(_("Move up"))
+			self["key_yellow"].setText("")
+		else:
+			self["key_green"].setText(_("Move up"))
+			self["key_yellow"].setText(_("Move down"))
+
+	def moveUp(self):
+		if len(self.list) <= 1:
+			return
+
+		index = self["list"].getIndex()
+		if index > 0:
+			tmp = self.config.providers[index - 1]
+			self.config.providers[index - 1] = self.config.providers[index]
+			self.config.providers[index] = tmp
+			
+			self.buildList()
+			self["list"].setIndex(index - 1)
+			
+	def moveDown(self):
+		if len(self.list) <= 1:
+			return
+
+		index = self["list"].getIndex()
+		if index < len(self.list) - 1:
+			tmp = self.config.providers[index + 1]
+			self.config.providers[index + 1] = self.config.providers[index]
+			self.config.providers[index] = tmp
+
+			self.buildList()
+			self["list"].setIndex(index + 1)
+
+	def quit(self):
+		self.config.save()
+		self.close()
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_providers.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_providers.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_providers.py	(revision 8762)
@@ -0,0 +1,137 @@
+from enigma import getDesktop
+
+from Screens.Screen import Screen
+
+from Components.Label import Label
+from Components.Button import Button
+from Components.ActionMap import ActionMap
+from Components.Sources.List import List
+
+from Tools.LoadPixmap import LoadPixmap
+
+from crossepg_downloader import CrossEPG_Downloader
+from crossepg_converter import CrossEPG_Converter
+from crossepg_loader import CrossEPG_Loader
+from crossepg_locale import _
+
+from crossepglib import *
+
+class CrossEPG_Providers(Screen):
+	def __init__(self, session, protocol):
+		if (getDesktop(0).size().width() < 800):
+			skin = "%s/skins/providers_sd.xml" % os.path.dirname(sys.modules[__name__].__file__)
+		else:
+			skin = "%s/skins/providers_hd.xml" % os.path.dirname(sys.modules[__name__].__file__)
+		f = open(skin, "r")
+		self.skin = f.read()
+		f.close()
+		Screen.__init__(self, session)
+
+		self.patchtype = getEPGPatchType()
+		self.config = CrossEPG_Config()
+		self.config.load()
+		self.providers = self.config.getAllProviders()
+		self.protocol = protocol
+
+		self.old_service = None
+		self.list = []
+
+		self["list"] = List(self.list)
+		self["list"].onSelectionChanged.append(self.selectionChanged)
+		self["key_red"] = Button(_("Back"))
+		self["key_green"] = Button(_("Enable"))
+		self["key_yellow"] = Button(_("Download"))
+		self["key_blue"] = Button("")
+		self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
+		{
+			"red": self.quit,
+			"cancel": self.quit,
+			"green": self.switchState,
+			"ok": self.switchState,
+			"yellow": self.download,
+		}, -2)
+
+		self.buildList()
+		self.onFirstExecBegin.append(self.setTitleByProtocol)
+		self.onFirstExecBegin.append(self.selectionChanged)
+
+	def setTitleByProtocol(self):
+		if self.protocol == "xmltv":
+			self.setTitle("CrossEPG - XMLTV providers")
+		elif self.protocol == "opentv":
+			self.setTitle("CrossEPG - OpenTV providers")
+		elif self.protocol == "xepgdb":
+			self.setTitle("CrossEPG - XEPGDB providers")
+		elif self.protocol == "scripts":
+			self.setTitle("CrossEPG - Scripts providers")
+
+	def buildList(self):
+		self.list = []
+		i = 0
+		for provider in self.providers[0]:
+			if self.providers[2][i] == self.protocol:
+				self.list.append(self.buildListEntry(provider, self.providers[1][i], self.config.providers.count(provider) > 0))
+			i += 1
+
+		self["list"].setList(self.list)
+
+	def buildListEntry(self, name, description, enabled):
+		if enabled:
+			pixmap = LoadPixmap(cached=True, path="%s/images/enabled.png" % os.path.dirname(sys.modules[__name__].__file__));
+			return((description, pixmap, name))
+		else:
+			return((description, None, name))
+		
+	def selectionChanged(self):
+		if len(self.list) == 0:
+			return
+
+		index = self["list"].getIndex()
+		provider = self.list[index][2]
+		if self.config.providers.count(provider) > 0:
+			self["key_green"].setText(_("Disable"))
+		else:
+			self["key_green"].setText(_("Enable"))
+
+	def switchState(self):
+		if len(self.list) == 0:
+			return
+
+		index = self["list"].getIndex()
+		provider = self.list[index][2]
+		if self.config.providers.count(provider) > 0:
+			self.config.providers.remove(provider)
+		else:
+			self.config.providers.append(provider)
+
+		self.buildList()
+		self["list"].setIndex(index)
+
+	def download(self):
+		if len(self.list) == 0:
+			return
+
+		index = self["list"].getIndex()
+		self.session.openWithCallback(self.downloadCallback, CrossEPG_Downloader, [self.list[index][2],])
+
+	def downloadCallback(self, ret):
+		if ret:
+			if self.patchtype != 3:
+				self.converter()
+			else:
+				self.loader()
+
+	def converter(self):
+		self.session.openWithCallback(self.converterCallback, CrossEPG_Converter)
+
+	def converterCallback(self, ret):
+		if ret and self.patchtype != -1:
+			self.loader()
+
+	def loader(self):
+		self.session.open(CrossEPG_Loader)
+
+	def quit(self):
+		self.config.save()
+		self.close()
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_setup.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_setup.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepg_setup.py	(revision 8762)
@@ -0,0 +1,298 @@
+from enigma import getDesktop
+
+from Screens.Screen import Screen
+from Screens.MessageBox import MessageBox
+
+from Components.config import KEY_LEFT, KEY_RIGHT, KEY_HOME, KEY_END, KEY_0, ConfigYesNo, ConfigSelection, ConfigClock
+from Components.ConfigList import ConfigList
+from Components.Button import Button
+from Components.Label import Label
+from Components.Harddisk import harddiskmanager
+from Components.PluginComponent import plugins
+from Components.ActionMap import NumberActionMap
+
+from Tools.Directories import resolveFilename, SCOPE_PLUGINS
+
+from Plugins.Plugin import PluginDescriptor
+
+from crossepglib import *
+from crossepg_locale import _
+from crossepg_auto import crossepg_auto
+
+from time import *
+
+class CrossEPG_Setup(Screen):
+	def __init__(self, session):
+		if (getDesktop(0).size().width() < 800):
+			skin = "%s/skins/setup_sd.xml" % (os.path.dirname(sys.modules[__name__].__file__))
+		else:
+			skin = "%s/skins/setup_hd.xml" % (os.path.dirname(sys.modules[__name__].__file__))
+		f = open(skin, "r")
+		self.skin = f.read()
+		f.close()
+		Screen.__init__(self, session)
+
+		patchtype = getEPGPatchType()
+		if patchtype == 0 or patchtype == 1 or patchtype == 3:
+			self.fastpatch = True
+		else:
+			self.fastpatch = False
+		
+		self.session = session
+
+		self.config = CrossEPG_Config()
+		self.config.load()
+
+		self.lamedbs = self.config.getAllLamedbs()
+
+		self.lamedbs_desc = []
+		self.mountpoint = []
+		self.mountdescription = []
+		self.automatictype = []
+
+		self.show_extension = self.config.show_extension
+		self.show_plugin = self.config.show_plugin
+
+		# make devices entries
+		if self.config.isQBOXHD():
+			self.mountdescription.append(_("Internal flash"))
+			self.mountpoint.append("/var/crossepg/data")
+
+		for partition in harddiskmanager.getMountedPartitions():
+			if (partition.mountpoint != '/') and (partition.mountpoint != ''): # and self.isMountedInRW(partition.mountpoint):
+				self.mountpoint.append(partition.mountpoint + "/crossepg")
+
+				if partition.description != '':
+					self.mountdescription.append(partition.description)
+				else:
+					self.mountdescription.append(partition.mountpoint)
+				
+		if not self.config.isQBOXHD():		# for other decoders we add internal flash as last entry (it's unsuggested)
+			self.mountdescription.append(_("Internal flash (unsuggested)"))
+			self.mountpoint.append(self.config.home_directory + "/data")
+			
+		# make lamedb entries
+		for lamedb in self.lamedbs:
+			if lamedb == "lamedb":
+				self.lamedbs_desc.append(_("main lamedb"))
+			else:
+				self.lamedbs_desc.append(lamedb.replace("lamedb.", "").replace(".", " "))
+				
+		# make automatic type entries
+		self.automatictype.append(_("disabled"))
+		self.automatictype.append(_("once a day"))
+		self.automatictype.append(_("every hour (only in standby)"))
+
+		self.list = []
+		self["config"] = ConfigList(self.list, session = self.session)
+		self["config"].onSelectionChanged.append(self.setInfo)
+		self["information"] = Label("")
+		self["key_red"] = Button(_("Back"))
+		self["key_green"] = Button()
+		self["key_yellow"] = Button()
+		self["key_blue"] = Button("")
+		self["config_actions"] = NumberActionMap(["SetupActions", "InputAsciiActions", "KeyboardInputActions", "ColorActions"],
+		{
+			"red": self.quit,
+			"cancel": self.quit,
+			"left": self.keyLeft,
+			"right": self.keyRight,
+			"home": self.keyHome,
+			"end": self.keyEnd,
+			"1": self.keyNumberGlobal,
+			"2": self.keyNumberGlobal,
+			"3": self.keyNumberGlobal,
+			"4": self.keyNumberGlobal,
+			"5": self.keyNumberGlobal,
+			"6": self.keyNumberGlobal,
+			"7": self.keyNumberGlobal,
+			"8": self.keyNumberGlobal,
+			"9": self.keyNumberGlobal,
+			"0": self.keyNumberGlobal
+		}, -1) # to prevent left/right overriding the listbox
+
+		self.makeList()
+
+	def showWarning(self):	
+		self.session.open(MessageBox, _("PLEASE READ!\nNo disk found. An hard drive or an usb pen is HARDLY SUGGESTED. If you still want use your internal flash pay attention to:\n(1) If you don't have enough free space your box may completely block and you need to flash it again\n(2) Many write operations on your internal flash may damage your flash memory"), type = MessageBox.TYPE_ERROR)
+	
+	def keyLeft(self):
+		self["config"].handleKey(KEY_LEFT)
+		self.update()
+		#self.setInfo()
+
+	def keyRight(self):
+		self["config"].handleKey(KEY_RIGHT)
+		self.update()
+		#self.setInfo()
+
+	def keyHome(self):
+		self["config"].handleKey(KEY_HOME)
+		self.update()
+		#self.setInfo()
+
+	def keyEnd(self):
+		self["config"].handleKey(KEY_END)
+		self.update()
+		#self.setInfo()
+
+	def keyNumberGlobal(self, number):
+		self["config"].handleKey(KEY_0 + number)
+		self.update()
+		#self.setInfo()
+
+	def makeList(self):
+		self.list = []
+
+		device_default = None
+		i = 0
+		for mountpoint in self.mountpoint:
+			if mountpoint == self.config.db_root:
+				device_default = self.mountdescription[i]
+			i += 1
+
+		# default device is really important... if miss a default we force it on first entry and update now the main config
+		if device_default == None:
+			self.config.db_root = self.mountpoint[0]
+			device_default = self.mountdescription[0]
+			
+		lamedb_default = _("main lamedb")
+		if self.config.lamedb != "lamedb":
+			lamedb_default = self.config.lamedb.replace("lamedb.", "").replace(".", " ")
+
+		scheduled_default = None
+		if self.config.download_standby_enabled:
+			scheduled_default = _("every hour (only in standby)")
+		elif self.config.download_daily_enabled:
+			scheduled_default = _("once a day")
+		else:
+			scheduled_default = _("disabled")
+
+		self.list.append((_("Storage device"), ConfigSelection(self.mountdescription, device_default)))
+		if len(self.lamedbs_desc) > 1:
+			self.list.append((_("Preferred lamedb"), ConfigSelection(self.lamedbs_desc, lamedb_default)))
+
+		self.list.append((_("Enable csv import"), ConfigYesNo(self.config.csv_import_enabled > 0)))
+		self.list.append((_("Force epg reload on boot"), ConfigYesNo(self.config.force_load_on_boot > 0)))
+		self.list.append((_("Download on tune"), ConfigYesNo(self.config.download_tune_enabled > 0)))
+		self.list.append((_("Scheduled download"), ConfigSelection(self.automatictype, scheduled_default)))
+
+		if self.config.download_daily_enabled:
+			ttime = localtime()
+			ltime = (ttime[0], ttime[1], ttime[2], self.config.download_daily_hours, self.config.download_daily_minutes, ttime[5], ttime[6], ttime[7], ttime[8])
+			self.list.append((_("Scheduled download at"), ConfigClock(mktime(ltime))))
+
+		if not self.fastpatch:
+			self.list.append((_("Reboot after a scheduled download"), ConfigYesNo(self.config.download_daily_reboot > 0)))
+			self.list.append((_("Reboot after a manual download"), ConfigYesNo(self.config.download_manual_reboot > 0)))
+		self.list.append((_("Show as plugin"), ConfigYesNo(self.config.show_plugin > 0)))
+		self.list.append((_("Show as extension"), ConfigYesNo(self.config.show_extension > 0)))
+
+		self["config"].setList(self.list)
+		self.setInfo()
+
+	def update(self):
+		redraw = False
+		self.config.db_root = self.mountpoint[self.list[0][1].getIndex()]
+		
+		i = 1
+		if len(self.lamedbs_desc) > 1:
+			self.config.lamedb = self.lamedbs[self.list[i][1].getIndex()]
+			i += 1
+
+		self.config.csv_import_enabled = int(self.list[i][1].getValue())
+		self.config.force_load_on_boot = int(self.list[i+1][1].getValue())
+		self.config.download_tune_enabled = int(self.list[i+2][1].getValue())
+
+		dailycache = self.config.download_daily_enabled
+		standbycache = self.config.download_standby_enabled
+		if self.list[i+3][1].getIndex() == 0:
+			self.config.download_daily_enabled = 0
+			self.config.download_standby_enabled = 0
+		elif self.list[i+3][1].getIndex() == 1:
+			self.config.download_daily_enabled = 1
+			self.config.download_standby_enabled = 0
+		else:
+			self.config.download_daily_enabled = 0
+			self.config.download_standby_enabled = 1
+
+		if dailycache != self.config.download_daily_enabled or standbycache != self.config.download_standby_enabled:
+			redraw = True
+
+		i += 4
+		if dailycache:
+			self.config.download_daily_hours = self.list[i][1].getValue()[0]
+			self.config.download_daily_minutes = self.list[i][1].getValue()[1]
+			i += 1
+
+		if not self.fastpatch:
+			self.config.download_daily_reboot = int(self.list[i][1].getValue())
+			self.config.download_manual_reboot = int(self.list[i+1][1].getValue())
+			i += 2
+
+		self.config.show_plugin = int(self.list[i][1].getValue())
+		self.config.show_extension = int(self.list[i+1][1].getValue())
+
+		if redraw:
+			self.makeList()
+
+	def setInfo(self):
+		index = self["config"].getCurrentIndex()
+		if len(self.lamedbs_desc) <= 1 and index > 0:
+			index += 1
+		if self.config.download_daily_enabled == 0 and index > 5:
+			index += 1
+		if self.fastpatch and index > 6:
+			index += 2
+
+		if index == 0:
+			self["information"].setText(_("Drive where you save data.\nThe drive MUST be mounted in rw"))
+		elif index == 1:
+			self["information"].setText(_("Lamedb used for epg.dat conversion.\nThis option doesn't work with crossepg patch v2"))
+		elif index == 2:
+			self["information"].setText(_("Import *.csv and *.bin from %s/import or %s/import\n(*.bin are binaries with a csv as stdout)") % (self.config.db_root, self.config.home_directory))
+		elif index == 3:
+			self["information"].setText(_("Reload epg at every boot.\nNormally it's not necessary but recover epg after an enigma2 crash"))
+		elif index == 4:
+			self["information"].setText(_("Only for opentv providers.\nIf you zap on channel used from a provider it download the epg in background"))
+		elif index == 5:
+			if self.config.download_standby_enabled:
+				self["information"].setText(_("When the decoder is in standby opentv providers will be automatically downloaded every hour.\nXMLTV providers will be always downloaded only once a day"))
+			elif self.config.download_daily_enabled:
+				self["information"].setText(_("Download epg once a day"))
+			else:
+				self["information"].setText(_("Scheduled download disabled"))
+		elif index == 6:
+			self["information"].setText(_("Time for scheduled daily download"))
+		elif index == 7:
+			self["information"].setText(_("Automatically reboot the decoder after a scheduled download"))
+		elif index == 8:
+			self["information"].setText(_("Automatically reboot the decoder after a manual download"))
+		elif index == 9:
+			self["information"].setText(_("Show crossepg in plugin menu"))
+		elif index == 10:
+			self["information"].setText(_("Show crossepg in extensions menu"))
+		
+	def quit(self):
+		self.config.last_full_download_timestamp = 0
+		self.config.last_partial_download_timestamp = 0
+		self.config.configured = 1
+		self.config.save()
+		if self.show_extension != self.config.show_extension or self.show_plugin != self.config.show_plugin:
+			for plugin in plugins.getPlugins(PluginDescriptor.WHERE_PLUGINMENU):
+				if plugin.name == "CrossEPG Downloader":
+					plugins.removePlugin(plugin)
+				
+			for plugin in plugins.getPlugins(PluginDescriptor.WHERE_EXTENSIONSMENU):
+				if plugin.name == "CrossEPG Downloader":
+					plugins.removePlugin(plugin)
+				
+			plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
+			
+		crossepg_auto.forcePoll()
+		
+		if self.config.db_root == self.config.home_directory + "/data" and not self.config.isQBOXHD():
+			self.showWarning()
+			
+		self.close()
+
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepglib.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepglib.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/crossepglib.py	(revision 8762)
@@ -0,0 +1,643 @@
+from enigma import *
+from crossepg_locale import _
+from Tools.Directories import crawlDirectory, pathExists, createDir
+from types import *
+
+import sys, traceback
+import os
+import re
+import time
+import new
+import _enigma
+
+# return value
+# -1 none
+# 0 simple epgcache.load() patch
+# 1 edg nemesis patch
+# 2 oudeis patch
+# 3 crossepg v2.1 patch
+def getEPGPatchType():
+	try:
+		xepgpatch = new.instancemethod(_enigma.eEPGCache_crossepgImportEPGv21,None,eEPGCache)
+		return 3
+	except Exception, e:
+		pass
+
+	try:
+		epgpatch = new.instancemethod(_enigma.eEPGCache_load,None,eEPGCache)
+		return 0
+	except Exception, e:
+		pass
+		
+	try:
+		edgpatch = new.instancemethod(_enigma.eEPGCache_reloadEpg,None,eEPGCache)
+		return 1
+	except Exception, e:
+		pass
+		
+	try:
+		oudeispatch = new.instancemethod(_enigma.eEPGCache_importEvent,None,eEPGCache)
+		return 2
+	except Exception, e:
+		pass
+
+	return -1
+
+class CrossEPG_Config:
+	providers = [ ]
+	db_root = "/hdd/crossepg"
+	lamedb = "lamedb"
+	home_directory = ""
+	
+	force_load_on_boot = 0
+	download_daily_enabled = 0
+	download_daily_hours = 4
+	download_daily_minutes = 0
+	download_daily_reboot = 1
+	download_tune_enabled = 0
+	download_standby_enabled = 0
+	download_manual_reboot = 0
+	csv_import_enabled = 0
+	show_plugin = 1
+	show_extension = 1
+	last_partial_download_timestamp = 0
+	last_full_download_timestamp = 0
+	configured = 0
+	
+	def __init__(self):
+		if pathExists("/usr/crossepg"):
+			self.home_directory = "/usr/crossepg"
+		elif pathExists("/var/crossepg"):
+			self.home_directory = "/var/crossepg"
+		else:
+			print "[CrossEPG_Config] ERROR!! CrossEPG binaries non found"
+			
+	def load(self):
+		try:
+			f = open("%s/crossepg.config" % (self.home_directory), "r")
+		except Exception, e:
+			#print "[CrossEPG_Config] %s" % (e)
+			return
+			
+		commentRe = re.compile(r"#(.*)")
+		entryRe = re.compile(r"(.*)=(.*)")
+		
+		for line in f.readlines(): 
+			try:
+				comment = re.findall(commentRe, line)
+				if not comment:
+					entry = re.findall(entryRe, line)
+					if entry:
+						key = entry[0][0].strip()
+						value = entry[0][1].strip()
+						if key == "db_root":
+							self.db_root = value
+						if key == "lamedb":
+							self.lamedb = value
+						elif key == "providers":
+							self.providers = []
+							tmp = value.split("|")
+							for p in tmp:
+								if len(p) > 0 and os.path.exists("%s/providers/%s.conf" % (self.home_directory, p)):
+									self.providers.append(p)
+						elif key == "force_load_on_boot":
+							self.force_load_on_boot = int(value);
+						elif key == "download_daily_enabled":
+							self.download_daily_enabled = int(value);
+						elif key == "download_daily_hours":
+							self.download_daily_hours = int(value);
+						elif key == "download_daily_minutes":
+							self.download_daily_minutes = int(value);
+						elif key == "download_tune_enabled":
+							self.download_tune_enabled = int(value);
+						elif key == "download_daily_reboot":
+							self.download_daily_reboot = int(value);
+						elif key == "download_manual_reboot":
+							self.download_manual_reboot = int(value);
+						elif key == "download_standby_enabled":
+							self.download_standby_enabled = int(value);
+						elif key == "last_partial_download_timestamp":
+							self.last_partial_download_timestamp = int(value);
+						elif key == "last_full_download_timestamp":
+							self.last_full_download_timestamp = int(value);
+						elif key == "csv_import_enabled":
+							self.csv_import_enabled = int(value);
+						elif key == "show_plugin":
+							self.show_plugin = int(value);
+						elif key == "show_extension":
+							self.show_extension = int(value);
+						elif key == "configured":
+							self.configured = int(value);
+			except Exception:
+				pass
+
+		f.close()
+		
+	def save(self):
+		try:
+			f = open("%s/crossepg.config" % (self.home_directory), "w")
+		except Exception, e:
+			print "[CrossEPG_Config] %s" % (e)
+			return
+
+		tmp = []
+		for p in self.providers:
+			if len(p) > 0:
+					tmp.append(p)
+		self.providers = tmp
+		
+		f.write("db_root=%s\n" % (self.db_root))
+		f.write("lamedb=%s\n" % (self.lamedb))
+		f.write("providers=%s\n" % ("|".join(self.providers)))
+		f.write("force_load_on_boot=%d\n" % (self.force_load_on_boot))
+		f.write("download_daily_enabled=%d\n" % (self.download_daily_enabled))
+		f.write("download_daily_hours=%d\n" % (self.download_daily_hours))
+		f.write("download_daily_minutes=%d\n" % (self.download_daily_minutes))
+		f.write("download_daily_reboot=%d\n" % (self.download_daily_reboot))
+		f.write("download_tune_enabled=%d\n" % (self.download_tune_enabled))
+		f.write("download_manual_reboot=%d\n" % (self.download_manual_reboot))
+		f.write("download_standby_enabled=%d\n" % (self.download_standby_enabled))
+		f.write("last_full_download_timestamp=%d\n" % (self.last_full_download_timestamp))
+		f.write("last_partial_download_timestamp=%d\n" % (self.last_partial_download_timestamp))
+		f.write("csv_import_enabled=%d\n" % (self.csv_import_enabled))
+		f.write("show_plugin=%d\n" % (self.show_plugin))
+		f.write("show_extension=%d\n" % (self.show_extension))
+		f.write("configured=%d\n" % (self.configured))
+		
+		f.close()
+		
+	def getChannelProtocol(self, provider):
+		try:
+			f = open("%s/providers/%s.conf" % (self.home_directory, provider), "r")
+		except Exception, e:
+			print "[CrossEPG_Config] %s" % (e)
+			return
+			
+		proto = re.compile(r"protocol=(.*)")
+		for line in f.readlines(): 
+			zproto = re.findall(proto, line)
+			if zproto:
+				f.close()
+				return zproto[0].strip()
+		
+		f.close()
+		return ""
+	
+	def getChannelID(self, provider):
+		try:
+			f = open("%s/providers/%s.conf" % (self.home_directory, provider), "r")
+		except Exception, e:
+			print "[CrossEPG_Config] %s" % (e)
+			return
+			
+		nid = -1;
+		tsid = -1;
+		sid = -1;
+		namespace = -1;
+		nidRe = re.compile(r"nid=(.*)")
+		tsidRe = re.compile(r"tsid=(.*)")
+		sidRe = re.compile(r"sid=(.*)")
+		namespaceRe = re.compile(r"namespace=(.*)")
+		
+		for line in f.readlines(): 
+			znid = re.findall(nidRe, line)
+			if znid:
+				nid = int(znid[0])
+			zsid = re.findall(sidRe, line)
+			if zsid:
+				sid = int(zsid[0])
+			ztsid = re.findall(tsidRe, line)	
+			if ztsid:
+				tsid = int(ztsid[0])
+			znamespace = re.findall(namespaceRe, line)	
+			if znamespace:
+				namespace = int(znamespace[0]);
+		
+		if nid == -1 or sid == -1 or tsid == -1:
+			return
+		
+		f.close()
+		return "1:0:1:%X:%X:%X:%X:0:0:0:" % (sid, tsid, nid, namespace)
+		
+	def getAllProviders(self):
+		providers = list()
+		providersdesc = list()
+		providersproto = list()
+		cfiles = crawlDirectory("%s/providers/" % (self.home_directory), ".*\.conf$")
+		for cfile in cfiles:
+			providers.append(cfile[1].replace(".conf", ""))
+			
+		providers.sort()
+		
+		for provider in providers:
+			try:
+				descadded = False
+				protoadded = False
+				f = open("%s/providers/%s.conf" % (self.home_directory, provider), "r")
+				desc = re.compile(r"description=(.*)")
+				proto = re.compile(r"protocol=(.*)")
+				for line in f.readlines(): 
+					zdesc = re.findall(desc, line)
+					if zdesc:
+						providersdesc.append(zdesc[0].strip())
+						descadded = True
+
+					zproto = re.findall(proto, line)
+					if zproto:
+						providersproto.append(zproto[0].strip())
+						protoadded = True
+
+					if descadded and protoadded:
+						break
+
+				f.close()
+				
+				if not descadded:
+					providersdesc.append(provider)
+
+				if not protoadded:
+					providersproto.append(None)
+					
+			except Exception, e:
+				print "[CrossEPG_Config] %s" % (e)
+				providersdesc.append(provider)
+				providersproto.append(None)
+				
+		ret = [providers, providersdesc, providersproto]
+		return ret
+			
+	def getAllLamedbs(self):
+		lamedbs = list()
+		cfiles = crawlDirectory("/etc/enigma2/", "^lamedb.*")
+		for cfile in cfiles:
+			lamedbs.append(cfile[1])
+			
+		return lamedbs
+	
+	def isQBOXHD(self):
+		try:
+			ret = False
+			f = open("/proc/stb/info/model", "r")
+			model = f.read().strip()
+			if model == "qboxhd" or model == "qboxhd-mini":
+				ret = True
+			f.close()
+			return ret
+		except Exception, e:
+			return False
+		
+	def deleteLog(self):
+		try:
+			os.unlink(self.db_root + "/crossepg.log")
+		except Exception, e:
+			print e
+
+class CrossEPG_Wrapper:
+	EVENT_READY			= 0
+	EVENT_OK			= 1
+	EVENT_START			= 2
+	EVENT_END			= 3
+	EVENT_QUIT			= 4
+	EVENT_ERROR			= 5
+	EVENT_ACTION			= 6
+	EVENT_STATUS			= 7
+	EVENT_PROGRESS			= 8
+	EVENT_PROGRESSONOFF		= 9
+	EVENT_CHANNEL			= 10
+	EVENT_STARTTIME			= 11
+	EVENT_LENGTH			= 12
+	EVENT_NAME			= 13
+	EVENT_DESCRIPTION		= 14
+	EVENT_FILE			= 15
+	EVENT_URL			= 16
+	
+	INFO_HEADERSDB_SIZE		= 50
+	INFO_DESCRIPTORSDB_SIZE	= 51
+	INFO_INDEXESDB_SIZE		= 52
+	INFO_ALIASESDB_SIZE		= 53
+	INFO_TOTAL_SIZE			= 54
+	INFO_CHANNELS_COUNT		= 55
+	INFO_EVENTS_COUNT		= 56
+	INFO_HASHES_COUNT		= 57
+	INFO_CREATION_TIME		= 58
+	INFO_UPDATE_TIME		= 59
+	INFO_VERSION			= 60
+	
+	CMD_DOWNLOADER	= 0
+	CMD_CONVERTER	= 1
+	CMD_INFO		= 2
+	CMD_IMPORTER	= 3
+
+	home_directory = ""
+
+	def __init__(self):
+		self.cmd = eConsoleAppContainer()
+		self.cache = None
+		self.callbackList = []
+		self.type = 0
+		self.maxSize = "0 byte"
+		
+		versionlist = getEnigmaVersionString().split("-");
+		
+		self.oldapi = False
+		try:
+			if len(versionlist) >= 3:
+				self.version = int(versionlist[0]+versionlist[1]+versionlist[2])
+				if self.version < 20100716:
+					self.oldapi = True
+		except Exception:
+			pass
+				
+		config = CrossEPG_Config()
+		if config.isQBOXHD():
+				self.oldapi = True
+		
+		if pathExists("/usr/crossepg"):
+			self.home_directory = "/usr/crossepg"
+		elif pathExists("/var/crossepg"):
+			self.home_directory = "/var/crossepg"
+		else:
+			print "[CrossEPG_Config] ERROR!! CrossEPG binaries non found"
+		
+	def init(self, cmd, dbdir):
+		if not pathExists(dbdir):
+			if not createDir(dbdir):
+				dbdir = "/hdd/crossepg"
+				
+		if cmd == self.CMD_DOWNLOADER:
+			x = "%s/crossepg_downloader -r -d %s" % (self.home_directory, dbdir)
+		elif cmd == self.CMD_CONVERTER:
+			x = "%s/crossepg_dbconverter -r -d %s" % (self.home_directory, dbdir)
+		elif cmd == self.CMD_INFO:
+			x = "%s/crossepg_dbinfo -r -d %s" % (self.home_directory, dbdir)
+		elif cmd == self.CMD_IMPORTER:
+			importdir = "%s/import/" % (dbdir)
+			x = "%s/crossepg_importer -r -i %s -d %s" % (self.home_directory, importdir, dbdir)
+		else:
+			print "[CrossEPG_Wrapper] unknow command on init"
+			return
+			
+		print "[CrossEPG_Wrapper] executing %s" % (x)
+		self.cmd.appClosed.append(self.__cmdFinished)
+		self.cmd.dataAvail.append(self.__cmdData)
+		if self.cmd.execute(x):
+			self.cmdFinished(-1)
+			
+	def __cmdFinished(self, retval):
+		self.__callCallbacks(self.EVENT_QUIT)
+		self.cmd.appClosed.remove(self.__cmdFinished)
+		self.cmd.dataAvail.remove(self.__cmdData)
+
+	def __cmdData(self, data):
+		if self.cache is None:
+			self.cache = data
+		else:
+			self.cache += data
+
+		if '\n' in data:
+			splitcache = self.cache.split('\n')
+			if self.cache[-1] == '\n':
+				iteration = splitcache
+				self.cache = None
+			else:
+				iteration = splitcache[:-1]
+				self.cache = splitcache[-1]
+			for mydata in iteration:
+				if mydata != '':
+					self.__parseLine(mydata)
+
+	def __parseLine(self, data):
+		if data.find("CHANNEL ") == 0:
+			self.__callCallbacks(self.EVENT_CHANNEL, data[7:])
+		elif data.find("STARTTIME ") == 0:
+			self.__callCallbacks(self.EVENT_STARTTIME, int(data[10:]))
+		elif data.find("LENGTH ") == 0:
+			self.__callCallbacks(self.EVENT_LENGTH, int(data[7:]))
+		elif data.find("NAME ") == 0:
+			self.__callCallbacks(self.EVENT_NAME, data[5:])
+		elif data.find("DESCRIPTION ") == 0:
+			self.__callCallbacks(self.EVENT_DESCRIPTION, data[12:].replace("\\n", "\n"))
+		elif data == "READY":
+			print "[CrossEPG_Wrapper] <- READY"
+			self.__callCallbacks(self.EVENT_READY, None)
+		elif data == "START":
+			print "[CrossEPG_Wrapper] <- START"
+			self.__callCallbacks(self.EVENT_START, None)
+		elif data == "END":
+			print "[CrossEPG_Wrapper] <- END"
+			self.__callCallbacks(self.EVENT_END, None)
+		elif data == "OK":
+			print "[CrossEPG_Wrapper] <- OK"
+			self.__callCallbacks(self.EVENT_OK, None)
+		elif data.find("ERROR ") == 0:
+			ttype = data[5:]
+			self.__callCallbacks(self.EVENT_ERROR, data[6:])
+		elif data.find("TYPE ") == 0:
+			ttype = data[5:]
+			print "[CrossEPG_Wrapper] <- TYPE %s" % (ttype)
+			if ttype == "READ CHANNELS":
+				self.type = 0;
+				self.__callCallbacks(self.EVENT_ACTION, _("Reading channels"))
+			elif ttype == "READ TITLES":
+				self.type = 1;
+				self.__callCallbacks(self.EVENT_ACTION, _("Reading titles"))
+			elif ttype == "PARSE TITLES":
+				self.type = 2;
+				self.__callCallbacks(self.EVENT_ACTION, _("Parsing titles"))
+			elif ttype == "READ SUMMARIES":
+				self.type = 3;
+				self.__callCallbacks(self.EVENT_ACTION, _("Reading summaries"))
+			elif ttype == "PARSE SUMMARIES":
+				self.type = 4;
+				self.__callCallbacks(self.EVENT_ACTION, _("Parsing summaries"))
+			elif ttype == "DOWNLOADING CHANNELS LIST":
+				self.type = 5;
+				self.__callCallbacks(self.EVENT_ACTION, _("Downloading channels list"))
+			elif ttype == "DEFLATING CHANNELS LIST":
+				self.type = 6;
+				self.__callCallbacks(self.EVENT_ACTION, _("Deflating channels list"))
+			elif ttype == "PARSING CHANNELS LIST":
+				self.type = 7;
+				self.__callCallbacks(self.EVENT_ACTION, _("Parsing channels list"))
+			elif ttype == "DOWNLOADING EVENTS":
+				self.type = 8;
+				self.__callCallbacks(self.EVENT_ACTION, _("Downloading events"))
+			elif ttype == "DEFLATING EVENTS":
+				self.type = 9;
+				self.__callCallbacks(self.EVENT_ACTION, _("Deflating events"))
+			elif ttype == "PARSING EVENTS":
+				self.type = 10;
+				self.__callCallbacks(self.EVENT_ACTION, _("Parsing events"))
+			elif ttype == "DOWNLOADING XEPGDB":
+				self.type = 11;
+				self.__callCallbacks(self.EVENT_ACTION, _("Downloading XEPGDB"))
+			elif ttype == "PARSING XEPGDB":
+				self.type = 12;
+				self.__callCallbacks(self.EVENT_ACTION, _("Merging XEPGDB"))
+			elif ttype == "DEFLATING XEPGDB":
+				self.type = 13;
+				self.__callCallbacks(self.EVENT_ACTION, _("Deflating XEPGDB"))
+			elif ttype == "RUNNING SCRIPT":
+				self.type = 14;
+				self.__callCallbacks(self.EVENT_ACTION, _("Running script"))
+			elif ttype.find("RUNNING CSCRIPT ") == 0:
+				self.type = 14;
+				self.__callCallbacks(self.EVENT_ACTION, _("Running script") + " " + data[21:])
+				
+		elif data.find("CHANNELS ") == 0:
+			self.__callCallbacks(self.EVENT_STATUS, _("%s channels") % (data[9:]))
+		elif data.find("SIZE ") == 0:
+			if self.type == 1 or self.type == 3:
+				self.maxSize = data[5:]
+				self.__callCallbacks(self.EVENT_STATUS, _("Read %s") % (data[5:]))
+			else:
+				self.__callCallbacks(self.EVENT_STATUS, _("%s of %s") % (data[5:], self.maxSize))
+		elif data.find("PROGRESS ") == 0:
+			if data[9:] == "ON":
+				self.__callCallbacks(self.EVENT_PROGRESSONOFF, True)
+			elif data[9:] == "OFF":
+				self.__callCallbacks(self.EVENT_PROGRESSONOFF, False)
+			else:
+				self.__callCallbacks(self.EVENT_PROGRESS, int(data[9:]))
+		elif data.find("FILE ") == 0:
+			self.__callCallbacks(self.EVENT_FILE, data[5:])
+		elif data.find("URL ") == 0:
+			self.__callCallbacks(self.EVENT_URL, data[4:])
+		elif data.find("VERSION ") == 0:
+			self.__callCallbacks(self.INFO_VERSION, data[8:])
+		elif data.find("HEADERSDB_SIZE ") == 0:
+			self.__callCallbacks(self.INFO_HEADERSDB_SIZE, data[15:])
+		elif data.find("DESCRIPTORSDB_SIZE ") == 0:
+			self.__callCallbacks(self.INFO_DESCRIPTORSDB_SIZE, data[19:])
+		elif data.find("INDEXESDB_SIZE ") == 0:
+			self.__callCallbacks(self.INFO_INDEXESDB_SIZE, data[15:])
+		elif data.find("ALIASESDB_SIZE ") == 0:
+			self.__callCallbacks(self.INFO_ALIASESDB_SIZE, data[15:])
+		elif data.find("TOTAL_SIZE ") == 0:
+			self.__callCallbacks(self.INFO_TOTAL_SIZE, data[11:])
+		elif data.find("CHANNELS_COUNT ") == 0:
+			self.__callCallbacks(self.INFO_CHANNELS_COUNT, data[15:])
+		elif data.find("EVENTS_COUNT ") == 0:
+			self.__callCallbacks(self.INFO_EVENTS_COUNT, data[13:])
+		elif data.find("HASHES_COUNT ") == 0:
+			self.__callCallbacks(self.INFO_HASHES_COUNT, data[13:])
+		elif data.find("CREATION_TIME ") == 0:
+			self.__callCallbacks(self.INFO_CREATION_TIME, data[14:])
+		elif data.find("UPDATE_TIME ") == 0:
+			self.__callCallbacks(self.INFO_UPDATE_TIME, data[12:])
+		elif data.find("LOGTEXT ") == 0:
+			self.__callCallbacks(self.EVENT_STATUS, data[8:])
+
+	def __callCallbacks(self, event, param = None):
+		for callback in self.callbackList:
+			callback(event, param)
+
+	def addCallback(self, callback):
+		self.callbackList.append(callback)
+
+	def delCallback(self, callback):
+		self.callbackList.remove(callback)
+
+	def running(self):
+		return self.cmd.running()
+		
+	def lamedb(self, value):
+		print "[CrossEPG_Wrapper] -> LAMEDB %s" % (value)
+		cmd = "LAMEDB %s\n" % (value)
+		if self.oldapi:
+			self.cmd.write(cmd, len(cmd))
+		else:
+			self.cmd.write(cmd)
+		
+	def epgdat(self, value):
+		print "[CrossEPG_Wrapper] -> EPGDAT %s" % (value)
+		cmd = "EPGDAT %s\n" % (value)
+		if self.oldapi:
+			self.cmd.write(cmd, len(cmd))
+		else:
+			self.cmd.write(cmd)
+			
+	def demuxer(self, value):
+		print "[CrossEPG_Wrapper] -> DEMUXER %s" % (value)
+		cmd = "DEMUXER %s\n" % (value)
+		if self.oldapi:
+			self.cmd.write(cmd, len(cmd))
+		else:
+			self.cmd.write(cmd)
+
+	def download(self, provider):
+		print "[CrossEPG_Wrapper] -> DOWNLOAD %s" % (provider)
+		cmd = "DOWNLOAD %s\n" % (provider)
+		if self.oldapi:
+			self.cmd.write(cmd, len(cmd))
+		else:
+			self.cmd.write(cmd)
+		
+	def convert(self):
+		print "[CrossEPG_Wrapper] -> CONVERT"
+		self.__callCallbacks(self.EVENT_ACTION, _("Converting data"))
+		self.__callCallbacks(self.EVENT_STATUS, "")
+		if self.oldapi:
+			self.cmd.write("CONVERT\n", 8)
+		else:
+			self.cmd.write("CONVERT\n")
+		
+	def importx(self):
+		print "[CrossEPG_Wrapper] -> IMPORT"
+		if self.oldapi:
+			self.cmd.write("IMPORT\n", 7)
+		else:
+			self.cmd.write("IMPORT\n")
+		
+	def text(self):
+		print "[CrossEPG_Wrapper] -> TEXT"
+		self.__callCallbacks(self.EVENT_ACTION, _("Loading data"))
+		self.__callCallbacks(self.EVENT_STATUS, "")
+		if self.oldapi:
+			self.cmd.write("TEXT\n", 5)
+		else:
+			self.cmd.write("TEXT\n")
+			
+	def stop(self):
+		print "[CrossEPG_Wrapper] -> STOP"
+		if self.oldapi:
+			self.cmd.write("STOP\n", 5)
+		else:
+			self.cmd.write("STOP\n")
+
+	def save(self):
+		print "[CrossEPG_Wrapper] -> SAVE"
+		self.__callCallbacks(self.EVENT_ACTION, _("Saving data"))
+		self.__callCallbacks(self.EVENT_STATUS, "")
+		if self.oldapi:
+			self.cmd.write("SAVE\n", 5)
+		else:
+			self.cmd.write("SAVE\n")
+
+	def wait(self):
+		print "[CrossEPG_Wrapper] -> WAIT"
+		if self.oldapi:
+			self.cmd.write("WAIT\n", 5)
+		else:
+			self.cmd.write("WAIT\n")
+
+	def quit(self):
+		print "[CrossEPG_Wrapper] -> QUIT"
+		if self.oldapi:
+			self.cmd.write("QUIT\n", 5)
+		else:
+			self.cmd.write("QUIT\n")
+
+	def open(self):
+		print "[CrossEPG_Wrapper] -> OPEN"
+		if self.oldapi:
+			self.cmd.write("OPEN\n", 5)
+		else:
+			self.cmd.write("OPEN\n")
+
+	def close(self):
+		print "[CrossEPG_Wrapper] -> CLOSE"
+		if self.oldapi:
+			self.cmd.write("CLOSE\n", 6)
+		else:
+			self.cmd.write("CLOSE\n")
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/plugin.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/plugin.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/plugin.py	(revision 8762)
@@ -0,0 +1,47 @@
+from crossepglib import CrossEPG_Config
+from crossepg_main import crossepg_main
+from crossepg_locale import _
+from Plugins.Plugin import PluginDescriptor
+
+def setup(menuid, **kwargs):
+	if menuid == "setup":
+		return [("CrossEPG", crossepg_main.setup, "crossepg", None)]
+	else:
+		return []
+
+def Plugins(**kwargs):
+	config = CrossEPG_Config()
+	config.load()
+	plugins = list()
+	if config.show_plugin == 1 and config.show_extension == 1:
+		plugins.append(PluginDescriptor(name="CrossEPG Downloader",
+										description=_("An EPG downloader"),
+										where = [ PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU ],
+										fnc = crossepg_main.downloader))
+	elif config.show_extension == 1:
+		plugins.append(PluginDescriptor(name="CrossEPG Downloader",
+										description=_("An EPG downloader"),
+										where = PluginDescriptor.WHERE_EXTENSIONSMENU,
+										fnc = crossepg_main.downloader))
+	elif config.show_plugin == 1:
+		plugins.append(PluginDescriptor(name="CrossEPG Downloader",
+										description=_("An EPG downloader"),
+										where = PluginDescriptor.WHERE_PLUGINMENU,
+										fnc = crossepg_main.downloader))
+	
+	if config.isQBOXHD():
+		plugins.append(PluginDescriptor(name="CrossEPG",
+										description=_("CrossEPG setup panel"),
+										where = PluginDescriptor.WHERE_PLUGINMENU,
+										fnc = crossepg_main.setup))
+	else:
+		plugins.append(PluginDescriptor(name="CrossEPG",
+										description=_("CrossEPG setup panel"),
+										where = PluginDescriptor.WHERE_MENU,
+										fnc = setup))
+										
+	plugins.append(PluginDescriptor(name="CrossEPG Auto",
+									description = _("CrossEPG automatic actions"),
+									where = PluginDescriptor.WHERE_SESSIONSTART,
+									fnc = crossepg_main.autostart))
+	return plugins;
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/about_hd.xml
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/about_hd.xml	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/about_hd.xml	(revision 8762)
@@ -0,0 +1,15 @@
+<screen position="360,150" size="560,400" title="CrossEPG - About">
+	<widget name="about" position="10,10" size="460,360" font="Regular;15" />
+	<widget name="rytec_pix" position="480,200" size="70,70" />
+	<widget name="krkadoni_pix" position="480,290" size="70,22" />
+
+	<widget name="key_red" position="0,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_green" position="140,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_yellow" position="280,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_blue" position="420,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	
+	<ePixmap name="red" pixmap="skin_default/buttons/red.png" position="0,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="green" pixmap="skin_default/buttons/green.png" position="140,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="yellow" pixmap="skin_default/buttons/yellow.png" position="280,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="blue" pixmap="skin_default/buttons/blue.png" position="420,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+</screen>
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/about_sd.xml
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/about_sd.xml	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/about_sd.xml	(revision 8762)
@@ -0,0 +1,15 @@
+<screen position="80,100" size="560,400" title="CrossEPG - About">
+	<widget name="about" position="10,10" size="460,360" font="Regular;15" />
+	<widget name="rytec_pix" position="480,200" size="70,70" />
+	<widget name="krkadoni_pix" position="480,290" size="70,22" />
+
+	<widget name="key_red" position="0,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_green" position="140,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_yellow" position="280,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_blue" position="420,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	
+	<ePixmap name="red" pixmap="skin_default/buttons/red.png" position="0,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="green" pixmap="skin_default/buttons/green.png" position="140,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="yellow" pixmap="skin_default/buttons/yellow.png" position="280,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="blue" pixmap="skin_default/buttons/blue.png" position="420,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+</screen>
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/downloader_hd.xml
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/downloader_hd.xml	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/downloader_hd.xml	(revision 8762)
@@ -0,0 +1,6 @@
+<screen position="530,590" size="600,70" title="CrossEPG" flags="wfNoBorder">
+	<widget name="background" position="0,0" size="600,80" zPosition="-1" />
+	<widget name="action" halign="center" valign="center" position="65,10" size="520,20" font="Regular;16" />
+	<widget name="status" halign="center" valign="center" position="65,30" size="520,20" font="Regular;16" />
+	<widget name="progress" position="65,55" size="520,5" borderWidth="1" />
+</screen>
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/downloader_sd.xml
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/downloader_sd.xml	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/downloader_sd.xml	(revision 8762)
@@ -0,0 +1,6 @@
+<screen position="330,450" size="350,70" title="CrossEPG" flags="wfNoBorder">
+	<widget name="background" position="0,0" size="350,80" zPosition="-1" />
+	<widget name="action" halign="center" valign="center" position="65,10" size="270,20" font="Regular;15" />
+	<widget name="status" halign="center" valign="center" position="65,30" size="270,20" font="Regular;15" />
+	<widget name="progress" position="65,55" size="270,5" borderWidth="1" />
+</screen>
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/info_hd.xml
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/info_hd.xml	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/info_hd.xml	(revision 8762)
@@ -0,0 +1,23 @@
+<screen position="360,150" size="560,400" title="CrossEPG - DB Info">
+	<widget name="version" position="10,10" size="540,25" font="Regular;20" />
+	<widget name="create" position="10,40" size="540,25" font="Regular;20" />
+	<widget name="last_update" position="10,70" size="540,25" font="Regular;20" />
+	<widget name="headersdb_size" position="10,100" size="540,25" font="Regular;20" />
+	<widget name="descriptorsdb_size" position="10,130" size="540,25" font="Regular;20" />
+	<widget name="indexesdb_size" position="10,160" size="540,25" font="Regular;20" />
+	<widget name="aliasesdb_size" position="10,190" size="540,25" font="Regular;20" />
+	<widget name="total_size" position="10,220" size="540,25" font="Regular;20" />
+	<widget name="channels_count" position="10,250" size="540,25" font="Regular;20" />
+	<widget name="events_count" position="10,280" size="540,25" font="Regular;20" />
+	<widget name="hashes_count" position="10,310" size="540,25" font="Regular;20" />
+
+	<widget name="key_red" position="0,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_green" position="140,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_yellow" position="280,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_blue" position="420,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	
+	<ePixmap name="red" pixmap="skin_default/buttons/red.png" position="0,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="green" pixmap="skin_default/buttons/green.png" position="140,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="yellow" pixmap="skin_default/buttons/yellow.png" position="280,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="blue" pixmap="skin_default/buttons/blue.png" position="420,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+</screen>
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/info_sd.xml
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/info_sd.xml	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/info_sd.xml	(revision 8762)
@@ -0,0 +1,23 @@
+<screen position="80,100" size="560,400" title="CrossEPG - DB Info">
+	<widget name="version" position="10,10" size="540,25" font="Regular;20" />
+	<widget name="create" position="10,40" size="540,25" font="Regular;20" />
+	<widget name="last_update" position="10,70" size="540,25" font="Regular;20" />
+	<widget name="headersdb_size" position="10,100" size="540,25" font="Regular;20" />
+	<widget name="descriptorsdb_size" position="10,130" size="540,25" font="Regular;20" />
+	<widget name="indexesdb_size" position="10,160" size="540,25" font="Regular;20" />
+	<widget name="aliasesdb_size" position="10,190" size="540,25" font="Regular;20" />
+	<widget name="total_size" position="10,220" size="540,25" font="Regular;20" />
+	<widget name="channels_count" position="10,250" size="540,25" font="Regular;20" />
+	<widget name="events_count" position="10,280" size="540,25" font="Regular;20" />
+	<widget name="hashes_count" position="10,310" size="540,25" font="Regular;20" />
+
+	<widget name="key_red" position="0,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_green" position="140,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_yellow" position="280,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_blue" position="420,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	
+	<ePixmap name="red" pixmap="skin_default/buttons/red.png" position="0,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="green" pixmap="skin_default/buttons/green.png" position="140,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="yellow" pixmap="skin_default/buttons/yellow.png" position="280,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="blue" pixmap="skin_default/buttons/blue.png" position="420,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+</screen>
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/menu_hd.xml
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/menu_hd.xml	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/menu_hd.xml	(revision 8762)
@@ -0,0 +1,13 @@
+<screen position="360,170" size="560,360" title="CrossEPG">
+	<widget source="list" render="Listbox" position="0,0" size="560,360" scrollbarMode="showOnDemand">
+		<convert type="TemplatedMultiContent">
+			{"template": [
+				MultiContentEntryPixmapAlphaTest(pos = (12, 4), size = (32, 32), png = 0),
+				MultiContentEntryText(pos = (58, 5), size = (440, 38), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_TOP, text = 1),
+				],
+				"fonts": [gFont("Regular", 22)],
+				"itemHeight": 40
+			}
+		</convert>
+	</widget>	
+</screen>
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/menu_sd.xml
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/menu_sd.xml	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/menu_sd.xml	(revision 8762)
@@ -0,0 +1,13 @@
+<screen position="80,120" size="560,360" title="CrossEPG">
+	<widget source="list" render="Listbox" position="0,0" size="560,360" scrollbarMode="showOnDemand">
+		<convert type="TemplatedMultiContent">
+			{"template": [
+				MultiContentEntryPixmapAlphaTest(pos = (12, 4), size = (32, 32), png = 0),
+				MultiContentEntryText(pos = (58, 5), size = (440, 38), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_TOP, text = 1),
+				],
+				"fonts": [gFont("Regular", 22)],
+				"itemHeight": 40
+			}
+		</convert>
+	</widget>	
+</screen>
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/providers_hd.xml
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/providers_hd.xml	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/providers_hd.xml	(revision 8762)
@@ -0,0 +1,23 @@
+<screen position="360,150" size="560,400" title="CrossEPG - Providers">
+	<widget source="list" render="Listbox" position="0,0" size="560,360" scrollbarMode="showOnDemand">
+		<convert type="TemplatedMultiContent">
+			{"template": [
+				MultiContentEntryText(pos = (12, 1), size = (440, 32), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_TOP, text = 0),
+				MultiContentEntryPixmapAlphaTest(pos = (480, 0), size = (40, 40), png = 1),
+				],
+				"fonts": [gFont("Regular", 18)],
+				"itemHeight": 30
+			}
+		</convert>
+	</widget>
+
+	<widget name="key_red" position="0,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_green" position="140,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_yellow" position="280,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_blue" position="420,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	
+	<ePixmap name="red" pixmap="skin_default/buttons/red.png" position="0,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="green" pixmap="skin_default/buttons/green.png" position="140,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="yellow" pixmap="skin_default/buttons/yellow.png" position="280,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="blue" pixmap="skin_default/buttons/blue.png" position="420,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+</screen>
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/providers_sd.xml
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/providers_sd.xml	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/providers_sd.xml	(revision 8762)
@@ -0,0 +1,23 @@
+<screen position="80,100" size="560,400" title="CrossEPG - Providers">
+	<widget source="list" render="Listbox" position="0,0" size="560,360" scrollbarMode="showOnDemand">
+		<convert type="TemplatedMultiContent">
+			{"template": [
+				MultiContentEntryText(pos = (12, 1), size = (440, 32), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_TOP, text = 0),
+				MultiContentEntryPixmapAlphaTest(pos = (480, 0), size = (40, 40), png = 1),
+				],
+				"fonts": [gFont("Regular", 18)],
+				"itemHeight": 30
+			}
+		</convert>
+	</widget>
+
+	<widget name="key_red" position="0,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_green" position="140,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_yellow" position="280,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_blue" position="420,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	
+	<ePixmap name="red" pixmap="skin_default/buttons/red.png" position="0,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="green" pixmap="skin_default/buttons/green.png" position="140,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="yellow" pixmap="skin_default/buttons/yellow.png" position="280,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="blue" pixmap="skin_default/buttons/blue.png" position="420,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+</screen>
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/setup_hd.xml
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/setup_hd.xml	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/setup_hd.xml	(revision 8762)
@@ -0,0 +1,14 @@
+<screen position="360,150" size="560,400" title="CrossEPG - Configuration">
+	<widget name="config" position="5,5" size="550,250" scrollbarMode="showOnDemand" zPosition="1"/>
+	<widget name="information" position="5,250" size="550,100" halign="center" valign="center" font="Regular;18" />
+
+	<widget name="key_red" position="0,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_green" position="140,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_yellow" position="280,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_blue" position="420,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	
+	<ePixmap name="red" pixmap="skin_default/buttons/red.png" position="0,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="green" pixmap="skin_default/buttons/green.png" position="140,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="yellow" pixmap="skin_default/buttons/yellow.png" position="280,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="blue" pixmap="skin_default/buttons/blue.png" position="420,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+</screen>
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/setup_sd.xml
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/setup_sd.xml	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/skins/setup_sd.xml	(revision 8762)
@@ -0,0 +1,14 @@
+<screen position="80,100" size="560,400" title="CrossEPG - Configuration">
+	<widget name="config" position="5,5" size="550,250" scrollbarMode="showOnDemand" zPosition="1"/>
+	<widget name="information" position="5,250" size="550,100" halign="center" valign="center" font="Regular;18" />
+	
+	<widget name="key_red" position="0,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_green" position="140,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_yellow" position="280,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	<widget name="key_blue" position="420,360" size="140,40" valign="center" halign="center" zPosition="5" transparent="1" foregroundColor="white" font="Regular;18"/>
+	
+	<ePixmap name="red" pixmap="skin_default/buttons/red.png" position="0,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="green" pixmap="skin_default/buttons/green.png" position="140,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="yellow" pixmap="skin_default/buttons/yellow.png" position="280,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+	<ePixmap name="blue" pixmap="skin_default/buttons/blue.png" position="420,360" size="140,40" zPosition="4" transparent="1" alphatest="on"/>
+</screen>
Index: /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/version.py
===================================================================
--- /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/version.py	(revision 8762)
+++ /ipk/source.sh4/swapepg_crossepg_0_61/var/swap/extensions/CrossEPG/version.py	(revision 8762)
@@ -0,0 +1,1 @@
+version = "0.6.1 (svn 241)"
