Merlin Music Player and iDream - initial checkin
authorDr.Best <dr_best@users.schwerkraft.elitedvb.net>
Sat, 27 Feb 2010 12:52:53 +0000 (12:52 +0000)
committerDr.Best <dr_best@users.schwerkraft.elitedvb.net>
Sat, 27 Feb 2010 12:52:53 +0000 (12:52 +0000)
27 files changed:
Makefile.am
configure.ac
merlinmusicplayer/CONTROL/control [new file with mode: 0644]
merlinmusicplayer/Makefile.am [new file with mode: 0755]
merlinmusicplayer/meta/Makefile.am [new file with mode: 0755]
merlinmusicplayer/meta/merlinmusicplayer.jpg [new file with mode: 0644]
merlinmusicplayer/meta/plugin_merlinmusicplayer.xml [new file with mode: 0755]
merlinmusicplayer/src/Makefile.am [new file with mode: 0755]
merlinmusicplayer/src/MerlinMusicPlayer.png [new file with mode: 0644]
merlinmusicplayer/src/__init__.py [new file with mode: 0644]
merlinmusicplayer/src/iDream.png [new file with mode: 0644]
merlinmusicplayer/src/images/Makefile.am [new file with mode: 0755]
merlinmusicplayer/src/images/dvr.png [new file with mode: 0644]
merlinmusicplayer/src/images/dvr_pau.png [new file with mode: 0644]
merlinmusicplayer/src/images/dvr_pl.png [new file with mode: 0644]
merlinmusicplayer/src/images/dvr_rep.png [new file with mode: 0644]
merlinmusicplayer/src/images/dvr_shuf.png [new file with mode: 0644]
merlinmusicplayer/src/images/mmp3p.png [new file with mode: 0644]
merlinmusicplayer/src/images/mmp3pHD.png [new file with mode: 0644]
merlinmusicplayer/src/images/mmpborderHD.png [new file with mode: 0644]
merlinmusicplayer/src/images/no_coverArt.png [new file with mode: 0644]
merlinmusicplayer/src/images/placeholder1.png [new file with mode: 0644]
merlinmusicplayer/src/images/progressbar.png [new file with mode: 0644]
merlinmusicplayer/src/merlinmp3player/Makefile.am [new file with mode: 0644]
merlinmusicplayer/src/merlinmp3player/merlinmp3player.cpp [new file with mode: 0644]
merlinmusicplayer/src/merlinmp3player/merlinmp3player.h [new file with mode: 0644]
merlinmusicplayer/src/plugin.py [new file with mode: 0644]

index 7f2f94b..ace41bd 100644 (file)
@@ -25,6 +25,7 @@ SUBDIRS = \
        letterbox \
        logomanager \
        mediadownloader \
+       merlinmusicplayer \
        meteoitalia \
        mosaic \
        moviecut \
index 5a60f95..eacec0f 100644 (file)
@@ -14,6 +14,8 @@ if test x"${have_e2_includes}" = "xyes"; then
        TUXBOX_APPS_DVB
        TUXBOX_APPS_LIB_PKGCONFIG(ENIGMA2,enigma2)
        TUXBOX_APPS_LIB_PKGCONFIG(SIGC,sigc++-1.2)
+       _TUXBOX_APPS_LIB_PKGCONFIG_OPTIONAL(GSTREAMER,gstreamer,HAVE_GSTREAMER)
+       _TUXBOX_APPS_LIB_PKGCONFIG_OPTIONAL(GSTREAMERPBUTILS,gstreamer-pbutils,HAVE_GSTSTREAMERPBUTILS)
        AC_DEFINE(HAVE_E2_INCLUDES, 1,[Define if enigm2 includes are available])
        CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions"
        LDFLAGS="$LDFLAGS -pthread $PYTHON_LDFLAGS"
@@ -143,6 +145,12 @@ mediadownloader/meta/Makefile
 mediadownloader/po/Makefile
 mediadownloader/src/Makefile
 
+merlinmusicplayer/Makefile
+merlinmusicplayer/src/Makefile
+merlinmusicplayer/src/images/Makefile
+merlinmusicplayer/src/merlinmp3player/Makefile
+
+
 meteoitalia/Makefile
 meteoitalia/meta/Makefile
 meteoitalia/src/Makefile
diff --git a/merlinmusicplayer/CONTROL/control b/merlinmusicplayer/CONTROL/control
new file mode 100644 (file)
index 0000000..6a77bc2
--- /dev/null
@@ -0,0 +1,10 @@
+Package: enigma2-plugin-extensions-merlinmusicplayer
+Version: 1.1
+Description: Merlin Music Player  and iDream (music management)
+Architecture: mipsel
+Section: extra
+Priority: optional
+Maintainer: Dr. Best <dr.best@dreambox-tools.info>
+Homepage: http://www.dreambox-tools.info
+Depends: enigma2(>2.6git20090615), twisted-web, python-mutagen, python-sqlite3
+Source: http://enigma2-plugins.schwerkraft.elitedvb.net/
diff --git a/merlinmusicplayer/Makefile.am b/merlinmusicplayer/Makefile.am
new file mode 100755 (executable)
index 0000000..7a31bf0
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = meta src
diff --git a/merlinmusicplayer/meta/Makefile.am b/merlinmusicplayer/meta/Makefile.am
new file mode 100755 (executable)
index 0000000..c9f8622
--- /dev/null
@@ -0,0 +1,5 @@
+installdir = $(datadir)/meta/
+
+dist_install_DATA = plugin_merlinmusicplayer.xml
+
+EXTRA_DIST = merlinmusicplayer.jpg
diff --git a/merlinmusicplayer/meta/merlinmusicplayer.jpg b/merlinmusicplayer/meta/merlinmusicplayer.jpg
new file mode 100644 (file)
index 0000000..99371e7
Binary files /dev/null and b/merlinmusicplayer/meta/merlinmusicplayer.jpg differ
diff --git a/merlinmusicplayer/meta/plugin_merlinmusicplayer.xml b/merlinmusicplayer/meta/plugin_merlinmusicplayer.xml
new file mode 100755 (executable)
index 0000000..381744b
--- /dev/null
@@ -0,0 +1,24 @@
+<default>
+         <prerequisites>
+                    <tag type="Multimedia" />
+         </prerequisites>
+          <info language="en">
+                    <author>Dr.Best</author>
+                    <name>Merlin Music Player</name>
+                    <packagename>enigma2-plugin-extensions-merlinmusicplayer</packagename>
+                    <shortdescription>Merlin Music Player and iDream</shortdescription>
+                    <description>Manage your music files in a database, play it with Merlin Music Player</description>
+                    <screenshot src="http://www.dreamboxupdate.com/preview/merlinmusicplayer.jpg" />               
+          </info>
+          <info language="de">
+                    <author>Dr.Best</author>
+                    <name>Partnerbox</name>
+                    <packagename>enigma2-plugin-extensions-merlinmusicplayer</packagename>
+                    <shortdescription>Merlin Music Player und iDream</shortdescription>
+                    <description>Datenbankverwaltung für Musikdateien, Abspielen mit Merlin Music Player</description>
+                    <screenshot src="http://www.dreamboxupdate.com/preview/merlinmusicplayer.jpg" />   
+          </info>
+         <files type="package"> <!-- without version, without .ipk -->
+               <file type="package" name="enigma2-plugin-extensions-merlinmusicplayer" />
+         </files>
+</default>
diff --git a/merlinmusicplayer/src/Makefile.am b/merlinmusicplayer/src/Makefile.am
new file mode 100755 (executable)
index 0000000..d2813d0
--- /dev/null
@@ -0,0 +1,7 @@
+SUBDIRS = images merlinmp3player
+
+installdir = /usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer
+
+install_PYTHON = *.py merlinmp3player/merlinmp3player.so
+
+install_DATA = *.png 
diff --git a/merlinmusicplayer/src/MerlinMusicPlayer.png b/merlinmusicplayer/src/MerlinMusicPlayer.png
new file mode 100644 (file)
index 0000000..ad519dc
Binary files /dev/null and b/merlinmusicplayer/src/MerlinMusicPlayer.png differ
diff --git a/merlinmusicplayer/src/__init__.py b/merlinmusicplayer/src/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/merlinmusicplayer/src/iDream.png b/merlinmusicplayer/src/iDream.png
new file mode 100644 (file)
index 0000000..cb0fa32
Binary files /dev/null and b/merlinmusicplayer/src/iDream.png differ
diff --git a/merlinmusicplayer/src/images/Makefile.am b/merlinmusicplayer/src/images/Makefile.am
new file mode 100755 (executable)
index 0000000..4a4b218
--- /dev/null
@@ -0,0 +1,3 @@
+installdir = /usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images
+
+install_DATA = *.png
diff --git a/merlinmusicplayer/src/images/dvr.png b/merlinmusicplayer/src/images/dvr.png
new file mode 100644 (file)
index 0000000..58f0a31
Binary files /dev/null and b/merlinmusicplayer/src/images/dvr.png differ
diff --git a/merlinmusicplayer/src/images/dvr_pau.png b/merlinmusicplayer/src/images/dvr_pau.png
new file mode 100644 (file)
index 0000000..0aac511
Binary files /dev/null and b/merlinmusicplayer/src/images/dvr_pau.png differ
diff --git a/merlinmusicplayer/src/images/dvr_pl.png b/merlinmusicplayer/src/images/dvr_pl.png
new file mode 100644 (file)
index 0000000..79ac9d1
Binary files /dev/null and b/merlinmusicplayer/src/images/dvr_pl.png differ
diff --git a/merlinmusicplayer/src/images/dvr_rep.png b/merlinmusicplayer/src/images/dvr_rep.png
new file mode 100644 (file)
index 0000000..f3f7ddb
Binary files /dev/null and b/merlinmusicplayer/src/images/dvr_rep.png differ
diff --git a/merlinmusicplayer/src/images/dvr_shuf.png b/merlinmusicplayer/src/images/dvr_shuf.png
new file mode 100644 (file)
index 0000000..570c1a8
Binary files /dev/null and b/merlinmusicplayer/src/images/dvr_shuf.png differ
diff --git a/merlinmusicplayer/src/images/mmp3p.png b/merlinmusicplayer/src/images/mmp3p.png
new file mode 100644 (file)
index 0000000..30d271b
Binary files /dev/null and b/merlinmusicplayer/src/images/mmp3p.png differ
diff --git a/merlinmusicplayer/src/images/mmp3pHD.png b/merlinmusicplayer/src/images/mmp3pHD.png
new file mode 100644 (file)
index 0000000..bc45882
Binary files /dev/null and b/merlinmusicplayer/src/images/mmp3pHD.png differ
diff --git a/merlinmusicplayer/src/images/mmpborderHD.png b/merlinmusicplayer/src/images/mmpborderHD.png
new file mode 100644 (file)
index 0000000..74e4650
Binary files /dev/null and b/merlinmusicplayer/src/images/mmpborderHD.png differ
diff --git a/merlinmusicplayer/src/images/no_coverArt.png b/merlinmusicplayer/src/images/no_coverArt.png
new file mode 100644 (file)
index 0000000..debc902
Binary files /dev/null and b/merlinmusicplayer/src/images/no_coverArt.png differ
diff --git a/merlinmusicplayer/src/images/placeholder1.png b/merlinmusicplayer/src/images/placeholder1.png
new file mode 100644 (file)
index 0000000..87f9e56
Binary files /dev/null and b/merlinmusicplayer/src/images/placeholder1.png differ
diff --git a/merlinmusicplayer/src/images/progressbar.png b/merlinmusicplayer/src/images/progressbar.png
new file mode 100644 (file)
index 0000000..c1a9d19
Binary files /dev/null and b/merlinmusicplayer/src/images/progressbar.png differ
diff --git a/merlinmusicplayer/src/merlinmp3player/Makefile.am b/merlinmusicplayer/src/merlinmp3player/Makefile.am
new file mode 100644 (file)
index 0000000..7da3d32
--- /dev/null
@@ -0,0 +1,15 @@
+OBJS = merlinmp3player.cpp
+
+-include $(OBJS:.cpp=.d)
+
+merlinmp3player.so: merlinmp3player.h
+
+
+       $(CXX) $(CPPFLAGS) -MD $(CXXFLAGS) $(ENIGMA2_CFLAGS) $(SIGC_CFLAGS) $(GSTREAMER_CFLAGS) $(GSTREAMERPBUTILS_CFLAGS) $(GSTREAMER_LDFLAGS) $(GSTREAMERPBUTILS_LDFLAGS) \
+       $(PYTHON_CPPFLAGS) $(DEFS) -I$(top_srcdir)/include -Wall -lgstbase-0.10 -W $(OBJS) -shared -fPIC -Wl,-soname,merlinmp3player.so -o merlinmp3player.so \
+       $(LDFLAGS)
+
+all: merlinmp3player.so
+
+CLEANFILES = merlinmp3player.so merlinmp3player.d
+
diff --git a/merlinmusicplayer/src/merlinmp3player/merlinmp3player.cpp b/merlinmusicplayer/src/merlinmp3player/merlinmp3player.cpp
new file mode 100644 (file)
index 0000000..0f25e41
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+  MerlinMP3Player E2
+
+  (c) 2010 by Dr. Best  <dr.best@dreambox-tools.info>
+  Support: www.dreambox-tools.info
+
+*/
+
+#include <lib/base/eerror.h>
+#include <lib/base/object.h>
+#include <lib/base/ebase.h>
+#include <string>
+#include "merlinmp3player.h"
+#include <lib/service/service.h>
+#include <lib/base/init_num.h>
+#include <lib/base/init.h>
+#include <gst/gst.h>
+
+// eServiceFactoryMerlinMP3Player
+
+eServiceFactoryMerlinMP3Player::eServiceFactoryMerlinMP3Player()
+{
+       ePtr<eServiceCenter> sc;
+       
+       eServiceCenter::getPrivInstance(sc);
+       if (sc)
+       {
+               std::list<std::string> extensions;
+               extensions.push_back("mp3");
+               sc->addServiceFactory(eServiceFactoryMerlinMP3Player::id, this, extensions);
+       }
+       m_service_info = new eStaticServiceMP3Info();
+
+}
+
+eServiceFactoryMerlinMP3Player::~eServiceFactoryMerlinMP3Player()
+{
+       ePtr<eServiceCenter> sc;
+       
+       eServiceCenter::getPrivInstance(sc);
+       if (sc)
+               sc->removeServiceFactory(eServiceFactoryMerlinMP3Player::id);
+}
+
+DEFINE_REF(eServiceFactoryMerlinMP3Player)
+
+       // iServiceHandler
+RESULT eServiceFactoryMerlinMP3Player::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
+{
+               // check resources...
+       ptr = new eServiceMerlinMP3Player(ref);
+       return 0;
+}
+
+RESULT eServiceFactoryMerlinMP3Player::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
+{
+       ptr=0;
+       return -1;
+}
+
+RESULT eServiceFactoryMerlinMP3Player::list(const eServiceReference &, ePtr<iListableService> &ptr)
+{
+       ptr=0;
+       return -1;
+}
+
+RESULT eServiceFactoryMerlinMP3Player::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
+{
+       ptr = m_service_info;
+       return 0;
+}
+
+RESULT eServiceFactoryMerlinMP3Player::offlineOperations(const eServiceReference &, ePtr<iServiceOfflineOperations> &ptr)
+{
+       ptr = 0;
+       return -1;
+}
+
+DEFINE_REF(eStaticServiceMP3Info)
+
+eStaticServiceMP3Info::eStaticServiceMP3Info()
+{
+       // nothing to to here...
+}
+
+RESULT eStaticServiceMP3Info::getName(const eServiceReference &ref, std::string &name)
+{
+       size_t last = ref.path.rfind('/');
+       if (last != std::string::npos)
+               name = ref.path.substr(last+1);
+       else
+               name = ref.path;
+       return 0;
+}
+
+int eStaticServiceMP3Info::getLength(const eServiceReference &ref)
+{
+       return -1;
+}
+
+// eServiceMerlinMP3Player
+
+eServiceMerlinMP3Player::eServiceMerlinMP3Player(eServiceReference ref):  m_ref(ref), m_pump(eApp, 1)
+{
+       m_filename = m_ref.path.c_str();
+       CONNECT(m_pump.recv_msg, eServiceMerlinMP3Player::gstPoll);
+       m_state = stIdle;
+       eDebug("eServiceMerlinMP3Player construct!");
+
+       GstElement *sink;
+       GstElement *source;
+       GstElement *decoder;
+
+       m_gst_pipeline = gst_pipeline_new ("audio-player");
+       if (!m_gst_pipeline)
+               eWarning("failed to create pipeline");
+
+       source   = gst_element_factory_make ("filesrc", "file reader");
+       decoder   = gst_element_factory_make ("mad", "MP3 decoder");
+       sink     = gst_element_factory_make ("alsasink", "ALSA output");
+       if (m_gst_pipeline && source && decoder && sink)
+       {
+               g_object_set (G_OBJECT (source), "location", m_filename.c_str(), NULL);
+               gst_bin_add_many (GST_BIN (m_gst_pipeline), source, decoder, sink, NULL);
+               gst_element_link_many (source, decoder, sink, NULL);
+               gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_pipeline)), gstBusSyncHandler, this);
+               gst_element_set_state (m_gst_pipeline, GST_STATE_PLAYING);
+       }
+       else
+       {
+               if (m_gst_pipeline)
+                       gst_object_unref(GST_OBJECT(m_gst_pipeline));
+               if (source)
+                       gst_object_unref(GST_OBJECT(source));
+               if (decoder)
+                       gst_object_unref(GST_OBJECT(decoder));
+               if (sink)
+                       gst_object_unref(GST_OBJECT(sink));
+               eDebug("no playing...!");
+       }
+       eDebug("eServiceMerlinMP3Player::using gstreamer with location=%s", m_filename.c_str());
+}
+
+eServiceMerlinMP3Player::~eServiceMerlinMP3Player()
+{
+       if (m_state == stRunning)
+               stop();
+
+       if (m_gst_pipeline)
+       {
+               gst_object_unref (GST_OBJECT (m_gst_pipeline));
+               eDebug("eServiceMerlinMP3Player destruct!");
+       }
+}
+
+DEFINE_REF(eServiceMerlinMP3Player);   
+
+RESULT eServiceMerlinMP3Player::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
+{
+       connection = new eConnection((iPlayableService*)this, m_event.connect(event));
+       return 0;
+}
+
+RESULT eServiceMerlinMP3Player::start()
+{
+       assert(m_state == stIdle);
+       
+       m_state = stRunning;
+       if (m_gst_pipeline)
+       {
+               eDebug("eServiceMerlinMP3Player::starting pipeline");
+               gst_element_set_state (m_gst_pipeline, GST_STATE_PLAYING);
+       }
+       m_event(this, evStart);
+       return 0;
+}
+
+RESULT eServiceMerlinMP3Player::stop()
+{
+       assert(m_state != stIdle);
+       if (m_state == stStopped)
+               return -1;
+       eDebug("eServiceMerlinMP3Player::stop %s", m_filename.c_str());
+       gst_element_set_state(m_gst_pipeline, GST_STATE_NULL);
+       m_state = stStopped;
+       return 0;
+}
+
+RESULT eServiceMerlinMP3Player::setTarget(int target)
+{
+       return -1;
+}
+
+RESULT eServiceMerlinMP3Player::pause(ePtr<iPauseableService> &ptr)
+{
+       ptr=this;
+       return 0;
+}
+
+RESULT eServiceMerlinMP3Player::setSlowMotion(int ratio)
+{
+       return -1;
+}
+
+RESULT eServiceMerlinMP3Player::setFastForward(int ratio)
+{
+       return -1;
+}
+  
+               // iPausableService
+RESULT eServiceMerlinMP3Player::pause()
+{
+       if (!m_gst_pipeline)
+               return -1;
+       gst_element_set_state(m_gst_pipeline, GST_STATE_PAUSED);
+       return 0;
+}
+
+RESULT eServiceMerlinMP3Player::unpause()
+{
+       if (!m_gst_pipeline)
+               return -1;
+       gst_element_set_state(m_gst_pipeline, GST_STATE_PLAYING);
+       return 0;
+}
+
+       /* iSeekableService */
+RESULT eServiceMerlinMP3Player::seek(ePtr<iSeekableService> &ptr)
+{
+       ptr = this;
+       return 0;
+}
+
+RESULT eServiceMerlinMP3Player::getLength(pts_t &pts)
+{
+       if (!m_gst_pipeline)
+               return -1;
+       if (m_state != stRunning)
+               return -1;
+       
+       GstFormat fmt = GST_FORMAT_TIME;
+       gint64 len;
+       
+       if (!gst_element_query_duration(m_gst_pipeline, &fmt, &len))
+               return -1;
+       
+               /* len is in nanoseconds. we have 90 000 pts per second. */
+       
+       pts = len / 11111;
+       return 0;
+}
+
+RESULT eServiceMerlinMP3Player::seekTo(pts_t to)
+{
+       if (!m_gst_pipeline)
+               return -1;
+
+               /* convert pts to nanoseconds */
+       gint64 time_nanoseconds = to * 11111LL;
+       if (!gst_element_seek (m_gst_pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
+               GST_SEEK_TYPE_SET, time_nanoseconds,
+               GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE))
+       {
+               eDebug("eServiceMerlinMP3Player::SEEK failed");
+               return -1;
+       }
+       return 0;
+}
+
+RESULT eServiceMerlinMP3Player::seekRelative(int direction, pts_t to)
+{
+       if (!m_gst_pipeline)
+               return -1;
+
+       pause();
+
+       pts_t ppos;
+       getPlayPosition(ppos);
+       ppos += to * direction;
+       if (ppos < 0)
+               ppos = 0;
+       seekTo(ppos);
+       
+       unpause();
+
+       return 0;
+}
+
+RESULT eServiceMerlinMP3Player::getPlayPosition(pts_t &pts)
+{
+       if (!m_gst_pipeline)
+               return -1;
+       if (m_state != stRunning)
+               return -1;
+       
+       GstFormat fmt = GST_FORMAT_TIME;
+       gint64 len;
+       
+       if (!gst_element_query_position(m_gst_pipeline, &fmt, &len))
+               return -1;
+       
+               /* len is in nanoseconds. we have 90 000 pts per second. */
+       pts = len / 11111;
+       return 0;
+}
+
+RESULT eServiceMerlinMP3Player::setTrickmode(int trick)
+{
+               /* trickmode currently doesn't make any sense for us. */
+       return -1;
+}
+
+RESULT eServiceMerlinMP3Player::isCurrentlySeekable()
+{
+       return 1;
+}
+
+RESULT eServiceMerlinMP3Player::info(ePtr<iServiceInformation>&i)
+{
+       i = this;
+       return 0;
+}
+
+RESULT eServiceMerlinMP3Player::getName(std::string &name)
+{
+       name = m_filename;
+       size_t n = name.rfind('/');
+       if (n != std::string::npos)
+               name = name.substr(n + 1);
+       return 0;
+}
+
+int eServiceMerlinMP3Player::getInfo(int w)
+{
+       return resNA;
+}
+
+std::string eServiceMerlinMP3Player::getInfoString(int w)
+{
+       return "";
+}
+
+void eServiceMerlinMP3Player::gstBusCall(GstBus *bus, GstMessage *msg)
+{
+       switch (GST_MESSAGE_TYPE (msg))
+       {
+               case GST_MESSAGE_EOS:
+                       m_event((iPlayableService*)this, evEOF);
+                       break;
+               case GST_MESSAGE_STATE_CHANGED:
+               {
+                       if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_pipeline))
+                               break;
+                       GstState old_state, new_state;
+                       gst_message_parse_state_changed(msg, &old_state, &new_state, NULL);
+                       if(old_state == new_state)
+                               break;
+                       eDebug("eServiceMerlinMP3Player::state transition %s -> %s", gst_element_state_get_name(old_state), gst_element_state_get_name(new_state));
+                       break;
+               }
+               case GST_MESSAGE_ERROR:
+               {
+                       gchar *debug;
+                       GError *err;
+                       gst_message_parse_error (msg, &err, &debug);
+                       g_free (debug);
+                       eWarning("Gstreamer error: %s", err->message);
+                       g_error_free(err);
+                       break;
+               }
+               default:
+                       break;
+       }
+}
+
+GstBusSyncReply eServiceMerlinMP3Player::gstBusSyncHandler(GstBus *bus, GstMessage *message, gpointer user_data)
+{
+       eServiceMerlinMP3Player *_this = (eServiceMerlinMP3Player*)user_data;
+       _this->m_pump.send(1);
+               /* wake */
+       return GST_BUS_PASS;
+}
+
+void eServiceMerlinMP3Player::gstPoll(const int&)
+{
+       usleep(1);
+       GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (m_gst_pipeline));
+       GstMessage *message;
+       while ((message = gst_bus_pop (bus)))
+       {
+               gstBusCall(bus, message);
+               gst_message_unref (message);
+       }
+}
+
+
+eAutoInitPtr<eServiceFactoryMerlinMP3Player> init_eServiceFactoryMerlinMP3Player(eAutoInitNumbers::service+1, "eServiceFactoryMerlinMP3Player");
+
+PyMODINIT_FUNC
+initmerlinmp3player(void)
+{
+       Py_InitModule("merlinmp3player", NULL);
+}
+
diff --git a/merlinmusicplayer/src/merlinmp3player/merlinmp3player.h b/merlinmusicplayer/src/merlinmp3player/merlinmp3player.h
new file mode 100644 (file)
index 0000000..693cbbb
--- /dev/null
@@ -0,0 +1,105 @@
+#include <lib/base/message.h>
+#include <lib/service/iservice.h>
+#include <gst/gst.h>
+
+class eStaticServiceMP3Info;
+
+class eServiceFactoryMerlinMP3Player: public iServiceHandler
+{
+DECLARE_REF(eServiceFactoryMerlinMP3Player);
+public:
+       eServiceFactoryMerlinMP3Player();
+       virtual ~eServiceFactoryMerlinMP3Player();
+       enum { id = 0x1014 };
+
+               // iServiceHandler
+       RESULT play(const eServiceReference &, ePtr<iPlayableService> &ptr);
+       RESULT record(const eServiceReference &, ePtr<iRecordableService> &ptr);
+       RESULT list(const eServiceReference &, ePtr<iListableService> &ptr);
+       RESULT info(const eServiceReference &, ePtr<iStaticServiceInformation> &ptr);
+       RESULT offlineOperations(const eServiceReference &, ePtr<iServiceOfflineOperations> &ptr);
+private:
+       ePtr<eStaticServiceMP3Info> m_service_info;
+};
+
+class eStaticServiceMP3Info: public iStaticServiceInformation
+{
+       DECLARE_REF(eStaticServiceMP3Info);
+       friend class eServiceFactoryMerlinMP3Player;
+       eStaticServiceMP3Info();
+public:
+       RESULT getName(const eServiceReference &ref, std::string &name);
+       int getLength(const eServiceReference &ref);
+};
+
+typedef struct _GstElement GstElement;
+
+class eServiceMerlinMP3Player: public iPlayableService, public iPauseableService, 
+       public iServiceInformation, public iSeekableService, public Object
+{
+DECLARE_REF(eServiceMerlinMP3Player);
+public:
+       virtual ~eServiceMerlinMP3Player();
+
+               // iPlayableService
+       RESULT connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection);
+       RESULT start();
+       RESULT stop();
+       RESULT setTarget(int target);
+       
+       RESULT pause(ePtr<iPauseableService> &ptr);
+       RESULT setSlowMotion(int ratio);
+       RESULT setFastForward(int ratio);
+
+       RESULT seek(ePtr<iSeekableService> &ptr);
+       // not implemented
+       RESULT audioChannel(ePtr<iAudioChannelSelection> &ptr) { ptr = 0; return 0; };
+       RESULT audioTracks(ePtr<iAudioTrackSelection> &ptr) { ptr = 0; return 0; };
+       RESULT frontendInfo(ePtr<iFrontendInformation> &ptr) { ptr = 0; return -1; };
+       RESULT subServices(ePtr<iSubserviceList> &ptr) { ptr = 0; return -1; };
+       RESULT timeshift(ePtr<iTimeshiftService> &ptr) { ptr = 0; return -1; };
+       RESULT cueSheet(ePtr<iCueSheet> &ptr) { ptr = 0; return -1; };
+       RESULT subtitle(ePtr<iSubtitleOutput> &ptr) { ptr = 0; return -1; };
+       RESULT audioDelay(ePtr<iAudioDelay> &ptr) { ptr = 0; return -1; };
+       RESULT rdsDecoder(ePtr<iRdsDecoder> &ptr) { ptr = 0; return -1; };
+       RESULT stream(ePtr<iStreamableService> &ptr) { ptr = 0; return -1; };
+       RESULT streamed(ePtr<iStreamedService> &ptr) { ptr = 0; return -1; };
+       RESULT keys(ePtr<iServiceKeys> &ptr) { ptr = 0; return -1; };
+
+               // iPausableService
+       RESULT pause();
+       RESULT unpause();
+       
+       RESULT info(ePtr<iServiceInformation>&);
+       
+               // iSeekableService
+       RESULT getLength(pts_t &SWIG_OUTPUT);
+       RESULT seekTo(pts_t to);
+       RESULT seekRelative(int direction, pts_t to);
+       RESULT getPlayPosition(pts_t &SWIG_OUTPUT);
+       RESULT setTrickmode(int trick);
+       RESULT isCurrentlySeekable();
+       
+               // iServiceInformation
+       RESULT getName(std::string &name);
+       int getInfo(int w);
+       std::string getInfoString(int w);
+private:
+       friend class eServiceFactoryMerlinMP3Player;
+       eServiceReference m_ref;
+       std::string m_filename;
+       eServiceMerlinMP3Player(eServiceReference ref); 
+       Signal2<void,iPlayableService*,int> m_event;
+       enum
+       {
+               stIdle, stRunning, stStopped,
+       };
+       int m_state;
+       GstElement *m_gst_pipeline;
+       eFixedMessagePump<int> m_pump;
+       
+       void gstBusCall(GstBus *bus, GstMessage *msg);
+       static GstBusSyncReply gstBusSyncHandler(GstBus *bus, GstMessage *message, gpointer user_data);
+       void gstPoll(const int&);
+};
+
diff --git a/merlinmusicplayer/src/plugin.py b/merlinmusicplayer/src/plugin.py
new file mode 100644 (file)
index 0000000..387b9aa
--- /dev/null
@@ -0,0 +1,2726 @@
+#
+#  Merlin Music Player E2
+#
+#
+#  Coded by Dr.Best (c) 2010
+#  Support: www.dreambox-tools.info
+#
+#  This plugin is licensed under the Creative Commons 
+#  Attribution-NonCommercial-ShareAlike 3.0 Unported 
+#  License. To view a copy of this license, visit
+#  http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative
+#  Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
+#
+#  Alternatively, this plugin may be distributed and executed on hardware which
+#  is licensed by Dream Multimedia GmbH.
+
+#  This plugin is NOT free software. It is open source, you are allowed to
+#  modify it (if you keep the license), but it may not be commercially 
+#  distributed other than under the conditions noted above.
+#
+
+from Plugins.Plugin import PluginDescriptor
+from Screens.Screen import Screen
+from Components.ActionMap import ActionMap, NumberActionMap
+from Components.Label import Label
+from enigma import RT_VALIGN_CENTER, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, RT_HALIGN_CENTER, gFont, eListbox,ePoint, eListboxPythonMultiContent
+
+# merlin mp3 player
+import merlinmp3player
+ENIGMA_MERLINPLAYER_ID = 0x1014
+
+from Components.FileList import FileList
+from enigma import eServiceReference, eTimer
+from os import path as os_path, mkdir as os_mkdir, listdir as os_listdir, walk as os_walk
+from Components.ProgressBar import ProgressBar
+from twisted.internet import reactor, defer
+from twisted.web import client
+from twisted.web.client import HTTPClientFactory, downloadPage
+from enigma import getDesktop
+from Screens.MessageBox import MessageBox
+from Components.GUIComponent import GUIComponent
+from enigma import ePicLoad
+from xml.etree.cElementTree import fromstring as cet_fromstring
+from urllib import quote
+from Components.ScrollLabel import ScrollLabel
+from Components.AVSwitch import AVSwitch
+from Tools.Directories import fileExists, resolveFilename, SCOPE_CURRENT_SKIN
+from Tools.LoadPixmap import LoadPixmap
+from Components.Pixmap import Pixmap, MultiPixmap
+from Components.ServicePosition import ServicePositionGauge
+from Screens.InfoBarGenerics import  InfoBarSeek, InfoBarNotifications
+from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
+from enigma import iPlayableService, iServiceInformation
+from Components.Sources.StaticText import StaticText
+from Screens.ChoiceBox import ChoiceBox
+from Screens.VirtualKeyBoard import VirtualKeyBoard
+from Tools.BoundFunction import boundFunction
+from sqlite3 import dbapi2 as sqlite
+from mutagen.flac import FLAC
+from mutagen.mp3 import MP3
+from mutagen.id3 import ID3
+from mutagen.easyid3 import EasyID3
+from mutagen.easymp4 import EasyMP4
+from mutagen.oggvorbis import OggVorbis
+import datetime
+from random import shuffle, randrange
+from Components.config import config, ConfigSubsection, ConfigDirectory, ConfigYesNo, ConfigInteger, getConfigListEntry, configfile
+from Components.ConfigList import ConfigListScreen
+from Tools.HardwareInfo import HardwareInfo
+
+
+config.plugins.merlinmusicplayer = ConfigSubsection()
+config.plugins.merlinmusicplayer.hardwaredecoder = ConfigYesNo(default = True)
+config.plugins.merlinmusicplayer.startlastsonglist = ConfigYesNo(default = True)
+config.plugins.merlinmusicplayer.lastsonglistindex = ConfigInteger(-1)
+config.plugins.merlinmusicplayer.databasepath = ConfigDirectory(default = "/hdd/")
+config.plugins.merlinmusicplayer.usegoogleimage = ConfigYesNo(default = True)
+config.plugins.merlinmusicplayer.googleimagepath = ConfigDirectory(default = "/hdd/")
+config.plugins.merlinmusicplayer.usescreensaver = ConfigYesNo(default = True)
+config.plugins.merlinmusicplayer.screensaverwait = ConfigInteger(1,limits = (1, 60))
+config.plugins.merlinmusicplayer.idreamextendedpluginlist = ConfigYesNo(default = True)
+config.plugins.merlinmusicplayer.merlinmusicplayerextendedpluginlist = ConfigYesNo(default = True)
+config.plugins.merlinmusicplayer.defaultfilebrowserpath = ConfigDirectory(default = "/hdd/")
+config.plugins.merlinmusicplayer.rememberlastfilebrowserpath = ConfigYesNo(default = True)
+
+from enigma import ePythonMessagePump
+from threading import Thread, Lock
+
+class ThreadQueue:
+       def __init__(self):
+               self.__list = [ ]
+               self.__lock = Lock()
+
+       def push(self, val):
+               lock = self.__lock
+               lock.acquire()
+               self.__list.append(val)
+               lock.release()
+
+       def pop(self):
+               lock = self.__lock
+               lock.acquire()
+               ret = self.__list.pop()
+               lock.release()
+               return ret
+
+THREAD_WORKING = 1
+THREAD_FINISHED = 2
+
+class PathToDatabase(Thread):
+       def __init__(self):
+               Thread.__init__(self)
+               self.__running = False
+               self.__cancel = False
+               self.__path = None
+               self.__messages = ThreadQueue()
+               self.__messagePump = ePythonMessagePump()
+
+       def __getMessagePump(self):
+               return self.__messagePump
+
+       def __getMessageQueue(self):
+               return self.__messages
+
+       def __getRunning(self):
+               return self.__running
+
+       def Cancel(self):
+               self.__cancel = True
+
+       MessagePump = property(__getMessagePump)
+       Message = property(__getMessageQueue)
+       isRunning = property(__getRunning)
+
+       def Start(self, path):
+               if not self.__running:
+                       self.__path = path
+                       self.start()
+
+       def run(self):
+               mp = self.__messagePump
+               self.__running = True
+               self.__cancel = False
+               if self.__path:
+                       connection = OpenDatabase()
+                       connection.text_factory = str
+                       cursor = connection.cursor()
+                       counter = 0
+                       for root, subFolders, files in os_walk(self.__path):
+                               if self.__cancel:
+                                       break
+                               for filename in files:
+                                       if self.__cancel:
+                                               break
+                                       audio, isAudio, title, genre,artist,album,tracknr,track,date,length,bitrate = getID3Tags(root,filename)
+                                       if  audio:      
+                                               # 1. Artist
+                                               artistID = -1
+                                               cursor.execute("""SELECT artist_id FROM Artists WHERE artist = "%s";""" % (artist))
+                                               row = cursor.fetchone()
+                                               if row is None:
+                                                               cursor.execute("""INSERT INTO Artists (artist) VALUES("%s");""" % (artist))
+                                                               artistID = cursor.lastrowid
+                                               else:
+                                                               artistID = row[0]
+                                               # 2. Album
+                                               albumID = -1
+                                               cursor.execute("""SELECT album_id FROM Album WHERE album_text = "%s";""" % (album))
+                                               row = cursor.fetchone()
+                                               if row is None:
+                                                               cursor.execute("""INSERT INTO Album (album_text) VALUES("%s");""" % (album))
+                                                               albumID = cursor.lastrowid
+                                               else:
+                                                               albumID = row[0]
+
+                                               # 3. Genre
+                                               genreID = -1            
+                                               cursor.execute("""SELECT genre_id FROM Genre WHERE genre_text = "%s";""" % (genre))
+                                               row = cursor.fetchone()
+                                               if row is None:
+                                                               cursor.execute("""INSERT INTO Genre (genre_text) VALUES("%s");""" % (genre))
+                                                               genreID = cursor.lastrowid
+                                               else:
+                                                               genreID = row[0]
+                                                       
+                                               # 4. Songs
+                                               try:
+                                                       cursor.execute("INSERT INTO Songs (filename,title,artist_id,album_id,genre_id,tracknumber, bitrate, length, track, date) VALUES(?,?,?,?,?,?,?,?,?,?);" , (os_path.join(root,filename),title,artistID,albumID,genreID, tracknr, bitrate, length, track, date))
+                                                       self.__messages.push((THREAD_WORKING, _("%s\n added to database") % os_path.join(root,filename)))
+                                                       mp.send(0)
+                                                       counter +=1
+                                               except sqlite.IntegrityError:
+                                                       self.__messages.push((THREAD_WORKING, _("%s\n already exists in database!") % os_path.join(root,filename)))
+                                                       mp.send(0)
+                                               audio = None
+                       if not self.__cancel:
+                               connection.commit()
+                       cursor.close()  
+                       connection.close()
+                       if self.__cancel:
+                               self.__messages.push((THREAD_FINISHED, _("Process aborted.\n 0 files added to database!\nPress OK to close.") ))
+                       else:   
+                               self.__messages.push((THREAD_FINISHED, _("%d files added to database!\nPress OK to close." % counter)))
+                       mp.send(0)
+                       self.__running = False
+                       Thread.__init__(self)
+
+pathToDatabase = PathToDatabase()
+
+
+class iDreamAddToDatabase(Screen):
+       skin = """<screen name="iDreamAddToDatabase" position="center,center" size="560,320" title="Add music files to iDream database">
+                       <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
+                       <widget name="output" position="10,10" size="540,300" valign="center" halign="center" font="Regular;22" />
+                       <widget render="Label" source="key_red" position="0,0" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                       <widget render="Label" source="key_green" position="140,0" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+               </screen>"""
+       def __init__(self, session, initDir):
+               Screen.__init__(self, session)
+               self["actions"] = ActionMap(["WizardActions", "ColorActions"],
+               {
+                       "back": self.cancel,
+                       "green": self.green,
+                       "red": self.cancel,
+                       "ok": self.green,
+                       
+               }, -1)
+               self["key_red"] = StaticText(_("Cancel"))
+               self["key_green"] = StaticText("Close")
+               self["output"] = Label()
+               self.onClose.append(self.__onClose)
+               pathToDatabase.MessagePump.recv_msg.get().append(self.gotThreadMsg)     
+               if not pathToDatabase.isRunning and initDir:
+                       pathToDatabase.Start(initDir)
+
+       def gotThreadMsg(self, msg):
+               msg = pathToDatabase.Message.pop()
+               self["output"].setText(msg[1])
+               if msg[0] == THREAD_FINISHED:
+                       self["key_red"].setText("")
+       
+       def green(self):
+               self.close()
+       
+       def cancel(self):
+               if pathToDatabase.isRunning:
+                       pathToDatabase.Cancel()
+
+       def __onClose(self):
+               pathToDatabase.MessagePump.recv_msg.get().remove(self.gotThreadMsg)     
+               
+
+class myHTTPClientFactory(HTTPClientFactory):
+       def __init__(self, url, method='GET', postdata=None, headers=None,
+       agent="SHOUTcast", timeout=0, cookies=None,
+       followRedirect=1, lastModified=None, etag=None):
+               HTTPClientFactory.__init__(self, url, method=method, postdata=postdata,
+               headers=headers, agent=agent, timeout=timeout, cookies=cookies,followRedirect=followRedirect)
+
+def sendUrlCommand(url, contextFactory=None, timeout=60, *args, **kwargs):
+       scheme, host, port, path = client._parse(url)
+       factory = myHTTPClientFactory(url, *args, **kwargs)
+       reactor.connectTCP(host, port, factory, timeout=timeout)
+       return factory.deferred
+
+
+class MethodArguments:
+       def __init__(self, method = None, arguments = None):
+               self.method = method
+               self.arguments = arguments
+
+class CacheList:
+       def __init__(self, cache = True, index = 0, listview = [], headertext = "", methodarguments = None):
+               self.cache = cache
+               self.index = index
+               self.listview = listview
+               self.headertext = headertext
+               self.methodarguments = methodarguments
+
+class Item:
+       def __init__(self, text = "", mode = 0, id = -1, navigator = False, artistID = 0, albumID = 0, title = "", artist = "", filename = "", bitrate = None, length = "", genre = "", track = "", date = "", album = "", playlistID = 0,  genreID = 0, songID = 0, join = True, PTS = None):
+               self.text = text
+               self.mode = mode
+               self.navigator = navigator
+               self.artistID = artistID
+               self.albumID = albumID
+               self.title = title
+               self.artist = artist
+               self.filename = filename
+               if bitrate is not None:
+                       if join:
+                               self.bitrate = "%d Kbps" % bitrate
+                       else:
+                               self.bitrate = bitrate
+               else:
+                       self.bitrate = ""
+               self.length = length
+               self.genre = genre
+               if track is not None:
+                       self.track = "Track %s" % track
+               else:
+                       self.track = ""
+               if date is not None:
+                       if join:
+                               self.date = " (%s)" % date
+                       else:
+                               self.date = date
+               else:
+                       self.date = ""
+               self.album = album
+               self.playlistID = playlistID
+               self.genreID = genreID
+               self.songID = songID
+               self.PTS = PTS
+
+
+def OpenDatabase():
+               connectstring = os_path.join(config.plugins.merlinmusicplayer.databasepath.value ,"iDream.db")
+               db_exists = False
+               if os_path.exists(connectstring):
+                       db_exists = True
+               connection = sqlite.connect(connectstring)
+               if not db_exists :
+                               connection.execute('CREATE TABLE IF NOT EXISTS Songs (song_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, filename TEXT NOT NULL UNIQUE, title TEXT, artist_id INTEGER, album_id INTEGER, genre_id INTEGER, tracknumber INTEGER, bitrate INTEGER, length TEXT, track TEXT, date TEXT, lyrics TEXT);')
+                               connection.execute('CREATE TABLE IF NOT EXISTS Artists (artist_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, artist TEXT NOT NULL UNIQUE);')
+                               connection.execute('CREATE TABLE IF NOT EXISTS Album (album_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, album_text TEXT NOT NULL UNIQUE);')
+                               connection.execute('CREATE TABLE IF NOT EXISTS Genre (genre_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, genre_text TEXT NOT NULL UNIQUE);')
+                               connection.execute('CREATE TABLE IF NOT EXISTS Playlists (playlist_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, playlist_text TEXT NOT NULL);')
+                               connection.execute('CREATE TABLE IF NOT EXISTS Playlist_Songs (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, playlist_id INTEGER NOT NULL, song_id INTEGER NOT NULL);')
+                               connection.execute('CREATE TABLE IF NOT EXISTS CurrentSongList (ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, song_id INTEGER, filename TEXT NOT NULL, title TEXT, artist TEXT, album TEXT, genre TEXT, bitrate TEXT, length TEXT, track TEXT, date TEXT, PTS INTEGER);')
+               return connection
+
+def getID3Tags(root,filename):
+       audio = None
+       isFlac = False
+       isAudio = True
+       title = ""
+       genre = ""
+       artist = ""
+       album = ""
+       tracknr = -1
+       track = None
+       date = None
+       length = ""
+       bitrate = None
+       if filename.lower().endswith(".mp3"):
+               try: audio = MP3(os_path.join(root,filename), ID3 = EasyID3)
+               except: audio = None
+       elif filename.lower().endswith(".flac"):
+               try: 
+                       audio = FLAC(os_path.join(root,filename))
+                       isFlac = True
+               except: audio = None
+       elif filename.lower().endswith(".m4a"):
+               try: audio = EasyMP4(os_path.join(root,filename))
+               except: audio = None
+       elif filename.lower().endswith(".ogg"):
+               try: audio = OggVorbis(os_path.join(root,filename))
+               except: audio = None
+       else:
+               isAudio = False
+       if audio:
+               title = audio.get('title', [filename])[0]
+               genre = audio.get('genre', ['n/a'])[0]
+               artist = audio.get('artist', ['n/a'])[0]
+               album = audio.get('album', ['n/a'])[0]
+               tracknr = int(audio.get('tracknumber', ['-1'])[0].split("/")[0])
+               track = audio.get('tracknumber', [None])[0]
+               date = audio.get('date', [None])[0]
+               
+               length = str(datetime.timedelta(seconds=int(audio.info.length)))
+               if not isFlac:
+                       bitrate = audio.info.bitrate / 1000
+               else:
+                       bitrate = None
+       else:
+               if isAudio:
+                       title = os_path.splitext(os_path.basename(filename))[0]
+                       genre = "n/a"
+                       artist = "n/a"
+                       album = "n/a"
+                       tracknr = -1
+                       track = None
+                       date = None
+                       length = ""
+                       bitrate = None
+
+       return audio, isAudio, title.encode("utf-8", 'ignore'), genre.encode("utf-8", 'ignore'),artist.encode("utf-8", 'ignore'),album.encode("utf-8", 'ignore'),tracknr,track,date,length.encode("utf-8", 'ignore'),bitrate
+
+class MerlinMusicPlayerScreenSaver(Screen):
+
+       sz_w = getDesktop(0).size().width()
+       if sz_w == 1280:
+               skin = """
+                       <screen name="MerlinMusicPlayerScreenSaver" position="0,0" size="1280,720" flags="wfNoBorder" backgroundColor="#00000000" title="MerlinMusicPlayerScreenSaver">
+                       <widget name="coverArt" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/no_coverArt.png" position="200,77" size="238,238" transparent="1" alphatest="blend" />
+                       <widget name="display" position="200,315" size="1280,24" zPosition="1" transparent="1" font="Regular;20" foregroundColor="#fcc000" />
+                       </screen>"""
+       elif sz_w == 1024:
+               skin = """
+                       <screen name="MerlinMusicPlayerScreenSaver" position="0,0" size="1024,576" flags="wfNoBorder" backgroundColor="#00000000" title="MerlinMusicPlayerScreenSaver">
+                       <widget name="coverArt" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/no_coverArt.png" position="200,77" size="238,238" transparent="1" alphatest="blend" />
+                       <widget name="display" position="200,315" size="1024,24" zPosition="1" transparent="1" font="Regular;20" foregroundColor="#fcc000" />
+                       </screen>"""
+
+       else:
+               skin = """
+                       <screen name="MerlinMusicPlayerScreenSaver" position="0,0" size="720,576" flags="wfNoBorder" backgroundColor="#00000000" title="MerlinMusicPlayerScreenSaver">
+                       <widget name="coverArt" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/no_coverArt.png" position="200,77" size="238,238" transparent="1" alphatest="blend" />
+                       <widget name="display" position="200,315" size="720,24" zPosition="1" transparent="1" font="Regular;20" foregroundColor="#fcc000" />
+                       </screen>"""
+               
+       
+       def __init__(self, session):
+               self.session = session
+               Screen.__init__(self, session)
+               self["actions"] = ActionMap(["WizardActions", "DirectionActions", "ColorActions", "EventViewActions"],
+               {
+                       "back": self.close,
+                       "right": self.close,
+                       "left": self.close,
+                       "up": self.close,
+                       "down": self.close,
+                       "ok": self.close,
+                       "pageUp": self.close,
+                       "pageDown": self.close,
+                       "yellow": self.close,
+                       "blue": self.close,
+                       "red": self.close,
+                       "green": self.close,
+                       "right": self.close,
+                       "left": self.close,
+                       "prevBouquet": self.close,
+                       "nextBouquet": self.close,
+                       "info": self.close,
+
+               }, -1)
+               self["coverArt"] = MerlinMediaPixmap()
+               self.coverMoveTimer = eTimer()
+               self.coverMoveTimer.timeout.get().append(self.moveCoverArt)
+               self.coverMoveTimer.start(1)
+               self["display"] = Label()
+
+       def updateDisplayText(self, text):
+               self["display"].setText(text)
+
+       def updateLCD(self, text, line):
+               self.summaries.setText(text,line)
+
+       def updateCover(self, filename = None, modus = 0):
+               print "[MerlinMusicPlayerScreenSaver] updating coverart with filename = %s and modus = %d" % (filename, modus)
+               if modus == 0:
+                       if filename:
+                               self["coverArt"].showCoverFromFile(filename)
+                       else:
+                               self["coverArt"].showDefaultCover()
+               elif modus == 1:
+                       self["coverArt"].showDefaultCover()
+               elif modus == 2:
+                       self["coverArt"].embeddedCoverArt()
+               elif modus == 3:
+                       self["coverArt"].updateCoverArt(filename)
+               elif modus == 4:
+                       self["coverArt"].showCoverFromFile(filename)
+
+       def moveCoverArt(self):
+               x = randrange(getDesktop(0).size().width()-238)
+               y = randrange(getDesktop(0).size().height()-238-28)
+               self["coverArt"].move(ePoint(x,y))
+               self["display"].move(ePoint(x,y+240))
+               self.coverMoveTimer.start(15000)
+
+       def createSummary(self):
+               return MerlinMusicPlayerLCDScreen
+
+class MerlinMusicPlayerScreen(Screen, InfoBarBase, InfoBarSeek, InfoBarNotifications):
+       
+       sz_w = getDesktop(0).size().width()
+       if sz_w == 1280:
+               skin = """
+                       <screen name="MerlinMusicPlayerScreen" position="0,0" size="1280,720" flags="wfNoBorder" backgroundColor="#00000000" title="iDream">
+                       <eLabel backgroundColor="#999999" position="178,112" size="924,2" zPosition="1"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="178,104" size="250,20" text="MERLIN  MUSIC  PLAYER" valign="center" zPosition="2"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="852,104" size="250,20" text="WWW.DREAMBOX-TOOLS.INFO" valign="center" zPosition="2"/>
+                       <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/mmp3pHD.png" position="128,72" size="1024,576"/>
+                       <widget name="coverArt" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/no_coverArt.png" position="328,149" size="238,238" transparent="1" alphatest="blend" />
+                       <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr.png" position="688,232" size="150,20" transparent="1" zPosition="1"/>
+                       <widget name="title" position="362,415" size="600,28" zPosition="1" transparent="1" font="Regular;24" foregroundColor="#fcc000" />
+                       <widget name="album" position="362,462" size="600,22" zPosition="1" transparent="1" font="Regular;18" foregroundColor="#999999" />
+                       <widget name="artist" position="362,492" size="600,22" zPosition="1" transparent="1" font="Regular;18" foregroundColor="#999999" />
+                       <widget name="genre" position="362,522" size="600,22" zPosition="1" transparent="1" font="Regular;18" foregroundColor="#999999" />
+                       <widget name="nextTitle" position="362,562" size="600,22" zPosition="1" transparent="1" font="Regular;16" foregroundColor="#f0f0f0" />
+                       <widget name="PositionGauge" position="664,264" size="198,14" pointer="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/progressbar.png:198,0" seek_pointer="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/progressbar.png:198,0" transparent="1"/>
+                       <widget source="session.CurrentService" render="Label" position="873,267" size="116,18" zPosition="1" font="Regular;18" halign="left" foregroundColor="#999999" transparent="1" >
+                                       <convert type="ServicePosition">Length,ShowHours</convert>
+                       </widget>
+                       <widget source="session.CurrentService" render="Label" position="684,292" size="198,20" zPosition="1" font="Regular;20" halign="left" foregroundColor="#fcc000" transparent="1" >
+                                       <convert type="ServicePosition">Position,ShowHours</convert>
+                       </widget>
+                       <widget name="shuffle" pixmaps="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/placeholder1.png,/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr_shuf.png" position="598,275" size="53,34" transparent="1" alphatest="on"/>
+                       <widget name="repeat" pixmaps="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/placeholder1.png,/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr_rep.png" position="598,239" size="53,34" transparent="1" alphatest="on"/>
+                       <widget name="dvrStatus" pixmaps="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr_pl.png,/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr_pau.png" position="683,227" size="160,39" transparent="1" alphatest="on"/>
+                       </screen>"""
+       elif sz_w == 1024:
+               skin = """
+                       <screen name="MerlinMusicPlayerScreen" position="0,0" size="1024,576" flags="wfNoBorder" backgroundColor="#00000000" title="iDream">
+                       <eLabel backgroundColor="#999999" position="50,40" size="924,2" zPosition="1"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="50,32" size="250,20" text="MERLIN  MUSIC  PLAYER" valign="center" zPosition="2"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="724,32" size="250,20" text="WWW.DREAMBOX-TOOLS.INFO" valign="center" zPosition="2"/>
+                       <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/mmp3pHD.png" position="0,0" size="1024,576"/>
+                       <widget name="coverArt" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/no_coverArt.png" position="200,77" size="238,238" transparent="1" alphatest="blend" />
+                       <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr.png" position="560,160" size="150,20" transparent="1" zPosition="1"/>
+                       <widget name="title" position="234,343" size="600,28" zPosition="1" transparent="1" font="Regular;24" foregroundColor="#fcc000" />
+                       <widget name="album" position="234,390" size="600,22" zPosition="1" transparent="1" font="Regular;18" foregroundColor="#999999" />
+                       <widget name="artist" position="234,420" size="600,22" zPosition="1" transparent="1" font="Regular;18" foregroundColor="#999999" />
+                       <widget name="genre" position="234,450" size="600,22" zPosition="1" transparent="1" font="Regular;18" foregroundColor="#999999" />
+                       <widget name="nextTitle" position="234,490" size="600,22" zPosition="1" transparent="1" font="Regular;16" foregroundColor="#f0f0f0" />
+                       <widget name="PositionGauge" position="536,197" size="198,14" pointer="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/progressbar.png:198,0" seek_pointer="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/progressbar.png:198,0" transparent="1"/>
+                       <widget source="session.CurrentService" render="Label" position="745,195" size="116,18" zPosition="1" font="Regular;18" halign="left" foregroundColor="#999999" transparent="1" >
+                                       <convert type="ServicePosition">Length,ShowHours</convert>
+                       </widget>
+                       <widget source="session.CurrentService" render="Label" position="556,220" size="198,20" zPosition="1" font="Regular;20" halign="left" foregroundColor="#fcc000" transparent="1" >
+                                       <convert type="ServicePosition">Position,ShowHours</convert>
+                       </widget>
+                       <widget name="shuffle" pixmaps="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/placeholder1.png,/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr_shuf.png" position="470,203" size="53,34" transparent="1" alphatest="on"/>
+                       <widget name="repeat" pixmaps="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/placeholder1.png,/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr_rep.png" position="470,167" size="53,34" transparent="1" alphatest="on"/>
+                       <widget name="dvrStatus" pixmaps="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr_pl.png,/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr_pau.png" position="555,155" size="160,39" transparent="1" alphatest="on"/>
+                       </screen>"""
+       else:
+               skin = """
+                       <screen name="MerlinMusicPlayerScreen" position="0,0" size="720,576" flags="wfNoBorder" backgroundColor="#00000000" title="iDream">
+                       <eLabel backgroundColor="#999999" position="50,50" size="620,2" zPosition="1"/>\r
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="50,40" size="250,20" text="MERLIN  MUSIC  PLAYER" valign="center" zPosition="2"/>\r
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="420,40" size="250,20" text="WWW.DREAMBOX-TOOLS.INFO" valign="center" zPosition="2"/>
+                       <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/mmp3p.png" position="120,350" size="33,162"/>
+                       <widget name="coverArt" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/no_coverArt.png" position="106,130" size="180,180" transparent="1" alphatest="blend" />
+                       <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr.png" position="410,160" size="150,20" transparent="1" zPosition="1"/>
+                       <widget name="title" position="160,345" size="550,28" zPosition="1" transparent="1" font="Regular;24" foregroundColor="#fcc000" />
+                       <widget name="album" position="160,392" size="550,22" zPosition="1" transparent="1" font="Regular;18" foregroundColor="#999999" />
+                       <widget name="artist" position="160,422" size="550,22" zPosition="1" transparent="1" font="Regular;18" foregroundColor="#999999" />
+                       <widget name="genre" position="160,455" size="550,22" zPosition="1" transparent="1" font="Regular;18" foregroundColor="#999999" />
+                       <widget name="nextTitle" position="160,492" size="550,22" zPosition="1" transparent="1" font="Regular;16" foregroundColor="#f0f0f0" />
+                       <widget name="PositionGauge" position="386,197" size="198,14" pointer="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/progressbar.png:198,0" seek_pointer="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/progressbar.png:198,0" transparent="1"/>
+                       <widget source="session.CurrentService" render="Label" position="595,193" size="116,18" zPosition="1" font="Regular;18" halign="left" foregroundColor="#999999" transparent="1" >
+                                       <convert type="ServicePosition">Length,ShowHours</convert>
+                       </widget>
+                       <widget source="session.CurrentService" render="Label" position="406,220" size="198,20" zPosition="1" font="Regular;20" halign="left" foregroundColor="#fcc000" transparent="1" >
+                                       <convert type="ServicePosition">Position,ShowHours</convert>
+                       </widget>
+                       <widget name="shuffle" pixmaps="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/placeholder1.png,/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr_shuf.png" position="320,203" size="53,34" transparent="1" alphatest="on"/>
+                       <widget name="repeat" pixmaps="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/placeholder1.png,/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr_rep.png" position="320,167" size="53,34" transparent="1" alphatest="on"/>
+                       <widget name="dvrStatus" pixmaps="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr_pl.png,/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/dvr_pau.png" position="405,155" size="160,39" transparent="1" alphatest="on"/>
+                       </screen>"""
+               
+       
+       def __init__(self, session, songlist, index, idreammode):
+               self.session = session
+               Screen.__init__(self, session)
+               InfoBarNotifications.__init__(self)
+               InfoBarBase.__init__(self)
+               self["actions"] = ActionMap(["WizardActions", "MediaPlayerActions", "EPGSelectActions", "MediaPlayerSeekActions", "ColorActions"],
+               {
+                       "back": self.closePlayer,
+                       "pause": self.pauseEntry,
+                       "stop": self.stopEntry,
+                       "right": self.playNext,
+                       "left": self.playPrevious,
+                       "up": self.showPlaylist,
+                       "down" : self.showPlaylist,
+                       "prevBouquet": self.shuffleList,
+                       "nextBouquet": self.repeatSong,
+                       "info" : self.showLyrics,
+                       "yellow": self.pauseEntry,
+                       "green": self.play,
+                       "input_date_time": self.config,
+               }, -1)
+
+               self.onClose.append(self.__onClose)
+               self.session.nav.stopService()
+               self["PositionGauge"] = ServicePositionGauge(self.session.nav)
+               self["coverArt"] = MerlinMediaPixmap()
+               self["repeat"] = MultiPixmap()
+               self["shuffle"] = MultiPixmap()
+               self["dvrStatus"] = MultiPixmap()
+               self["title"] = Label()
+               self["album"] = Label()
+               self["artist"] = Label()
+               self["genre"] = Label()
+               self["nextTitle"] = Label()
+               self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+                       {
+                               iPlayableService.evUpdatedInfo: self.__evUpdatedInfo,
+                               iPlayableService.evUser+10: self.__evAudioDecodeError,
+                               iPlayableService.evUser+12: self.__evPluginError,
+                               iPlayableService.evUser+13: self.embeddedCoverArt,
+                               iPlayableService.evStart: self.__serviceStarted,
+                       })
+
+               InfoBarSeek.__init__(self, actionmap = "MediaPlayerSeekActions")
+               self.songList = songlist
+               self.origSongList = songlist[:]
+               self.currentIndex = index
+               self.shuffle = False
+               self.repeat = False
+               self.currentFilename = ""
+               self.currentGoogleCoverFile = ""
+               self.googleDownloadDir = os_path.join(config.plugins.merlinmusicplayer.googleimagepath.value, "downloaded_covers/" )
+               if not os_path.exists(self.googleDownloadDir):
+                       os_mkdir(self.googleDownloadDir)
+               self.init = 0
+               self.onShown.append(self.__onShown)
+               # for lcd
+               self.currentTitle = ""
+               self.nextTitle = ""
+               self.screenSaverTimer = eTimer()
+               self.screenSaverTimer.timeout.get().append(self.screenSaverTimerTimeout)
+               self.screenSaverScreen = None
+
+               self.iDreamMode = idreammode
+
+       def embeddedCoverArt(self):             
+               self["coverArt"].embeddedCoverArt()
+               if self.screenSaverScreen:
+                       self.screenSaverScreen.updateCover(modus = 2)
+
+       def screenSaverTimerTimeout(self):
+               if config.plugins.merlinmusicplayer.usescreensaver.value:
+                       if self.screenSaverTimer.isActive():
+                               self.screenSaverTimer.stop()
+                       if not self.screenSaverScreen:
+                               self.screenSaverScreen = self.session.instantiateDialog(MerlinMusicPlayerScreenSaver)
+                               self.session.execDialog(self.screenSaverScreen)
+                               self.screenSaverScreen.updateLCD(self.currentTitle,1)
+                               self.screenSaverScreen.updateLCD(self.nextTitle,4)
+                               album = self["album"].getText()
+                               if album:
+                                       text = "%s - %s" % (self["title"].getText(), album)
+                               else:
+                                       text = self["title"].getText()
+                               self.screenSaverScreen.updateDisplayText(text)
+                               self.screenSaverScreen.updateCover(self["coverArt"].coverArtFileName, modus = 0)
+
+       def resetScreenSaverTimer(self):
+               if config.plugins.merlinmusicplayer.usescreensaver.value and config.plugins.merlinmusicplayer.screensaverwait.value != 0:
+                       if self.screenSaverTimer.isActive():
+                               self.screenSaverTimer.stop()
+                       self.screenSaverTimer.start(config.plugins.merlinmusicplayer.screensaverwait.value * 60000)
+
+       def __onShown(self):
+               if self.init == 0:
+                       self.init = 1
+                       self["coverArt"].onShow()
+                       self.playSong(self.songList[self.currentIndex][0].filename)
+               else:
+                       self.summaries.setText(self.currentTitle,1)
+                       self.summaries.setText(self.nextTitle,4)
+                       if self.screenSaverScreen:
+                               self.screenSaverScreen.doClose()
+                               self.screenSaverScreen = None
+               self.resetScreenSaverTimer()
+               
+       def __onClose(self):
+               del self["coverArt"].picload
+               self.seek = None
+
+       def config(self):
+               if self.screenSaverTimer.isActive():
+                       self.screenSaverTimer.stop()
+               self.session.openWithCallback(self.setupFinished, MerlinMusicPlayerSetup, False)
+       
+       def setupFinished(self, result):
+               if result:
+                       self.googleDownloadDir = os_path.join(config.plugins.merlinmusicplayer.googleimagepath.value, "downloaded_covers/" )
+                       if not os_path.exists(self.googleDownloadDir):
+                               os_mkdir(self.googleDownloadDir)
+               self.resetScreenSaverTimer()
+
+       def closePlayer(self):  
+               if config.plugins.merlinmusicplayer.startlastsonglist.value:
+                       config.plugins.merlinmusicplayer.lastsonglistindex.value = self.currentIndex
+                       config.plugins.merlinmusicplayer.lastsonglistindex.save()
+                       connection = OpenDatabase()
+                       connection.text_factory = str
+                       cursor = connection.cursor()
+                       cursor.execute("Delete from CurrentSongList;")
+                       for song in self.origSongList:
+                               cursor.execute("INSERT INTO CurrentSongList (song_id, filename,title,artist,album,genre, bitrate, length, track, date, PTS) VALUES(?,?,?,?,?,?,?,?,?,?,?);" , (song[0].songID, song[0].filename,song[0].title,song[0].artist,song[0].album,song[0].genre, song[0].bitrate, song[0].length, song[0].track, song[0].date, song[0].PTS))
+                       connection.commit()
+                       cursor.close()
+                       connection.close()
+               if self.screenSaverTimer.isActive():
+                       self.screenSaverTimer.stop()
+               self.close()
+
+       def playSong(self, filename):
+               self.session.nav.stopService()
+               self.seek = None
+               self.currentFilename = filename
+               if not config.plugins.merlinmusicplayer.hardwaredecoder.value and self.currentFilename.lower().endswith(".mp3") and self.songList[self.currentIndex][0].PTS is None:
+                       sref = eServiceReference(ENIGMA_MERLINPLAYER_ID, 0, self.currentFilename) # play mp3 file with merlinmp3player lib
+                       self.session.nav.playService(sref)
+                       if self.iDreamMode:
+                               self.updateMusicInformation( self.songList[self.currentIndex][0].artist, self.songList[self.currentIndex][0].title, 
+                                       self.songList[self.currentIndex][0].album, self.songList[self.currentIndex][0].genre, self.songList[self.currentIndex][0].date, clear = True )
+                       else:
+                               path,filename = os_path.split(self.currentFilename)
+                               audio, isAudio, title, genre,artist,album,tracknr,track,date,length,bitrate = getID3Tags(path,filename)
+                               if audio:
+                                       if date:
+                                               year = "(%s)" % str(date)
+                                       else:
+                                               year = ""
+                                       self.updateMusicInformation( artist, title, album, genre, year, clear = True )
+                               else:
+                                       self.updateMusicInformation( title = title, clear = True)
+                               audio = None
+               else:
+                       sref = eServiceReference(4097, 0, self.currentFilename)
+                       self.session.nav.playService(sref)
+                       if self.songList[self.currentIndex][0].PTS is not None:
+                               service = self.session.nav.getCurrentService()
+                               if service:
+                                       self.seek = service.seek()
+                               self.updateMusicInformationCUE()
+                               self.ptsTimer = eTimer()
+                               self.ptsTimer.callback.append(self.ptsTimerCallback)
+                               self.ptsTimer.start(1000)
+               self["nextTitle"].setText(self.getNextTitle())
+
+       def ptsTimerCallback(self):
+               if self.seek:
+                       pts = self.seek.getPlayPosition()
+                       index = 0
+                       currentIndex = 0
+                       for songs in self.songList:
+                               if pts[1] > songs[0].PTS:
+                                       currentIndex = index
+                               else:
+                                       break
+                               index +=1
+                       if currentIndex != self.currentIndex:
+                               self.currentIndex = currentIndex
+                               self.updateMusicInformationCUE()
+               self.ptsTimer.start(1000)
+
+       def updateMusicInformationCUE(self):
+               self.updateSingleMusicInformation("artist", self.songList[self.currentIndex][0].artist, True)
+               self.updateSingleMusicInformation("title", self.songList[self.currentIndex][0].title, True)
+               self.updateSingleMusicInformation("album", self.songList[self.currentIndex][0].album, True)
+               self.summaries.setText(self.songList[self.currentIndex][0].title,1)
+               if self.screenSaverScreen:
+                       self.screenSaverScreen.updateLCD(self.songList[self.currentIndex][0].title,1)
+                       if self.songList[self.currentIndex][0].album:
+                               self.screenSaverScreen.updateDisplayText("%s - %s" % (self.songList[self.currentIndex][0].title,self.songList[self.currentIndex][0].album))
+                       else:
+                               self.screenSaverScreen.updateDisplayText(self.songList[self.currentIndex][0].title)
+               self.updateCover(self.songList[self.currentIndex][0].artist, self.songList[self.currentIndex][0].album)
+               self.currentTitle = self.songList[self.currentIndex][0].title
+               self["nextTitle"].setText(self.getNextTitle())
+
+       def __serviceStarted(self):
+               self["dvrStatus"].setPixmapNum(0)
+
+       def __evUpdatedInfo(self):
+               currPlay = self.session.nav.getCurrentService()
+               if currPlay is not None:
+                       sTitle = currPlay.info().getInfoString(iServiceInformation.sTagTitle)
+                       sAlbum = currPlay.info().getInfoString(iServiceInformation.sTagAlbum)
+                       sArtist = currPlay.info().getInfoString(iServiceInformation.sTagArtist)
+                       sGenre = currPlay.info().getInfoString(iServiceInformation.sTagGenre)
+                       sYear = currPlay.info().getInfoString(iServiceInformation.sTagDate)
+                       if sYear:
+                               sYear = "(%s)" % sYear
+                       if not sTitle:
+                               sTitle = os_path.splitext(os_path.basename(self.currentFilename))[0]
+                       
+                       if self.songList[self.currentIndex][0].PTS is None:
+                               self.updateMusicInformation( sArtist, sTitle, sAlbum, sGenre, sYear, clear = True )
+                       else:
+                               self.updateSingleMusicInformation("genre", sGenre, True)
+               else:
+                       self.updateMusicInformation()
+
+       def updateMusicInformation(self, artist = "", title = "", album = "", genre = "", year = "", clear = False):
+               if year and album:
+                       album = "%s %s" % (album, year)
+               self.updateSingleMusicInformation("artist", artist, clear)
+               self.updateSingleMusicInformation("title", title, clear)
+               self.updateSingleMusicInformation("album", album, clear)
+               self.updateSingleMusicInformation("genre", genre, clear)
+               self.currentTitle = title
+               if not self.iDreamMode and self.songList[self.currentIndex][0].PTS is None:
+                       # for lyrics
+                       self.songList[self.currentIndex][0].title = title
+                       self.songList[self.currentIndex][0].artist = artist
+               self.summaries.setText(title,1)
+               if self.screenSaverScreen:
+                       self.screenSaverScreen.updateLCD(title,1)
+                       if album:
+                               self.screenSaverScreen.updateDisplayText("%s - %s" % (title,album))
+                       else:
+                               self.screenSaverScreen.updateDisplayText(title)
+               self.updateCover(artist, album)
+
+       def updateCover(self, artist, album):
+               hasCover = False
+               audio = None
+               audiotype = 0
+               if self.currentFilename.lower().endswith(".mp3"):
+                       try: 
+                               audio = ID3(self.currentFilename)
+                               audiotype = 1
+                       except: audio = None
+               elif self.currentFilename.lower().endswith(".flac"):
+                       try: 
+                               audio = FLAC(self.currentFilename)
+                               audiotype = 2
+                       except: audio = None
+               elif self.currentFilename.lower().endswith(".m4a"):
+                       try: 
+                               audio = MP4(self.currentFilename)
+                               audiotype = 3
+                       except: audio = None
+               elif self.currentFilename.lower().endswith(".ogg"):
+                       try:
+                               audio = OggVorbis(self.currentFilename)
+                               audiotype = 4
+                       except: audio = None
+               if audio:
+                       if audiotype == 1:
+                               apicframes = audio.getall("APIC")
+                               if len(apicframes) >= 1:
+                                       hasCover = True
+                                       if not config.plugins.merlinmusicplayer.hardwaredecoder.value:
+                                               coverArtFile = file("/tmp/.id3coverart", 'wb')
+                                               coverArtFile.write(apicframes[0].data)
+                                               coverArtFile.close()
+                                               self["coverArt"].embeddedCoverArt()
+                                               if self.screenSaverScreen:
+                                                       self.screenSaverScreen.updateCover(modus = 2)
+                       elif audiotype == 2:
+                               if len(audio.pictures) >= 1:
+                                       hasCover = True
+                       elif audiotype == 3:
+                               if 'covr' in audio.tags:
+                                       hasCover = True
+                       elif audiotype == 4:
+                               if 'METADATA_BLOCK_PICTURE' in audio.tags:
+                                       hasCover = True
+                       audio = None
+               if not hasCover:
+                       if not self["coverArt"].updateCoverArt(self.currentFilename):
+                               if config.plugins.merlinmusicplayer.usegoogleimage.value:
+                                       self.getGoogleCover(artist, album)
+                               else:
+                                       self["coverArt"].showDefaultCover()
+                                       if self.screenSaverScreen:
+                                               self.screenSaverScreen.updateCover(modus = 1)
+                       else:
+                               if self.screenSaverScreen:
+                                       self.screenSaverScreen.updateCover(filename = self.currentFilename, modus = 3)
+                               self.currentGoogleCoverFile = ""
+               else:
+                       self.currentGoogleCoverFile = ""
+
+       def updateSingleMusicInformation(self, name, info, clear):
+               if info != "" or clear:
+                       if self[name].getText() != info:
+                               self[name].setText(info)
+
+       def getGoogleCover(self, artist,album):
+               if artist != "" and album != "":
+                       url = "http://images.google.de/images?q=%s+%s&btnG=Bilder-Suche" % (quote(album),quote(artist))
+                       sendUrlCommand(url, None,10).addCallback(self.googleImageCallback).addErrback(self.coverDownloadFailed)
+               else:
+                       self["coverArt"].showDefaultCover()
+
+       def googleImageCallback(self, result):
+               foundPos = result.find("imgres?imgurl=")
+               foundPos2 = result.find("&imgrefurl=")
+               if foundPos != -1 and foundPos2 != -1:
+                       url = result[foundPos+14:foundPos2]
+                       parts = url.split("/")
+                       filename = parts[-1]
+                       if filename != self.currentGoogleCoverFile:
+                               self.currentGoogleCoverFile = filename
+                               filename = self.googleDownloadDir + parts[-1]
+                               if os_path.exists(filename):
+                                       print "[MerlinMusicPlayer] using cover from %s " % filename
+                                       self["coverArt"].showCoverFromFile(filename)
+                                       if self.screenSaverScreen:
+                                               self.screenSaverScreen.updateCover(filename = filename, modus = 4)
+                               else:
+                                       print "[MerlinMusicPlayer] downloading cover from %s " % url
+                                       downloadPage(url , self.googleDownloadDir + parts[-1]).addCallback(boundFunction(self.coverDownloadFinished, filename)).addErrback(self.coverDownloadFailed)
+
+       def coverDownloadFailed(self,result):
+               print "[MerlinMusicPlayer] cover download failed: %s " % result
+               self["coverArt"].showDefaultCover()
+               if self.screenSaverScreen:
+                       self.screenSaverScreen.updateCover(modus = 1)
+
+       def coverDownloadFinished(self,filename, result):
+               print "[MerlinMusicPlayer] cover download finished"
+               self["coverArt"].showCoverFromFile(filename)
+               if self.screenSaverScreen:
+                       self.screenSaverScreen.updateCover(filename = filename, modus = 4)
+
+       def __evAudioDecodeError(self):
+               currPlay = self.session.nav.getCurrentService()
+               sAudioType = currPlay.info().getInfoString(iServiceInformation.sUser+10)
+               print "[MerlinMusicPlayer] audio-codec %s can't be decoded by hardware" % (sAudioType)
+               self.session.open(MessageBox, _("This Dreambox can't decode %s streams!") % sAudioType, type = MessageBox.TYPE_INFO,timeout = 20 )
+
+       def __evPluginError(self):
+               currPlay = self.session.nav.getCurrentService()
+               message = currPlay.info().getInfoString(iServiceInformation.sUser+12)
+               print "[MerlinMusicPlayer]" , message
+               self.session.open(MessageBox, message, type = MessageBox.TYPE_INFO,timeout = 20 )
+
+       def doEofInternal(self, playing):
+               if playing:
+                       self.playNext()
+
+       def checkSkipShowHideLock(self):
+               self.updatedSeekState()
+
+       def updatedSeekState(self):
+               if self.seekstate == self.SEEK_STATE_PAUSE:
+                       self["dvrStatus"].setPixmapNum(1)
+               elif self.seekstate == self.SEEK_STATE_PLAY:
+                       self["dvrStatus"].setPixmapNum(0)
+
+       def pauseEntry(self):
+               self.pauseService()
+               self.resetScreenSaverTimer()
+
+       def play(self):
+               #play the current song from beginning again
+               if self.songList[self.currentIndex][0].PTS is None:
+                       self.playSong(self.songList[self.currentIndex][0].filename)
+               else:
+                       if self.seek:
+                               self.seek.seekTo(self.songList[self.currentIndex][0].PTS)
+                               self.updatedSeekState()
+               self.resetScreenSaverTimer()            
+
+       def unPauseService(self):
+               self.setSeekState(self.SEEK_STATE_PLAY)
+
+       def stopEntry(self):
+               self.seek = None
+               self.session.nav.stopService()
+               self.origSongList = []
+               self.songList = []
+               if config.plugins.merlinmusicplayer.startlastsonglist.value:
+                       config.plugins.merlinmusicplayer.lastsonglistindex.value = -1
+                       config.plugins.merlinmusicplayer.lastsonglistindex.save()
+                       connection = OpenDatabase()
+                       connection.text_factory = str
+                       cursor = connection.cursor()
+                       cursor.execute("Delete from CurrentSongList;")
+                       connection.commit()
+                       cursor.close()
+                       connection.close()
+               self.resetScreenSaverTimer()
+               self.close()
+
+       def playNext(self):
+               if not self.repeat:
+                       if self.currentIndex +1 > len(self.songList) -1:
+                               self.currentIndex = 0
+                       else:
+                               self.currentIndex += 1
+               if self.songList[self.currentIndex][0].PTS is None:
+                       self.playSong(self.songList[self.currentIndex][0].filename)
+               else:
+                       self.playCUETrack()
+               if not self.screenSaverScreen:
+                       self.resetScreenSaverTimer()
+
+       def playPrevious(self):
+               if not self.repeat:
+                       if self.currentIndex - 1 < 0:
+                               self.currentIndex = len(self.songList) - 1
+                       else:
+                               self.currentIndex -= 1
+
+               if self.songList[self.currentIndex][0].PTS is None:
+                       self.playSong(self.songList[self.currentIndex][0].filename)
+               else:
+                       self.playCUETrack()
+               self.resetScreenSaverTimer()
+
+       def getNextTitle(self):
+               if self.repeat:
+                       index = self.currentIndex
+               else:
+                       if self.currentIndex + 1 > len(self.songList) -1:
+                               index = 0
+                       else:
+                               index = self.currentIndex + 1
+               if self.iDreamMode or self.songList[index][0].PTS is not None:
+                       text = "%s - %s" % (self.songList[index][0].title, self.songList[index][0].artist)
+               else:
+                       if self.songList[index][0].filename.lower().startswith("http://"):
+                               text = self.songList[index][0].filename
+                       else:
+                               path,filename = os_path.split(self.songList[index][0].filename)
+                               audio, isAudio, title, genre,artist,album,tracknr,track,date,length,bitrate = getID3Tags(path,filename)
+                               if audio:
+                                       if artist:
+                                               text = "%s - %s" % (title, artist)
+                                       else:
+                                               text = title
+                               else:
+                                       text = title
+                               audio = None
+               self.nextTitle = text
+               self.summaries.setText(text,4)
+               if self.screenSaverScreen:
+                       self.screenSaverScreen.updateLCD(text,4)
+               return str(text)
+
+       def shuffleList(self):
+               if self.songList[self.currentIndex][0].PTS is None: # not implemented for cue files yet
+                       self.shuffle = not self.shuffle
+                       if self.shuffle:
+                               self["shuffle"].setPixmapNum(1)
+                               shuffle(self.songList)
+                       else:
+                               self.songList = self.origSongList[:]
+                               self["shuffle"].setPixmapNum(0)
+                       index = 0
+                       for x in self.songList:
+                               if x[0].filename == self.currentFilename:
+                                       self.currentIndex = index
+                                       break
+                               index += 1
+                       self["nextTitle"].setText(self.getNextTitle())
+               else:
+                       self.session.open(MessageBox, _("Shuffle is not available yet with cue-files!"), type = MessageBox.TYPE_INFO,timeout = 20 )
+               self.resetScreenSaverTimer()
+
+       def repeatSong(self):
+               if self.songList[self.currentIndex][0].PTS is None: # not implemented for cue files yet
+                       self.repeat = not self.repeat
+                       if self.repeat:
+                               self["repeat"].setPixmapNum(1)
+                       else:
+                               self["repeat"].setPixmapNum(0)
+                       self["nextTitle"].setText(self.getNextTitle())
+               else:
+                       self.session.open(MessageBox, _("Repeat is not available yet with cue-files!"), type = MessageBox.TYPE_INFO,timeout = 20 )
+               self.resetScreenSaverTimer()
+
+       def showPlaylist(self):
+               if self.screenSaverTimer.isActive():
+                       self.screenSaverTimer.stop()
+               self.session.openWithCallback(self.showPlaylistCallback, MerlinMusicPlayerSongList, self.songList, self.currentIndex, self.iDreamMode)
+
+       def showPlaylistCallback(self, index):
+               if index != -1:
+                       self.currentIndex = index
+
+                       if self.songList[self.currentIndex][0].PTS is None:
+                               self.playSong(self.songList[self.currentIndex][0].filename)
+                       else:
+                               self.playCUETrack()             
+
+               self.resetScreenSaverTimer()
+
+       def playCUETrack(self):
+               if self.ptsTimer.isActive():
+                       self.ptsTimer.stop()
+               if self.seek:
+                       self.seek.seekTo(self.songList[self.currentIndex][0].PTS)
+                       self.updatedSeekState()
+                       self.updateMusicInformationCUE()
+                       self.ptsTimer.start(1000)
+
+       def showLyrics(self):
+               if self.screenSaverTimer.isActive():
+                       self.screenSaverTimer.stop()
+               self.session.openWithCallback(self.resetScreenSaverTimer, MerlinMusicPlayerLyrics, self.songList[self.currentIndex][0])
+
+       def createSummary(self):
+               return MerlinMusicPlayerLCDScreen
+
+class MerlinMusicPlayerLyrics(Screen):
+
+       sz_w = getDesktop(0).size().width()
+       if sz_w == 1280:
+               skin = """
+                       <screen name="MerlinMusicPlayerLyrics" position="0,0" size="1280,720" flags="wfNoBorder" backgroundColor="#00000000" title="Merlin Music Player Lyrics">
+                       <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/mmpborderHD.png" position="128,72" size="1024,576"/>
+                       <eLabel backgroundColor="#999999" position="178,112" size="924,2" zPosition="1"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="178,104" size="250,20" text="MERLIN  MUSIC  PLAYER" valign="center" zPosition="2"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="852,104" size="250,20" text="WWW.DREAMBOX-TOOLS.INFO" valign="center" zPosition="2"/>
+                       <widget name="headertext" position="178,145" zPosition="1" size="900,23" font="Regular;20" transparent="1"  foregroundColor="#fcc000" backgroundColor="#00000000"/>
+                       <widget name="resulttext" position="178,172" zPosition="1" size="900,20" font="Regular;16" transparent="1"   backgroundColor="#00000000"/>
+                       <widget name="lyric_text" position="178,222" zPosition="2" size="940,350" font="Regular;18" transparent="0"  backgroundColor="#00000000"/>
+                       </screen>"""
+       elif sz_w == 1024:
+               skin = """
+                       <screen name="MerlinMusicPlayerLyrics" position="0,0" size="1024,576" flags="wfNoBorder" backgroundColor="#00000000" title="Merlin Music Player Lyrics">
+                       <eLabel backgroundColor="#999999" position="50,40" size="924,2" zPosition="1"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="50,32" size="250,20" text="MERLIN  MUSIC  PLAYER" valign="center" zPosition="2"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="724,32" size="250,20" text="WWW.DREAMBOX-TOOLS.INFO" valign="center" zPosition="2"/>
+                       <widget name="headertext" position="50,73" zPosition="1" size="900,23" font="Regular;20" transparent="1"  foregroundColor="#fcc000" backgroundColor="#00000000"/>
+                       <widget name="resulttext" position="50,100" zPosition="1" size="900,20" font="Regular;16" transparent="1"   backgroundColor="#00000000"/>
+                       <widget name="lyric_text" position="50,150" zPosition="2" size="940,350" font="Regular;18" transparent="0"  backgroundColor="#00000000"/>
+                       </screen>"""
+       else:
+               skin = """
+                       <screen name="MerlinMusicPlayerLyrics" position="0,0" size="720,576" flags="wfNoBorder" backgroundColor="#00000000" title="Merlin Music Player Lyrics">
+                       <eLabel backgroundColor="#999999" position="50,50" size="620,2" zPosition="1"/>\r
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="50,40" size="250,20" text="MERLIN  MUSIC  PLAYER" valign="center" zPosition="2"/>\r
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="420,40" size="250,20" text="WWW.DREAMBOX-TOOLS.INFO" valign="center" zPosition="2"/>
+                       <widget name="headertext" position="50,73" zPosition="1" size="620,23" font="Regular;20" transparent="1"  foregroundColor="#fcc000" backgroundColor="#00000000"/>
+                       <widget name="resulttext" position="50,100" zPosition="1" size="620,20" font="Regular;16" transparent="1"   backgroundColor="#00000000"/>
+                       <widget name="lyric_text" position="50,150" zPosition="2" size="620,350" font="Regular;18" transparent="0"  backgroundColor="#00000000"/>
+                       </screen>"""
+               
+       
+       def __init__(self, session, currentsong):
+               self.session = session
+               Screen.__init__(self, session)
+               self["headertext"] = Label(_("Merlin Music Player Lyrics"))
+               self["resulttext"] = Label(_("Getting lyrics from api.leoslyrics.com..."))
+               self["actions"] = ActionMap(["WizardActions", "DirectionActions"],
+               {
+                       "back": self.close,
+                       "upUp": self.pageUp,
+                       "leftUp": self.pageUp,
+                       "downUp": self.pageDown,
+                       "rightUp": self.pageDown,
+               }, -1)
+               self["lyric_text"] = ScrollLabel()
+               self.currentSong = currentsong
+               self.onLayoutFinish.append(self.startRun)
+
+       def startRun(self):
+               url = "http://api.leoslyrics.com/api_search.php?auth=duane&artist=%s&songtitle=%s" % (quote(self.currentSong.artist), quote(self.currentSong.title))
+               sendUrlCommand(url, None,10).addCallback(self.getHID).addErrback(self.urlError)
+       
+       def urlError(self, error = None):
+               if error is not None:
+                       self["resulttext"].setText(str(error.getErrorMessage()))
+
+       def getHID(self, xmlstring):
+               root = cet_fromstring(xmlstring)
+               url = ""
+               child = root.find("searchResults")
+               if child:
+                       child2 = child.find("result")
+                       if child2:
+                               url = "http://api.leoslyrics.com/api_lyrics.php?auth=duane&hid=%s" % quote(child2.get("hid"))
+                               sendUrlCommand(url, None,10).addCallback(self.getLyrics).addErrback(self.urlError)
+               if not url:
+                       self["resulttext"].setText(_("No lyrics found"))
+
+       def getLyrics(self, xmlstring):
+               root = cet_fromstring(xmlstring)
+               lyrictext = ""
+               child = root.find("lyric")
+               if child:
+                       title = child.findtext("title").encode("utf-8", 'ignore')
+                       child2 = child.find("artist")
+                       if child2:
+                               artist = child2.findtext("name").encode("utf-8", 'ignore')
+                       else:
+                               artist = ""
+                       lyrictext = child.findtext("text").encode("utf-8", 'ignore')
+                       self["lyric_text"].setText(lyrictext)
+                       result = _("Response -> lyrics for: %s (%s)") % (title,artist)
+                       self["resulttext"].setText(result)
+               if not lyrictext:
+                       self["resulttext"].setText(_("No lyrics found"))
+
+       def pageUp(self):
+               self["lyric_text"].pageUp()
+
+       def pageDown(self):
+               self["lyric_text"].pageDown()   
+
+class MerlinMusicPlayerSongList(Screen):
+       
+       sz_w = getDesktop(0).size().width()
+       if sz_w == 1280:
+               skin = """
+                       <screen name="MerlinMusicPlayerSongList" position="0,0" size="1280,720" flags="wfNoBorder" backgroundColor="#00000000" title="Songlist">
+                       <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/mmpborderHD.png" position="128,72" size="1024,576"/>
+                       <eLabel backgroundColor="#999999" position="178,112" size="924,2" zPosition="1"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="178,104" size="250,20" text="MERLIN  MUSIC  PLAYER" valign="center" zPosition="2"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="852,104" size="250,20" text="WWW.DREAMBOX-TOOLS.INFO" valign="center" zPosition="2"/>
+                       <widget name="headertext" position="178,145" zPosition="1" size="900,23" font="Regular;20" transparent="1"  foregroundColor="#fcc000" backgroundColor="#00000000"/>
+                       <widget name="list" position="178,182" zPosition="2" size="940,350" scrollbarMode="showOnDemand" transparent="0"  backgroundColor="#00000000"/>
+                       </screen>"""
+       elif sz_w == 1024:
+               skin = """
+                       <screen name="MerlinMusicPlayerSongList" position="0,0" size="1024,576" flags="wfNoBorder" backgroundColor="#00000000" title="Songlist">
+                       <eLabel backgroundColor="#999999" position="50,40" size="924,2" zPosition="1"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="50,32" size="250,20" text="MERLIN  MUSIC  PLAYER" valign="center" zPosition="2"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="724,32" size="250,20" text="WWW.DREAMBOX-TOOLS.INFO" valign="center" zPosition="2"/>
+                       <widget name="headertext" position="50,73" zPosition="1" size="900,23" font="Regular;20" transparent="1"  foregroundColor="#fcc000" backgroundColor="#00000000"/>
+                       <widget name="list" position="50,110" zPosition="2" size="940,350" scrollbarMode="showOnDemand" transparent="0"  backgroundColor="#00000000"/>
+                       </screen>"""
+       else:
+               skin = """
+                       <screen name="MerlinMusicPlayerSongList" position="0,0" size="720,576" flags="wfNoBorder" backgroundColor="#00000000" title="Songlist">
+                       <eLabel backgroundColor="#999999" position="50,50" size="620,2" zPosition="1"/>\r
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="50,40" size="250,20" text="MERLIN  MUSIC  PLAYER" valign="center" zPosition="2"/>\r
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="420,40" size="250,20" text="WWW.DREAMBOX-TOOLS.INFO" valign="center" zPosition="2"/>
+                       <widget name="headertext" position="50,73" zPosition="1" size="620,23" font="Regular;20" transparent="1"  foregroundColor="#fcc000" backgroundColor="#00000000"/>
+                       <widget name="list" position="50,110" zPosition="2" size="620,350" scrollbarMode="showOnDemand" transparent="0"  backgroundColor="#00000000"/>
+                       </screen>"""
+               
+       
+       def __init__(self, session, songlist, index, idreammode):
+               self.session = session
+               Screen.__init__(self, session)
+               self["headertext"] = Label(_("Merlin Music Player Songlist"))
+               self["list"] = iDreamList()
+               self["list"].connectSelChanged(self.lcdUpdate)
+               self["actions"] = ActionMap(["WizardActions"],
+               {
+                       "ok": self.ok,
+                       "back": self.closing,
+               }, -1)
+               self.songList = songlist
+               self.index = index
+               self.iDreamMode = idreammode
+               self.onLayoutFinish.append(self.startRun)
+               self.onShown.append(self.lcdUpdate)
+
+       def startRun(self):
+               if self.iDreamMode:
+                       self["list"].setMode(10) # songlist
+               self["list"].setList(self.songList)
+               self["list"].moveToIndex(self.index)
+
+       def ok(self):
+               self.close(self["list"].getCurrentIndex())
+
+       def closing(self):
+               self.close(-1)
+
+       def lcdUpdate(self):
+               try:
+                       index = self["list"].getCurrentIndex()
+                       songlist = self["list"].getList()
+                       self.summaries.setText(songlist[index][0].title,1)
+                       count = self["list"].getItemCount()
+                       # voheriges
+                       index -= 1
+                       if index < 0:
+                               index = count
+                       self.summaries.setText(songlist[index][0].title,3)
+                       # naechstes
+                       index = self["list"].getCurrentIndex() + 1
+                       if index > count:
+                               index = 0
+                       self.summaries.setText(songlist[index][0].title,4)
+               except: pass
+
+       def createSummary(self):
+               return MerlinMusicPlayerLCDScreenText
+
+class iDreamMerlin(Screen):
+       
+
+       sz_w = getDesktop(0).size().width()
+       if sz_w == 1280:
+               skin = """
+                       <screen name="iDreamMerlin" position="0,0" size="1280,720" flags="wfNoBorder" backgroundColor="#00000000" title="iDream">
+                               <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/mmpborderHD.png" position="128,72" size="1024,576"/>
+                               <ePixmap position="178,102" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
+                               <ePixmap position="328,102" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
+                               <ePixmap position="478,102" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
+                               <ePixmap position="628,102" zPosition="4" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
+                               <widget render="Label" source="key_red" position="178,102" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget render="Label" source="key_green" position="328,102" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget render="Label" source="key_yellow" position="478,102" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget render="Label" source="key_blue" position="628,102" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget name="headertext" position="178,149" zPosition="1" size="900,23" font="Regular;20" transparent="1"  foregroundColor="#fcc000" backgroundColor="#00000000"/>
+                               <widget name="list" position="178,182" zPosition="2" size="940,350" scrollbarMode="showOnDemand" transparent="0"  backgroundColor="#00000000"/>
+                       </screen>"""
+       elif sz_w == 1024:
+               skin = """
+                       <screen name="iDreamMerlin" position="0,0" size="1024,576" flags="wfNoBorder" backgroundColor="#00000000" title="iDream">
+                               <ePixmap position="50,30" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
+                               <ePixmap position="200,30" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
+                               <ePixmap position="350,30" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
+                               <ePixmap position="500,30" zPosition="4" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
+                               <widget render="Label" source="key_red" position="50,30" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget render="Label" source="key_green" position="200,30" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget render="Label" source="key_yellow" position="350,30" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget render="Label" source="key_blue" position="500,30" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget name="headertext" position="50,77" zPosition="1" size="900,23" font="Regular;20" transparent="1"  foregroundColor="#fcc000" backgroundColor="#00000000"/>
+                               <widget name="list" position="50,110" zPosition="2" size="940,350" scrollbarMode="showOnDemand" transparent="0"  backgroundColor="#00000000"/>
+                       </screen>"""
+       else:
+               skin = """
+                       <screen name="iDreamMerlin" position="0,0" size="720,576" flags="wfNoBorder" backgroundColor="#00000000" title="iDream">
+                               <ePixmap position="50,30" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
+                               <ePixmap position="200,30" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
+                               <ePixmap position="350,30" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
+                               <ePixmap position="500,30" zPosition="4" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
+                               <widget render="Label" source="key_red" position="50,30" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget render="Label" source="key_green" position="200,30" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget render="Label" source="key_yellow" position="350,30" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget render="Label" source="key_blue" position="500,30" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget name="headertext" position="50,77" zPosition="1" size="620,23" font="Regular;20" transparent="1"  foregroundColor="#fcc000" backgroundColor="#00000000"/>
+                               <widget name="list" position="50,110" zPosition="2" size="620,350" scrollbarMode="showOnDemand" transparent="0"  backgroundColor="#00000000"/>
+                       </screen>"""
+               
+       
+       def __init__(self, session):
+               self.session = session
+               Screen.__init__(self, session)
+               self["list"] = iDreamList()
+               self["list"].connectSelChanged(self.lcdUpdate)
+
+
+               self["actions"] = ActionMap(["WizardActions", "DirectionActions", "ColorActions", "EPGSelectActions"],
+               {
+                       "ok": self.ok,
+                       "back": self.closing,
+                       "red": self.red_pressed,
+                       "green": self.green_pressed,
+                       "yellow": self.yellow_pressed,
+                       "blue": self.blue_pressed,
+                       "input_date_time": self.menu_pressed,
+                       "info" : self.info_pressed,
+               }, -1)
+
+               self["actions2"] = NumberActionMap(["InputActions"],
+               {
+                       "0": self.keyNumber_pressed,
+               }, -1)
+
+               self.onLayoutFinish.append(self.startRun)
+               self.onShown.append(self.lcdUpdate)
+               self.onClose.append(self.__onClose)
+               
+               self.CurrentService = self.session.nav.getCurrentlyPlayingServiceReference()
+               self.session.nav.stopService()
+               
+               self.mode = 0
+               self.mainMenuList = []
+               self.cacheList = []
+               self.LastMethod = None
+               self.player = None
+               
+               self["key_red"] = StaticText("")
+               self["key_green"] = StaticText("")
+               self["key_yellow"] = StaticText("")
+               self["key_blue"] = StaticText("")
+               self["headertext"] = Label(_("iDream Main Menu"))
+
+       def getPlayList(self):
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               playList = []
+               cursor.execute("select playlist_id,playlist_text from playlists order by playlist_text;")
+               for row in cursor:
+                       playList.append((row[1], row[0]))
+               cursor.close()  
+               connection.close()
+               return playList
+
+       def sqlCommand(self, sqlSatement):
+               connection = OpenDatabase()
+               cursor = connection.cursor()
+               cursor.execute(sqlSatement)
+               cursor.close()
+               connection.commit()
+               connection.close()
+
+       def clearCache(self):
+               for items in self.cacheList:
+                       items.cache = False
+                       items.listview = []
+                       items.headertext = ""
+
+       def getCurrentSelection(self):
+               sel = None
+               try: sel = self["list"].l.getCurrentSelection()[0]
+               except: pass
+               return sel
+
+       def addListToPlaylistConfirmed(self, methodName, answer):
+               if answer:
+                       playList = self.getPlayList()
+                       if len(playList):
+                               self.session.openWithCallback(methodName, ChoiceBox,list = playList)
+                       else:
+                               self.session.openWithCallback(self.createPlaylistConfirmed, MessageBox, _("There are no playlists defined.\nDo you want to create a new playlist?"))
+
+       def menu_pressed(self):
+               options = [(_("Configuration"), self.config),(_("Search in iDream database"), self.searchInIDreamDatabase),]
+               options.extend(((_("Scan path for music files and add them to database"), self.scanDir),))
+               if self.mode != 1:
+                       options.extend(((_("Create new playlist"), self.createPlaylist),))
+               if self["list"].getDisplaySongMode():
+                       if self.mode == 2:
+                               options.extend(((_("Delete song from current playlist"), self.deleteSongFromPlaylist),))
+                       else:
+                               options.extend(((_("Add selected song to a playlist"), self.addSongToPlaylist),))
+                               if self.mode == 18:
+                                       options.extend(((_("Add all songs from selected album to a playlist"), self.addAlbumToPlaylist),))
+                               elif self.mode == 19:
+                                       options.extend(((_("Add all songs from selected artist to a playlist"), self.addArtistToPlaylist),))
+                               options.extend(((_("Delete song from database"), self.deleteSongFromDatabase),))
+               else:
+                       if self.mode == 1:
+                               options.extend(((_("Delete selected playlist"), self.deletePlaylist),))
+                       elif self.mode == 4:
+                               options.extend(((_("Add all songs from selected artist to a playlist"), self.addArtistToPlaylist),))
+                       elif self.mode == 5 or self.mode == 7:
+                               options.extend(((_("Add all songs from selected album to a playlist"), self.addAlbumToPlaylist),))
+                       elif self.mode == 13:
+                               options.extend(((_("Add all songs from selected genre to a playlist"), self.addGenreToPlaylist),))
+               self.session.openWithCallback(self.menuCallback, ChoiceBox,list = options)
+
+       def menuCallback(self, ret):
+               ret and ret[1]()
+
+       def scanDir(self):
+               SelectPath
+               self.session.openWithCallback(self.pathSelected,SelectPath,"/media/")
+
+       def pathSelected(self, res):
+               if res is not None:
+                       self.session.openWithCallback(self.filesAdded, iDreamAddToDatabase,res)
+
+       def filesAdded(self):
+               if pathToDatabase.isRunning:
+                       self.close()
+               else:
+                       self.red_pressed()
+               
+
+
+
+       def addGenreToPlaylist(self):
+               self.session.openWithCallback(boundFunction(self.addListToPlaylistConfirmed,self.addGenreToPlaylistConfirmedCallback), MessageBox, _("Do you really want to add all songs from that genre to a playlist?"))
+
+       def addGenreToPlaylistConfirmedCallback(self, ret):
+               if ret:
+                       sel = self.getCurrentSelection()
+                       if sel:
+                               self.sqlCommand("INSERT INTO Playlist_Songs (playlist_id,song_id) select %d, song_id from songs where genre_id=%d order by album_id,tracknumber,title,filename;" % (ret[1],sel.genreID))
+                               self.clearCache()
+
+       def addArtistToPlaylist(self):
+               self.session.openWithCallback(boundFunction(self.addListToPlaylistConfirmed, self.addArtistToPlaylistConfirmedCallback), MessageBox, _("Do you really want to add all songs from that artist to a playlist?"))
+
+       def addArtistToPlaylistConfirmedCallback(self, ret):
+               if ret:
+                       sel = self.getCurrentSelection()
+                       if sel:
+                               self.sqlCommand("INSERT INTO Playlist_Songs (playlist_id,song_id) select %d, song_id from songs where artist_id=%d order by album_id,tracknumber,title,filename;" % (ret[1],sel.artistID))
+                               self.clearCache()
+
+       def addAlbumToPlaylist(self):
+               self.session.openWithCallback(boundFunction(self.addListToPlaylistConfirmed, self.addAlbumToPlaylistConfirmedCallback), MessageBox, _("Do you really want to add all songs from that album to a playlist?"))
+
+       def addAlbumToPlaylistConfirmedCallback(self, ret):
+               if ret:
+                       sel = self.getCurrentSelection()
+                       if sel:
+                               self.sqlCommand("INSERT INTO Playlist_Songs (playlist_id,song_id) select %d, song_id from songs where album_id=%d order by tracknumber,title,filename;" % (ret[1],sel.albumID))
+                               self.clearCache()
+
+       def deletePlaylist(self):
+               self.session.openWithCallback(self.deletePlaylistConfirmed, MessageBox, _("Do you really want to delete the current playlist?"))
+
+       def deletePlaylistConfirmed(self, answer):
+               if answer:
+                       sel = self.getCurrentSelection()
+                       if sel:
+                               self.sqlCommand("delete from playlist_songs where playlist_id = %d" % (sel.playlistID))
+                               self.sqlCommand("delete from playlists where playlist_id = %d" % (sel.playlistID))
+                               self["list"].removeItem(self["list"].getCurrentIndex())
+                               self.clearCache()
+
+
+       def deleteSongFromPlaylist(self):
+               self.session.openWithCallback(self.deleteSongFromPlaylistConfirmed, MessageBox, _("Do you really want to delete that song the current playlist?"))
+
+       def deleteSongFromPlaylistConfirmed(self, answer):
+               if answer:
+                       sel = self.getCurrentSelection()
+                       if sel:
+                               self.sqlCommand("delete from playlist_songs where song_id = %d" % (sel.songID))
+                               self["list"].removeItem(self["list"].getCurrentIndex())
+                               self.clearCache()
+
+       def deleteSongFromDatabase(self):
+               self.session.openWithCallback(self.deleteSongFromDatabaseConfirmed, MessageBox, _("Do you really want to delete that song from the database?"))
+
+       def deleteSongFromDatabaseConfirmed(self, answer):
+               if answer:
+                       sel = self.getCurrentSelection()
+                       if sel:
+                               self.sqlCommand("delete from playlist_songs where song_id = %d" % (sel.songID))
+                               self.sqlCommand("delete from songs where song_id = %d" % (sel.songID))
+                               self["list"].removeItem(self["list"].getCurrentIndex())
+                               self.clearCache()
+                       
+       def addSongToPlaylist(self):
+               playList = self.getPlayList()
+               if len(playList):
+                       self.session.openWithCallback(self.addSongToPlaylistCallback, ChoiceBox,list = playList)
+               else:
+                       self.session.openWithCallback(self.createPlaylistConfirmed, MessageBox, _("There are no playlists defined.\nDo you want to create a new playlist?"))
+
+       def createPlaylistConfirmed(self, val):
+               if val:
+                       self.createPlaylist()
+
+       def addSongToPlaylistCallback(self,ret):
+               if ret:
+                       sel = self.getCurrentSelection()
+                       if sel:
+                               self.sqlCommand("INSERT INTO Playlist_Songs (playlist_id,song_id) VALUES(%d,%d);" % (ret[1],sel.songID))
+                               self.clearCache()
+
+       def createPlaylist(self):
+               self.session.openWithCallback(self.createPlaylistFinished, VirtualKeyBoard, title = _("Enter name for playlist"))
+
+       def createPlaylistFinished(self, text = None):
+               if text:
+                       self.sqlCommand("""INSERT INTO Playlists (playlist_text) VALUES("%s");""" % (text))
+                       self.clearCache()
+                       self.menu_pressed()
+
+       def searchInIDreamDatabase(self):
+               options = [(_("search for title"), 1),
+                       (_("search for artist"), 2),
+                       (_("search for album"), 3),
+                       (_("search in all of them"), 4),]
+               self.session.openWithCallback(self.enterSearchText, ChoiceBox,list = options)
+
+       def enterSearchText(self, ret):
+               if ret:
+                       self.session.openWithCallback(boundFunction(self.enterSearchTextFinished,ret[1]), VirtualKeyBoard, title = _("Enter search-text"))
+
+       def enterSearchTextFinished(self, searchType, searchText = None):
+               if searchText:
+                       search = "%" + searchText + "%"
+                       if searchType == 1:
+                               sql_where = "where title like '%s'" % search
+                               text = _("""Search results for "%s" in all titles""") % searchText
+                       elif searchType == 2:
+                               sql_where = "where artists.artist like '%s'" % search
+                               text = _("""Search results for "%s" in all artists""") % searchText
+                       elif searchType == 3:
+                               sql_where = "where album_text like '%s'" % search
+                               text = _("""Search results for "%s" in all albums""") % searchText
+                       else:
+                               sql_where = "where (title like '%s' or artists.artist like '%s' or album_text like '%s')"  % (search,search,search)
+                               text = _("""Search results for "%s" in title, artist or album""") % searchText
+                       self.setButtons(red = True, yellow = True, blue = True)
+                       oldmode = self.mode
+                       self.mode = 20
+                       self["list"].setMode(self.mode)
+                       self.buildSearchSongList(sql_where, text, oldmode, True)
+
+
+       def keyNumber_pressed(self, number):
+               if number == 0 and self.mode != 0:
+                       self["list"].moveToIndex(0)
+                       self.ok()
+
+       def ok(self):
+               sel = self.getCurrentSelection()
+               if sel is None:
+                       return
+               if sel.mode == 99:
+                       self.green_pressed()
+               else:
+                       self.mode = sel.mode
+                       self["list"].setMode(self.mode)
+                       if sel.navigator and len(self.cacheList) > 0:
+                               cache = self.cacheList.pop()
+                       else:
+                               cache = CacheList(cache = False, index = -1)
+                       if sel.navigator: 
+                               self["headertext"].setText(cache.headertext)
+                               if cache.cache:
+                                       self["list"].setList(cache.listview)
+                                       self.LastMethod = MethodArguments(method = cache.methodarguments.method, arguments = cache.methodarguments.arguments)
+                               else:
+                                       cache.methodarguments.method(**cache.methodarguments.arguments)
+                               self["list"].moveToIndex(cache.index)
+                       if self.mode == 0:
+                               self.setButtons()
+                               if not sel.navigator:
+                                       self.buildMainMenuList()
+                       elif self.mode == 1:
+                               self.setButtons(red = True)
+                               if not sel.navigator:
+                                       self.buildPlaylistList(addToCache = True)
+                       elif self.mode == 2:
+                               self.setButtons(red = True, green = True, yellow = True, blue = True)
+                               if not sel.navigator:
+                                       self.buildPlaylistSongList(playlistID = sel.playlistID, addToCache = True)
+                       elif self.mode == 4:
+                               self.setButtons(red = True)
+                               if not sel.navigator:
+                                       self.buildArtistList(addToCache = True)
+                       elif self.mode == 5:
+                               self.setButtons(red = True)
+                               if not sel.navigator:
+                                       self.buildArtistAlbumList(sel.artistID, addToCache = True)
+                       elif self.mode == 6:
+                               self.setButtons(red = True, green = True, yellow = True)
+                               if not sel.navigator:
+                                       self.buildAlbumSongList(albumID = sel.albumID, mode = 5, addToCache = True)
+                       elif self.mode == 7:
+                               self.setButtons(red = True)
+                               if not sel.navigator:
+                                       self.buildAlbumList(addToCache = True)
+                       elif self.mode == 8:
+                               self.setButtons(red = True, green = True, yellow = True)
+                               if not sel.navigator:
+                                       self.buildAlbumSongList(albumID = sel.albumID, mode = 7, addToCache = True)
+                       elif self.mode == 10:
+                               self.setButtons(red = True, green = True, yellow = True, blue = True)
+                               if not sel.navigator:
+                                       self.buildSongList(addToCache = True)
+                       elif self.mode == 13:
+                               self.setButtons(red = True)
+                               if not sel.navigator:
+                                       self.buildGenreList(addToCache = True)
+                       elif self.mode == 14:
+                               self.setButtons(red = True, green = True, yellow = True, blue = True)
+                               if not sel.navigator:
+                                       self.buildGenreSongList(genreID = sel.genreID, addToCache = True)
+                       elif self.mode == 18 or self.mode == 19:
+                               if self.mode == 18:
+                                       self.setButtons(red = True, green = True, yellow = True)
+                               if self.mode == 19:
+                                       self.setButtons(red = True, green = True, blue = True)
+                               if not sel.navigator:
+                                       self.red_pressed() # back to main menu --> normally that can not be happened
+                       elif self.mode == 20:
+                               self.setButtons(red = True, green = True, yellow = True, blue = True)
+                               if not sel.navigator:
+                                       self.red_pressed() # back to main menu --> normally that can not be happened
+
+       def buildPlaylistList(self, addToCache):
+               if addToCache:
+                       self.cacheList.append(CacheList(index = self["list"].getCurrentIndex(), listview = self["list"].getList(), headertext = self["headertext"].getText(), methodarguments = self.LastMethod))
+               arguments = {}
+               arguments["addToCache"] = False
+               self.LastMethod = MethodArguments(method = self.buildPlaylistList, arguments = arguments)
+               self["headertext"].setText(_("Playlists"))
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               playlistList = []
+               playlistList.append((Item(text = _("[back]"), mode = 0, navigator = True),))
+               cursor.execute("select playlists.playlist_id, playlist_text, count(Playlist_Songs.playlist_id) from playlists left outer join Playlist_Songs on playlists.playlist_id = Playlist_Songs.playlist_id group by playlists.playlist_id order by playlists.playlist_text;")
+               for row in cursor:
+                       playlistList.append((Item(text = "%s (%d)" % (row[1], row[2]), mode = 2, playlistID = row[0]),))
+               cursor.close() 
+               connection.close()
+               self["list"].setList(playlistList)
+               if len(playlistList) > 1:
+                       self["list"].moveToIndex(1)
+
+       def buildPlaylistSongList(self, playlistID, addToCache):
+               if addToCache:
+                       self.cacheList.append(CacheList(index = self["list"].getCurrentIndex(), listview = self["list"].getList(), headertext = self["headertext"].getText(), methodarguments = self.LastMethod))
+               arguments = {}
+               arguments["playlistID"] = playlistID
+               arguments["addToCache"] = False
+               self.LastMethod = MethodArguments(method = self.buildPlaylistSongList, arguments = arguments)
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               playlistSongList = []
+               playlistSongList.append((Item(text = _("[back]"), mode = 1, navigator = True),))
+               cursor.execute("select songs.song_id, title, artists.artist, filename, songs.artist_id, bitrate, length, genre_text, track, date, album_text, songs.Album_id from songs inner join artists on songs.artist_id = artists.artist_id inner join Album on songs.Album_id = Album.Album_id inner join genre on songs.genre_id = genre.genre_id inner join playlist_songs on songs.song_id = playlist_songs.song_id where playlist_songs.playlist_id =  %d order by playlist_songs.id;" % (playlistID))
+               for row in cursor:
+                       playlistSongList.append((Item(mode = 99, songID = row[0], title = row[1], artist = row[2], filename = row[3], artistID = row[4], bitrate = row[5], length = row[6], genre = row[7], track = row[8], date = row[9], album = row[10], albumID = row[11], playlistID = playlistID),))
+               cursor.execute("SELECT playlist_text from playlists where playlist_id = %d;" % playlistID)
+               row = cursor.fetchone()
+               self["headertext"].setText(_("Playlist (%s) -> Song List") % row[0])
+               cursor.close() 
+               connection.close()
+               self["list"].setList(playlistSongList)
+               if len(playlistSongList) > 1:
+                       self["list"].moveToIndex(1)
+                               
+       def buildGenreList(self, addToCache):
+               if addToCache:
+                       self.cacheList.append(CacheList(index = self["list"].getCurrentIndex(), listview = self["list"].getList(), headertext = self["headertext"].getText(), methodarguments = self.LastMethod))
+               arguments = {}
+               arguments["addToCache"] = False
+               self.LastMethod = MethodArguments(method = self.buildGenreList, arguments = arguments)
+               self["headertext"].setText(_("Genre List"))
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               genreList = []
+               genreList.append((Item(text = _("[back]"), mode = 0, navigator = True),))
+               cursor.execute("select Genre.genre_id,Genre.Genre_text, count(*) from songs inner join Genre on songs.genre_id = Genre.Genre_id group by songs.Genre_id order by Genre.Genre_text;")
+               for row in cursor:
+                       genreList.append((Item(text = "%s (%d)" % (row[1], row[2]), mode = 14, genreID = row[0]),))
+               cursor.close() 
+               connection.close()
+               self["list"].setList(genreList)
+               if len(genreList) > 1:
+                       self["list"].moveToIndex(1)
+
+       def buildGenreSongList(self, genreID, addToCache):
+               if addToCache:
+                       self.cacheList.append(CacheList(index = self["list"].getCurrentIndex(), listview = self["list"].getList(), headertext = self["headertext"].getText(), methodarguments = self.LastMethod))
+               arguments = {}
+               arguments["genreID"] = genreID
+               arguments["addToCache"] = False
+               self.LastMethod = MethodArguments(method = self.buildGenreSongList, arguments = arguments)
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               genreSongList = []
+               genreSongList.append((Item(text = _("[back]"), mode = 13, navigator = True),))
+               cursor.execute("select song_id, title, artists.artist, filename, songs.artist_id, bitrate, length, genre_text, track, date, album_text, songs.Album_id from songs inner join artists on songs.artist_id = artists.artist_id inner join Album on songs.Album_id = Album.Album_id inner join genre on songs.genre_id = genre.genre_id where songs.genre_id = %d order by title, filename;" % (genreID))
+               for row in cursor:
+                       genreSongList.append((Item(mode = 99, songID = row[0], title = row[1], artist = row[2], filename = row[3], artistID = row[4], bitrate = row[5], length = row[6], genre = row[7], track = row[8], date = row[9], album = row[10], albumID = row[11], genreID = genreID),))
+               cursor.execute("SELECT genre_text from genre where genre_ID = %d;" % genreID)
+               row = cursor.fetchone()
+               self["headertext"].setText(_("Genre (%s) -> Song List") % row[0])
+               cursor.close() 
+               connection.close()
+               self["list"].setList(genreSongList)
+               if len(genreSongList) > 1:
+                       self["list"].moveToIndex(1)
+
+       def setButtons(self, red = False, green = False, yellow = False, blue = False):
+               if red:
+                       self["key_red"].setText("Main Menu")
+               else:
+                       self["key_red"].setText("")
+               if green:
+                       self["key_green"].setText("Play")
+               else:
+                       self["key_green"].setText("")
+               if yellow:
+                       self["key_yellow"].setText("All Artists")
+               else:           
+                       self["key_yellow"].setText("")
+               if blue:
+                       self["key_blue"].setText("Show Album")
+               else:
+                       self["key_blue"].setText("")
+
+       def info_pressed(self):
+               if self.player is not None:
+                       if self.player.songList:
+                               self.session.execDialog(self.player)
+
+       def green_pressed(self):
+               sel = self["list"].l.getCurrentSelection()[0]
+               if sel is None:
+                       return
+               if sel.songID != 0:
+                       if self.player is not None:
+                               self.player.doClose()
+                               self.player = None
+                       self.player = self.session.instantiateDialog(MerlinMusicPlayerScreen,self["list"].getList()[1:], self["list"].getCurrentIndex() -1, True)
+                       self.session.execDialog(self.player)
+
+       def red_pressed(self):
+               self.cacheList = []
+               self.setButtons()
+               self.mode = 0
+               self["list"].setMode(self.mode)
+               self.buildMainMenuList()
+       
+       def yellow_pressed(self):
+               sel = self["list"].l.getCurrentSelection()[0]
+               if sel.artistID != 0:
+                       oldmode = self.mode
+                       self.mode = 19
+                       self.setButtons(red = True, green = True, blue = True)
+                       self["list"].setMode(self.mode)
+                       self.buildArtistSongList(artistID = sel.artistID, mode = oldmode, addToCache = True)
+               
+       def blue_pressed(self):
+               sel = self["list"].l.getCurrentSelection()[0]
+               if sel.albumID != 0:
+                       self.setButtons(red = True, green = True, yellow = True)
+                       oldmode = self.mode
+                       self.mode = 18
+                       self["list"].setMode(self.mode)
+                       self.buildAlbumSongList(albumID = sel.albumID, mode = oldmode, addToCache = True)
+       
+       def buildSongList(self, addToCache):
+               if addToCache:
+                       self.cacheList.append(CacheList(index = self["list"].getCurrentIndex(), listview = self["list"].getList(), headertext = self["headertext"].getText(), methodarguments = self.LastMethod))
+               arguments = {}
+               arguments["addToCache"] = False
+               self.LastMethod = MethodArguments(method = self.buildSongList,  arguments = arguments)
+               self["headertext"].setText(_("All Songs"))
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               SongList = []
+               SongList.append((Item(text = _("[back]"), mode = 0, navigator = True),))
+               cursor.execute("select song_id, title, artists.artist, filename, songs.artist_id, bitrate, length, genre_text, track, date, album_text, songs.Album_id from songs inner join artists on songs.artist_id = artists.artist_id inner join Album on songs.Album_id = Album.Album_id inner join genre on songs.genre_id = genre.genre_id order by title, filename;")
+               for row in cursor:
+                       SongList.append((Item(mode = 99, songID = row[0], title = row[1], artist = row[2], filename = row[3], artistID = row[4], bitrate = row[5], length = row[6], genre = row[7], track = row[8], date = row[9], album = row[10], albumID = row[11]),))
+               cursor.close() 
+               connection.close()
+               self["list"].setList(SongList)
+               if len(SongList) > 1:
+                       self["list"].moveToIndex(1)
+
+
+       def buildSearchSongList(self, sql_where, headerText, mode, addToCache):
+               if addToCache:
+                       self.cacheList.append(CacheList(index = self["list"].getCurrentIndex(), listview = self["list"].getList(), headertext = self["headertext"].getText(), methodarguments = self.LastMethod))
+               arguments = {}
+               arguments["sql_where"] = sql_where
+               arguments["headerText"] = headerText
+               arguments["mode"] = mode
+               arguments["addToCache"] = False
+               self.LastMethod = MethodArguments(method = self.buildSearchSongList, arguments = arguments)
+               self["headertext"].setText(headerText)
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               SongList = []
+               SongList.append((Item(text = _("[back]"), mode = mode, navigator = True),))
+               cursor.execute("select song_id, title, artists.artist, filename, songs.artist_id, bitrate, length, genre_text, track, date, album_text, songs.Album_id from songs inner join artists on songs.artist_id = artists.artist_id inner join Album on songs.Album_id = Album.Album_id inner join genre on songs.genre_id = genre.genre_id %s order by title, filename;" % sql_where)
+               for row in cursor:
+                       SongList.append((Item(mode = 99, songID = row[0], title = row[1], artist = row[2], filename = row[3], artistID = row[4], bitrate = row[5], length = row[6], genre = row[7], track = row[8], date = row[9], album = row[10], albumID = row[11]),))
+               cursor.close() 
+               connection.close()
+               self["list"].setList(SongList)
+               if len(SongList) > 1:
+                       self["list"].moveToIndex(1)
+
+       
+       def buildArtistSongList(self, artistID, mode, addToCache):
+               if addToCache:
+                       self.cacheList.append(CacheList(index = self["list"].getCurrentIndex(), listview = self["list"].getList(), headertext = self["headertext"].getText(), methodarguments = self.LastMethod))
+               arguments = {}
+               arguments["artistID"] = artistID
+               arguments["mode"] = mode
+               arguments["addToCache"] = False
+               self.LastMethod = MethodArguments(method = self.buildArtistSongList, arguments = arguments)
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               artistSongList = []
+               artistSongList.append((Item(text = _("[back]"), mode = mode, navigator = True),))
+               cursor.execute("select song_id, title, artists.artist, filename, bitrate, length, genre_text, track, date, album_text, songs.Album_id from songs inner join artists on songs.artist_id = artists.artist_id inner join Album on songs.Album_id = Album.Album_id inner join genre on songs.genre_id = genre.genre_id where songs.artist_id = %d order by Album.album_text, tracknumber, filename;" % (artistID))
+               for row in cursor:
+                       artistSongList.append((Item(mode = 99, songID = row[0], title = row[1], artist = row[2], filename = row[3], bitrate = row[4], length = row[5], genre = row[6], track = row[7], date = row[8], album = row[9], albumID = row[10], artistID = artistID),))
+               cursor.execute("SELECT artist from artists where artist_ID = %d;" % artistID)
+               row = cursor.fetchone()
+               self["headertext"].setText(_("Artist (%s) -> Song List") % row[0])
+               cursor.close() 
+               connection.close()
+               self["list"].setList(artistSongList)
+               if len(artistSongList) > 1:
+                       self["list"].moveToIndex(1)
+                       
+       def buildAlbumSongList(self, albumID, mode, addToCache):
+               if addToCache:
+                       self.cacheList.append(CacheList(index = self["list"].getCurrentIndex(), listview = self["list"].getList(), headertext = self["headertext"].getText(), methodarguments = self.LastMethod))
+               arguments = {}
+               arguments["albumID"] = albumID
+               arguments["mode"] = mode
+               arguments["addToCache"] = False
+               self.LastMethod = MethodArguments(method = self.buildAlbumSongList, arguments = arguments)
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               albumSongList = []
+               albumSongList.append((Item(text = _("[back]"), mode = mode, navigator = True),))
+               cursor.execute("select song_id, title, artists.artist, filename, songs.artist_id, bitrate, length, genre_text, track, date, album_text from songs inner join artists on songs.artist_id = artists.artist_id inner join Album on songs.Album_id = Album.Album_id inner join genre on songs.genre_id = genre.genre_id where songs.album_id = %d order by tracknumber, filename;" % (albumID))
+               for row in cursor:
+                       albumSongList.append((Item(mode = 99, songID = row[0], title = row[1], artist = row[2], filename = row[3], artistID = row[4], bitrate = row[5], length = row[6], genre = row[7], track = row[8], date = row[9], album = row[10], albumID = albumID),))
+               cursor.execute("SELECT album_text from album where album_ID = %d;" % albumID)
+               row = cursor.fetchone()
+               self["headertext"].setText(_("Album (%s) -> Song List") % row[0])
+               cursor.close() 
+               connection.close()
+               self["list"].setList(albumSongList)
+               if len(albumSongList) > 1:
+                       self["list"].moveToIndex(1)
+               
+       def buildMainMenuList(self, addToCache = True):
+               arguments = {}
+               arguments["addToCache"] = True
+               self.LastMethod = MethodArguments(method = self.buildMainMenuList, arguments = arguments)
+               self["headertext"].setText(_("iDream Main Menu"))
+               mainMenuList = []
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               # 1. Playlists
+               cursor.execute("SELECT COUNT (*) FROM playlists;")
+               row = cursor.fetchone()
+               mainMenuList.append((Item(text = _("Playlists (%d)") % row[0], mode = 1),))
+               # 2. Artists
+               cursor.execute("SELECT COUNT (*) FROM artists;")
+               row = cursor.fetchone()
+               mainMenuList.append((Item(text = _("Artists (%d)") % row[0], mode = 4),))
+               # 3. Albums
+               cursor.execute("SELECT COUNT (DISTINCT album_text) FROM album;")
+               row = cursor.fetchone()
+               mainMenuList.append((Item(text = _("Albums (%d)") % row[0], mode = 7),))
+               # 4. Songs
+               cursor.execute("SELECT COUNT (*) FROM songs;")
+               row = cursor.fetchone()
+               mainMenuList.append((Item(text = _("Songs (%d)") % row[0], mode = 10),))
+               # 5. Genres
+               cursor.execute("SELECT COUNT (*) FROM genre;")
+               row = cursor.fetchone()
+               mainMenuList.append((Item(text = _("Genres (%d)") % row[0], mode = 13),))
+               cursor.close()  
+               connection.close()
+               self["list"].setList(mainMenuList)
+               self["list"].moveToIndex(0)
+               
+       def buildArtistList(self, addToCache):
+               if addToCache:
+                       self.cacheList.append(CacheList(index = self["list"].getCurrentIndex(), listview = self["list"].getList(), headertext = self["headertext"].getText(), methodarguments = self.LastMethod))
+               arguments = {}
+               arguments["addToCache"] = False
+               self.LastMethod = MethodArguments(method = self.buildArtistList, arguments = arguments)
+               self["headertext"].setText(_("Artists List"))
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               artistList = []
+               artistList.append((Item(text = _("[back]"), mode = 0, navigator = True),))
+               cursor.execute("SELECT artists.artist_id,artists.artist, count (distinct album.album_text) FROM songs INNER JOIN artists ON songs.artist_id = artists.artist_id inner join album on songs.album_id =  album.album_id GROUP BY songs.artist_id ORDER BY artists.artist;")
+               for row in cursor:
+                       artistList.append((Item(text = "%s (%d)" % (row[1], row[2]), mode = 5, artistID = row[0]),))
+               cursor.close() 
+               connection.close()
+               self["list"].setList(artistList)
+               
+       def buildArtistAlbumList(self, ArtistID, addToCache):
+               if addToCache:
+                       self.cacheList.append(CacheList(index = self["list"].getCurrentIndex(), listview = self["list"].getList(), headertext = self["headertext"].getText(), methodarguments = self.LastMethod))
+               arguments = {}
+               arguments["ArtistID"] = ArtistID
+               arguments["addToCache"] = False
+               self.LastMethod = MethodArguments(method = self.buildArtistAlbumList, arguments = arguments)
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               albumArtistList = []
+               albumArtistList.append((Item(text = _("[back]"), mode = 4, navigator = True),))
+               cursor.execute("select Album.Album_id,Album.Album_text from songs inner join Album on songs.Album_id = Album.Album_id where songs.artist_id = %d group by songs.Album_id order by Album.Album_text;" % ArtistID)
+               for row in cursor:
+                       cursor2 = connection.cursor()
+                       cursor2.execute("select count(song_id) from songs where album_id = %d;" % row[0])
+                       row2 = cursor2.fetchone()
+                       albumArtistList.append((Item(text = "%s (%d)" % (row[1], row2[0]), mode = 6, albumID = row[0], artistID = ArtistID),))
+                       cursor2.close()
+               cursor.execute("SELECT artist from artists where artist_ID = %d;" % ArtistID)
+               row = cursor.fetchone()
+               self["headertext"].setText(_("Artist (%s) -> Album List") % row[0])
+               cursor.close() 
+               connection.close()
+               self["list"].setList(albumArtistList)
+               if len(albumArtistList) > 1:
+                       self["list"].moveToIndex(1)
+                       
+       def buildAlbumList(self, addToCache):
+               if addToCache:
+                       self.cacheList.append(CacheList(index = self["list"].getCurrentIndex(), listview = self["list"].getList(), headertext = self["headertext"].getText(), methodarguments = self.LastMethod))
+               arguments = {}
+               arguments["addToCache"] = False
+               self.LastMethod = MethodArguments(method = self.buildAlbumList, arguments = arguments)
+               self["headertext"].setText(_("Albums List"))
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               albumList = []
+               albumList.append((Item(text = _("[back]"), mode = 0, navigator = True),))
+               cursor.execute("select Album.Album_id,Album.Album_text, count(*) from songs inner join Album on songs.Album_id = Album.Album_id group by songs.Album_id order by Album.Album_text;")
+               for row in cursor:
+                       albumList.append((Item(text = "%s (%d)" % (row[1], row[2]), mode = 8, albumID = row[0]),))
+               cursor.close() 
+               connection.close()
+               self["list"].setList(albumList)
+               if len(albumList) > 1:
+                       self["list"].moveToIndex(1)
+                       
+       def startRun(self):
+               if pathToDatabase.isRunning:
+                       self.showScanner = eTimer()
+                       self.showScanner.callback.append(self.showScannerCallback)
+                       self.showScanner.start(0,1)
+               else:
+                       if config.plugins.merlinmusicplayer.startlastsonglist.value:
+                               self.startPlayerTimer = eTimer()
+                               self.startPlayerTimer.callback.append(self.startPlayerTimerCallback)
+                               self.startPlayerTimer.start(0,1)
+                       self.mode = 0
+                       self["list"].setMode(self.mode)
+                       self.buildMainMenuList()
+
+       def showScannerCallback(self):
+               self.session.openWithCallback(self.filesAdded, iDreamAddToDatabase,None)
+
+
+       def startPlayerTimerCallback(self):
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               iDreamMode = False
+               SongList = []
+               cursor.execute("select song_id, filename, title, artist, album, genre, bitrate, length,  track, date, PTS from CurrentSongList;")
+               for row in cursor:
+                       SongList.append((Item(songID = row[0], text = os_path.basename(row[1]), filename = row[1], title = row[2], artist = row[3], album = row[4], genre = row[5],  bitrate = row[6], length = row[7], track = row[8], date = row[9], PTS = row[10], join = False),))
+                       if row[0] != 0:
+                               iDreamMode = True
+               cursor.close() 
+               connection.close()
+               if self.player is not None:
+                       self.player.doClose()
+                       self.player = None
+               count = len(SongList)
+               if count:
+                       # just to be sure, check the index , it's critical
+                       index = config.plugins.merlinmusicplayer.lastsonglistindex.value
+                       if index >= count:
+                               index = 0
+                       self.player = self.session.instantiateDialog(MerlinMusicPlayerScreen,SongList, index, iDreamMode)
+                       self.session.execDialog(self.player)
+
+       def config(self):
+               self.session.openWithCallback(self.setupFinished, MerlinMusicPlayerSetup, True)
+
+       def setupFinished(self, result):
+               if result:
+                       self.red_pressed()
+
+       def Error(self, error = None):
+               if error is not None:
+                       self["list"].hide()
+                       self["statustext"].setText(str(error.getErrorMessage()))
+                       
+       def closing(self):
+               self.close()
+               
+       def __onClose(self):
+               if self.player is not None:
+                       self.player.doClose()
+                       self.player = None
+               self.session.nav.playService(self.CurrentService)
+
+       def lcdUpdate(self):
+               try:
+                       count = self["list"].getItemCount()
+                       index = self["list"].getCurrentIndex()
+                       iDreamList = self["list"].getList()
+                       self.summaries.setText(iDreamList[index][0].title or iDreamList[index][0].text,1)
+                       # voheriges
+                       index -= 1
+                       if index < 0:
+                               index = count
+                       self.summaries.setText(iDreamList[index][0].title or iDreamList[index][0].text,3)
+                       # naechstes
+                       index = self["list"].getCurrentIndex() + 1
+                       if index > count:
+                               index = 0
+                       self.summaries.setText(iDreamList[index][0].title or iDreamList[index][0].text,4)
+               except: pass
+
+       def createSummary(self):
+               return MerlinMusicPlayerLCDScreenText
+
+               
+class iDreamList(GUIComponent, object):
+       def buildEntry(self, item):
+               width = self.l.getItemSize().width()
+               res = [ None ]
+               if self.displaySongMode:
+                       if item.navigator:
+                               res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 3, width , 20, 0, RT_HALIGN_CENTER|RT_VALIGN_CENTER, "%s" % item.text))
+                       else:
+                               res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 3, width - 100 , 20, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, "%s - %s" % (item.title, item.artist)))
+                               res.append((eListboxPythonMultiContent.TYPE_TEXT, width - 100,3,100, 20, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, "%s" % item.track))
+                               res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 26,width -200, 18, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, "%s%s" % (item.album, item.date)))
+                               res.append((eListboxPythonMultiContent.TYPE_TEXT, width -200, 26,200, 18, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, "%s" % item.length))
+                               res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 47,width -200, 18, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, "%s" % item.genre))
+                               res.append((eListboxPythonMultiContent.TYPE_TEXT, width -200, 47,200, 18, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, "%s" % item.bitrate))
+               else:
+                       if item.navigator:
+                               res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 3, width , 20, 0, RT_HALIGN_CENTER|RT_VALIGN_CENTER, "%s" % item.text))
+                       else:
+                               if item.PTS is None:
+                                       res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 3, width , 20, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, "%s" % item.text))
+                               else:
+                                       res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 3, width , 20, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, "%s" % item.title))
+               
+               return res
+       
+       def __init__(self):
+               GUIComponent.__init__(self)
+               self.l = eListboxPythonMultiContent()
+               self.l.setBuildFunc(self.buildEntry)
+               self.l.setFont(0, gFont("Regular", 20))
+               self.l.setFont(1, gFont("Regular", 16))
+               self.l.setItemHeight(22)
+               self.onSelectionChanged = [ ]
+               self.mode = 0
+               self.displaySongMode = False
+               self.list = []
+               self.itemCount = 0
+
+       def connectSelChanged(self, fnc):
+               if not fnc in self.onSelectionChanged:
+                       self.onSelectionChanged.append(fnc)
+
+       def disconnectSelChanged(self, fnc):
+               if fnc in self.onSelectionChanged:
+                       self.onSelectionChanged.remove(fnc)
+
+       def selectionChanged(self):
+               for x in self.onSelectionChanged:
+                       x()
+       
+       def getCurrent(self):
+               cur = self.l.getCurrentSelection()
+               return cur and cur[0]
+       
+       GUI_WIDGET = eListbox
+       
+       def postWidgetCreate(self, instance):
+               instance.setContent(self.l)
+               instance.selectionChanged.get().append(self.selectionChanged)
+
+       def preWidgetRemove(self, instance):
+               instance.setContent(None)
+               instance.selectionChanged.get().remove(self.selectionChanged)
+
+       def moveToIndex(self, index):
+               self.instance.moveSelectionTo(index)
+
+       def getCurrentIndex(self):
+               return self.instance.getCurrentIndex()
+
+       currentIndex = property(getCurrentIndex, moveToIndex)
+       currentSelection = property(getCurrent)
+
+       def setList(self, list):
+               self.list = list
+               self.l.setList(list)
+               self.itemCount = len(self.list) - 1
+       
+       def getItemCount(self):
+               return  self.itemCount
+
+       def getList(self):
+               return self.list
+
+       def removeItem(self, index):
+               del self.list[index]
+               self.l.entryRemoved(index)
+
+       def getDisplaySongMode(self):
+               return self.displaySongMode
+               
+       def setMode(self, mode):
+               self.mode = mode
+               if mode == 2 or mode == 6 or mode == 8 or mode == 10 or mode == 18 or mode == 19 or mode == 14 or mode == 20:
+                       self.displaySongMode = True
+                       self.l.setItemHeight(68)
+               else:
+                       self.displaySongMode = False
+                       self.l.setItemHeight(22)
+
+
+class MerlinMediaPixmap(Pixmap):
+       def __init__(self):
+               Pixmap.__init__(self)
+               self.coverArtFileName = ""
+               self.picload = ePicLoad()
+               self.picload.PictureData.get().append(self.paintCoverArtPixmapCB)
+               self.coverFileNames = ["folder.png", "folder.jpg", "cover.jpg", "cover.png", "coverArt.jpg"]
+
+       def applySkin(self, desktop, screen):
+               from Tools.LoadPixmap import LoadPixmap
+               noCoverFile = None
+               if self.skinAttributes is not None:
+                       for (attrib, value) in self.skinAttributes:
+                               if attrib == "pixmap":
+                                       noCoverFile = value
+                                       break
+               if noCoverFile is None:
+                       noCoverFile = resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/no_coverArt.png")
+               self.noCoverPixmap = LoadPixmap(noCoverFile)
+               return Pixmap.applySkin(self, desktop, screen)
+
+       def onShow(self):
+               Pixmap.onShow(self)
+               sc = AVSwitch().getFramebufferScale()
+               self.picload.setPara((self.instance.size().width(), self.instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
+
+       def paintCoverArtPixmapCB(self, picInfo=None):
+               ptr = self.picload.getData()
+               if ptr != None:
+                       self.instance.setPixmap(ptr.__deref__())
+
+       def updateCoverArt(self, path):
+               back = False
+               while not path.endswith("/"):
+                       path = path[:-1]
+               new_coverArtFileName = None
+               for filename in self.coverFileNames:
+                       if fileExists(path + filename):
+                               new_coverArtFileName = path + filename
+               if self.coverArtFileName != new_coverArtFileName:
+                       if new_coverArtFileName:
+                               self.coverArtFileName = new_coverArtFileName
+                               print "[MerlinMusicPlayer] using cover from %s " % self.coverArtFileName
+                               self.picload.startDecode(self.coverArtFileName)
+                               back = True
+               else:
+                       if new_coverArtFileName:
+                               back = True
+               return back
+
+       def showDefaultCover(self):
+               self.coverArtFileName = ""
+               self.instance.setPixmap(self.noCoverPixmap)
+
+       def showCoverFromFile(self, filename):
+               self.coverArtFileName = filename
+               self.picload.startDecode(self.coverArtFileName)
+
+       def embeddedCoverArt(self):
+               print "[embeddedCoverArt] found"
+               self.coverArtFileName = "/tmp/.id3coverart"
+               self.picload.startDecode(self.coverArtFileName)
+
+
+class SelectPath(Screen):
+       skin = """<screen name="SelectPath" position="center,center" size="560,320" title="Select path">
+                       <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
+                       <widget name="target" position="0,60" size="540,22" valign="center" font="Regular;22" />
+                       <widget name="filelist" position="0,100" zPosition="1" size="560,220" scrollbarMode="showOnDemand"/>
+                       <widget render="Label" source="key_red" position="0,0" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                       <widget render="Label" source="key_green" position="140,0" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+               </screen>"""
+       def __init__(self, session, initDir):
+               Screen.__init__(self, session)
+               inhibitDirs = ["/bin", "/boot", "/dev", "/etc", "/lib", "/proc", "/sbin", "/sys", "/usr", "/var"]
+               inhibitMounts = []
+               self["filelist"] = FileList(initDir, showDirectories = True, showFiles = False, inhibitMounts = inhibitMounts, inhibitDirs = inhibitDirs)
+               self["target"] = Label()
+               self["actions"] = ActionMap(["WizardActions", "DirectionActions", "ColorActions", "EPGSelectActions"],
+               {
+                       "back": self.cancel,
+                       "left": self.left,
+                       "right": self.right,
+                       "up": self.up,
+                       "down": self.down,
+                       "ok": self.ok,
+                       "green": self.green,
+                       "red": self.cancel
+                       
+               }, -1)
+               self["key_red"] = StaticText(_("Cancel"))
+               self["key_green"] = StaticText(_("OK"))
+
+       def cancel(self):
+               self.close(None)
+
+       def green(self):
+               self.close(self["filelist"].getSelection()[0])
+
+       def up(self):
+               self["filelist"].up()
+               self.updateTarget()
+
+       def down(self):
+               self["filelist"].down()
+               self.updateTarget()
+
+       def left(self):
+               self["filelist"].pageUp()
+               self.updateTarget()
+
+       def right(self):
+               self["filelist"].pageDown()
+               self.updateTarget()
+
+       def ok(self):
+               if self["filelist"].canDescent():
+                       self["filelist"].descent()
+                       self.updateTarget()
+
+       def updateTarget(self):
+               currFolder = self["filelist"].getSelection()[0]
+               if currFolder is not None:
+                       self["target"].setText(currFolder)
+               else:
+                       self["target"].setText(_("Invalid Location"))
+
+
+class MerlinMusicPlayerLCDScreen(Screen):
+       skin = """
+               <screen position="0,0" size="132,64">
+                       <widget source="session.CurrentService" render="Label" position="4,0" size="132,12" valign="top" font="Regular;10" halign="center">
+                               <convert type="ServicePosition">Position,ShowHours</convert>
+                       </widget>
+                       <widget name="text1" position="4,14" size="132,35" halign="center" valign="top" font="Regular;14"/>
+                       <widget name="text4" position="4,51" size="132,12" halign="center" valign="top" font="Regular;10"/>
+               </screen>"""
+
+       def __init__(self, session, parent):
+               Screen.__init__(self, session)
+               self["text1"] = Label()
+               self["text4"] = Label()
+
+       def setText(self, text, line):
+               if line == 1:
+                       self["text1"].setText(text)
+               elif line == 4:
+                       self["text4"].setText(text)
+
+class MerlinMusicPlayerLCDScreenText(Screen):
+       skin = """
+               <screen position="0,0" size="132,64">
+                       <widget name="text3" position="4,0" size="132,14" font="Regular;10"/>
+                       <widget name="text1" position="4,14" size="132,35" font="Regular;14"/>
+                       <widget name="text4" position="4,49" size="132,14" font="Regular;10"/>
+               </screen>"""
+
+       def __init__(self, session, parent):
+               Screen.__init__(self, session)
+               self["text1"] = Label()
+               self["text3"] = Label()
+               self["text4"] = Label()
+
+       def setText(self, text, line):
+               textleer = "    "
+               text = text + textleer*10
+               if line == 1:
+                       self["text1"].setText(text)
+               elif line == 3:
+                       self["text3"].setText(text)
+               elif line == 4:
+                       self["text4"].setText(text)
+
+
+class MerlinMusicPlayerSetup(Screen, ConfigListScreen):
+
+       sz_w = getDesktop(0).size().width()
+       if sz_w == 1280:
+               skin = """
+                       <screen position="0,0" size="1280,720" flags="wfNoBorder" backgroundColor="#00000000" title="Merlin Music Player Setup" >
+                               <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/mmpborderHD.png" position="128,72" size="1024,576"/>
+                               <ePixmap position="178,102" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
+                               <ePixmap position="328,102" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
+                               <widget render="Label" source="key_red" position="178,102" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget render="Label" source="key_green" position="328,102" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget name="config" position="178,152" size="924,350" backgroundColor="#00000000" scrollbarMode="showOnDemand" />
+                       </screen>"""
+
+       elif sz_w == 1024:
+               skin = """
+                       <screen position="0,0" size="1024,576" flags="wfNoBorder" backgroundColor="#00000000" title="Merlin Music Player Setup" >
+                               <ePixmap position="50,30" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
+                               <ePixmap position="200,30" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
+                               <widget render="Label" source="key_red" position="50,30" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget render="Label" source="key_green" position="200,30" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget name="config" position="50,80" size="924,350" backgroundColor="#00000000" scrollbarMode="showOnDemand" />
+                       </screen>"""
+       else:
+               skin = """
+                       <screen name="MerlinMusicPlayerFileList" position="0,0" size="720,576" flags="wfNoBorder" backgroundColor="#00000000" title="Merlin Music Player Setup">
+                               <ePixmap position="50,30" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
+                               <ePixmap position="200,30" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
+                               <widget render="Label" source="key_red" position="50,30" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget render="Label" source="key_green" position="200,30" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
+                               <widget name="config" position="50,80" size="620,350" backgroundColor="#00000000" scrollbarMode="showOnDemand" />
+                       </screen>"""
+
+
+       def __init__(self, session, databasePath):
+               Screen.__init__(self, session)
+
+               self["key_red"] = StaticText(_("Cancel"))
+               self["key_green"] = StaticText(_("OK"))
+
+               self.list = [ ]
+               if HardwareInfo().get_device_name() != "dm7025":
+                       self.list.append(getConfigListEntry(_("Use hardware-decoder for MP3"), config.plugins.merlinmusicplayer.hardwaredecoder))
+               self.list.append(getConfigListEntry(_("Play last used songlist after starting"), config.plugins.merlinmusicplayer.startlastsonglist))
+               if databasePath:
+                       self.database = getConfigListEntry(_("iDream database path"), config.plugins.merlinmusicplayer.databasepath)
+                       self.list.append(self.database)
+               else:
+                       self.database = None
+               self.list.append(getConfigListEntry(_("Use google-images for cover art"), config.plugins.merlinmusicplayer.usegoogleimage))
+               self.googleimage = getConfigListEntry(_("Google image path"), config.plugins.merlinmusicplayer.googleimagepath)
+               self.list.append(self.googleimage)
+               self.list.append(getConfigListEntry(_("Activate screensaver"), config.plugins.merlinmusicplayer.usescreensaver))
+               self.list.append(getConfigListEntry(_("Wait for screensaver (in min)"), config.plugins.merlinmusicplayer.screensaverwait))
+               self.list.append(getConfigListEntry(_("Remember last path of filebrowser"), config.plugins.merlinmusicplayer.rememberlastfilebrowserpath))
+               self.defaultFileBrowserPath = getConfigListEntry(_("Filebrowser startup path"), config.plugins.merlinmusicplayer.defaultfilebrowserpath)
+               self.list.append(self.defaultFileBrowserPath)
+               self.list.append(getConfigListEntry(_("Show iDream in extended-pluginlist"), config.plugins.merlinmusicplayer.idreamextendedpluginlist))
+               self.list.append(getConfigListEntry(_("Show Merlin Music Player in extended-pluginlist"), config.plugins.merlinmusicplayer.merlinmusicplayerextendedpluginlist))
+
+               ConfigListScreen.__init__(self, self.list, session)
+               self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
+               {
+                       "green": self.keySave,
+                       "cancel": self.keyClose,
+                       "ok": self.keySelect,
+               }, -2)
+
+       def keySelect(self):
+               cur = self["config"].getCurrent()
+               if cur == self.database:
+                       self.session.openWithCallback(self.pathSelectedDatabase,SelectPath,config.plugins.merlinmusicplayer.databasepath.value)
+               elif cur == self.defaultFileBrowserPath:
+                       self.session.openWithCallback(self.pathSelectedFilebrowser,SelectPath,config.plugins.merlinmusicplayer.defaultfilebrowserpath.value)
+               elif cur == self.googleimage:
+                       self.session.openWithCallback(self.pathSelectedGoogleImage,SelectPath,config.plugins.merlinmusicplayer.googleimagepath.value)
+
+       def pathSelectedGoogleImage(self, res):
+               if res is not None:
+                       config.plugins.merlinmusicplayer.googleimagepath.value = res
+
+       def pathSelectedDatabase(self, res):
+               if res is not None:
+                       config.plugins.merlinmusicplayer.databasepath.value = res
+
+       def pathSelectedFilebrowser(self, res):
+               if res is not None:
+                       config.plugins.merlinmusicplayer.defaultfilebrowserpath.value = res
+
+       def keySave(self):
+               for x in self["config"].list:
+                       x[1].save()
+               configfile.save()
+               self.close(True)
+
+       def keyClose(self):
+               for x in self["config"].list:
+                       x[1].cancel()
+               self.close(False)
+
+
+
+class MerlinMusicPlayerFileList(Screen):
+       
+       sz_w = getDesktop(0).size().width()
+       if sz_w == 1280:
+               skin = """
+                       <screen name="MerlinMusicPlayerFileList" position="0,0" size="1280,720" flags="wfNoBorder" backgroundColor="#00000000" title="iDream">
+                       <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinMusicPlayer/images/mmpborderHD.png" position="128,72" size="1024,576"/>
+                       <eLabel backgroundColor="#999999" position="178,112" size="924,2" zPosition="1"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="178,104" size="250,20" text="MERLIN  MUSIC  PLAYER" valign="center" zPosition="2"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="852,104" size="250,20" text="WWW.DREAMBOX-TOOLS.INFO" valign="center" zPosition="2"/>
+                       <widget name="headertext" position="178,145" zPosition="1" size="900,23" font="Regular;20" transparent="1"  foregroundColor="#fcc000" backgroundColor="#00000000"/>
+                       <widget name="list" position="178,182" zPosition="2" size="940,350" scrollbarMode="showOnDemand" transparent="0"  backgroundColor="#00000000"/>                         
+                       </screen>"""
+       elif sz_w == 1024:
+               skin = """
+                       <screen name="MerlinMusicPlayerFileList" position="0,0" size="1024,576" flags="wfNoBorder" backgroundColor="#00000000" title="iDream">
+                       <eLabel backgroundColor="#999999" position="50,40" size="924,2" zPosition="1"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="50,32" size="250,20" text="MERLIN  MUSIC  PLAYER" valign="center" zPosition="2"/>
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="724,32" size="250,20" text="WWW.DREAMBOX-TOOLS.INFO" valign="center" zPosition="2"/>
+                       <widget name="headertext" position="50,73" zPosition="1" size="900,23" font="Regular;20" transparent="1"  foregroundColor="#fcc000" backgroundColor="#00000000"/>
+                       <widget name="list" position="50,110" zPosition="2" size="940,350" scrollbarMode="showOnDemand" transparent="0"  backgroundColor="#00000000"/>
+                       </screen>"""
+       else:
+               skin = """
+                       <screen name="MerlinMusicPlayerFileList" position="0,0" size="720,576" flags="wfNoBorder" backgroundColor="#00000000" title="iDream">
+                       <eLabel backgroundColor="#999999" position="50,50" size="620,2" zPosition="1"/>\r
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="50,40" size="250,20" text="MERLIN  MUSIC  PLAYER" valign="center" zPosition="2"/>\r
+                       <eLabel backgroundColor="#999999" font="Regular;16" foregroundColor="#0f0f0f" halign="center" position="420,40" size="250,20" text="WWW.DREAMBOX-TOOLS.INFO" valign="center" zPosition="2"/>
+
+                       <widget name="headertext" position="50,73" zPosition="1" size="620,23" font="Regular;20" transparent="1"  foregroundColor="#fcc000" backgroundColor="#00000000"/>
+                       <widget name="list" position="50,110" zPosition="2" size="620,350" scrollbarMode="showOnDemand" transparent="0"  backgroundColor="#00000000"/>
+                       </screen>"""
+               
+       
+       def __init__(self, session):
+               self.session = session
+               Screen.__init__(self, session)
+               self["list"] = FileList(config.plugins.merlinmusicplayer.defaultfilebrowserpath.value, showDirectories = True, showFiles = True, matchingPattern = "(?i)^.*\.(mp3|m4a|flac|ogg|m3u|pls|cue)", useServiceRef = False)
+
+
+               self["actions"] = ActionMap(["WizardActions", "DirectionActions", "ColorActions", "EPGSelectActions"],
+               {
+                       "ok": self.ok,
+                       "back": self.close,
+                       "input_date_time": self.config,
+                       "info" : self.info_pressed,
+               }, -1)
+
+               self["headertext"] = Label(_("Filelist"))
+               self.player = None
+               self.onClose.append(self.__onClose)
+               self.onLayoutFinish.append(self.startRun)
+               self.CurrentService = self.session.nav.getCurrentlyPlayingServiceReference()
+               self.session.nav.stopService()
+
+       def startRun(self):
+               if config.plugins.merlinmusicplayer.startlastsonglist.value:
+                       self.startPlayerTimer = eTimer()
+                       self.startPlayerTimer.callback.append(self.startPlayerTimerCallback)
+                       self.startPlayerTimer.start(0,1)
+
+       def startPlayerTimerCallback(self):
+               connection = OpenDatabase()
+               connection.text_factory = str
+               cursor = connection.cursor()
+               iDreamMode = False
+               SongList = []
+               cursor.execute("select song_id, filename, title, artist, album, genre, bitrate, length,  track, date, PTS from CurrentSongList;")
+               for row in cursor:
+                       SongList.append((Item(songID = row[0], text = os_path.basename(row[1]), filename = row[1], title = row[2], artist = row[3], album = row[4], genre = row[5],  bitrate = row[6], length = row[7], track = row[8], date = row[9], PTS = row[10], join = False),))
+                       if row[0] != 0:
+                               iDreamMode = True
+               cursor.close() 
+               connection.close()
+               if self.player is not None:
+                       self.player.doClose()
+                       self.player = None
+               count = len(SongList)
+               if count:
+                       # just to be sure, check the index , it's critical
+                       index = config.plugins.merlinmusicplayer.lastsonglistindex.value
+                       if index >= count:
+                               index = 0
+                       self.player = self.session.instantiateDialog(MerlinMusicPlayerScreen,SongList, index, iDreamMode)
+                       self.session.execDialog(self.player)
+       
+       def readCUE(self, filename):
+               SongList = []
+               displayname = None
+               try:
+                       cuefile = open(filename, "r")
+               except IOError:
+                       return None
+               import re
+               performer_re = re.compile(r"""PERFORMER "(?P<performer>.*?)"(?:=\r\n|\r|\n|$)""")
+               title_re = re.compile(r"""TITLE "(?P<title>.*?)"(?:=\r\n|\r|\n|$)""")
+               filename_re = re.compile(r"""FILE "(?P<filename>.+?)".*(?:=\r\n|\r|\n|$)""", re.DOTALL)
+               track_re = re.compile(r"""TRACK (?P<track_number>[^ ]+?)(?:[ ]+.*?)(?:=\r\n|\r|\n|$)""")
+               index_re = re.compile(r"""INDEX (?P<index_nr>[^ ]+?)[ ]+(?P<track_index>[^ ]+?)(?:=\r\n|\r|\n|$)""")
+               msts_re = re.compile("""^(?P<mins>[0-9]{1,}):(?P<secs>[0-9]{2}):(?P<ms>[0-9]{2})$""")
+               songfilename = ""
+               album = ""
+               performer = ""
+               title = ""
+               pts = 0
+               state = 0 # header
+               for line in cuefile.readlines():
+                       entry = line.strip()
+                       m = filename_re.search(entry)
+                       if m:
+                               if  m.group('filename')[0] == "/":
+                                       songfilename = m.group('filename')
+                               else:
+                                       songfilename = os_path.dirname(filename) + "/" + m.group('filename')
+                       m = title_re.search(entry)
+                       if m:
+                               if state == 0:
+                                       album = m.group('title')
+                               else:
+                                       title = m.group('title')
+                       m = performer_re.search(entry)
+                       if m:
+                               performer = m.group('performer')
+                       m = track_re.search(entry)
+                       if m:
+                               state = 1 # tracks
+                       m = index_re.search(entry)
+                       if m:
+                               if int(m.group('index_nr')) == 1:
+                                       m1 = msts_re.search(m.group('track_index'))
+                                       if m1:
+                                               pts = (int(m1.group('mins')) * 60 + int(m1.group('secs'))) * 90000
+                                               SongList.append((Item(text = title, filename = songfilename, title = title, artist = performer, album = album,join = False, PTS = pts),))
+               cuefile.close()
+               return SongList
+
+       def readM3U(self, filename):
+               SongList = []
+               displayname = None
+               try:
+                       m3ufile = open(filename, "r")
+               except IOError:
+                       return None
+               for line in m3ufile.readlines():
+                       entry = line.strip()
+                       if entry != "":
+                               if entry.startswith("#EXTINF:"):
+                                       extinf = entry.split(',',1)
+                                       if len(extinf) > 1:
+                                               displayname = extinf[1]
+                               elif entry[0] != "#":
+                                       if entry[0] == "/":
+                                               songfilename = entry
+                                       else:
+                                               songfilename = os_path.dirname(filename) + "/" + entry
+                                       if displayname:
+                                               text = displayname
+                                               displayname = None
+                                       else:
+                                               text = entry
+                                       SongList.append((Item(text = text, filename = songfilename),))
+               m3ufile.close()
+               return SongList
+
+       def readPLS(self, filename):
+               SongList = []
+               displayname = None
+               try:
+                       plsfile = open(filename, "r")
+               except IOError:
+                       return None
+               entry = plsfile.readline().strip()
+               if entry == "[playlist]":
+                       while True:
+                               entry = plsfile.readline().strip()
+                               if entry == "":
+                                       break
+                               if entry[0:4] == "File":
+                                       pos = entry.find('=') + 1
+                                       newentry = entry[pos:]
+                                       SongList.append((Item(text = newentry, filename = newentry),))
+               else:
+                       SongList = self.readM3U(filename)
+               plsfile.close()
+               return SongList
+
+       def ok(self):
+               if self["list"].canDescent():
+                       self["list"].descent()
+               else:
+                       SongList = []
+                       index = 0
+                       foundIndex = 0
+                       count = 0
+                       currentFilename = self["list"].getFilename()
+                       if currentFilename.lower().endswith(".m3u"):
+                               SongList = self.readM3U(os_path.join(self["list"].getCurrentDirectory(),currentFilename))
+                       elif currentFilename.lower().endswith(".pls"):
+                               SongList = self.readPLS(os_path.join(self["list"].getCurrentDirectory(),currentFilename))
+                       elif currentFilename.lower().endswith(".cue"):
+                               SongList = self.readCUE(os_path.join(self["list"].getCurrentDirectory(),currentFilename))
+                       else:
+                               files = os_listdir(self["list"].getCurrentDirectory())
+                               files.sort()
+                               for filename in files:
+                                       if filename.lower().endswith(".mp3") or filename.lower().endswith(".flac") or filename.lower().endswith(".m4a") or filename.lower().endswith(".ogg"):
+                                               SongList.append((Item(text = filename, filename = os_path.join(self["list"].getCurrentDirectory(),filename)),))
+                                               if self["list"].getFilename() == filename:
+                                                       foundIndex = index
+                                               index += 1
+                       if self.player is not None:
+                               self.player.doClose()
+                               self.player = None
+                       count = len(SongList)
+                       if count:
+                               self.player = self.session.instantiateDialog(MerlinMusicPlayerScreen,SongList, foundIndex, False)
+                               self.session.execDialog(self.player)
+                       else:
+                               self.session.open(MessageBox, _("No music files found!"), type = MessageBox.TYPE_INFO,timeout = 20 )
+
+       def config(self):
+               self.session.open(MerlinMusicPlayerSetup, True)
+
+       def info_pressed(self):
+               if self.player is not None:
+                       if self.player.songList:
+                               self.session.execDialog(self.player)
+
+       def __onClose(self):
+               if self.player is not None:
+                       self.player.doClose()
+                       self.player = None
+               self.session.nav.playService(self.CurrentService)
+               if config.plugins.merlinmusicplayer.rememberlastfilebrowserpath.value:
+                       config.plugins.merlinmusicplayer.defaultfilebrowserpath.value = self["list"].getCurrentDirectory()
+                       config.plugins.merlinmusicplayer.defaultfilebrowserpath.save()
+
+
+def main(session,**kwargs):
+       session.open(iDreamMerlin)
+
+def merlinmusicplayerfilelist(session,**kwargs):
+       session.open(MerlinMusicPlayerFileList)
+
+def Plugins(**kwargs):
+
+       list = [PluginDescriptor(name="Merlin iDream", description=_("Dreambox Music Database"), where = [PluginDescriptor.WHERE_PLUGINMENU], icon = "iDream.png", fnc=main)]
+       list.append(PluginDescriptor(name="Merlin Music Player", description=_("Merlin Music Player"), where = [PluginDescriptor.WHERE_PLUGINMENU], icon = "MerlinMusicPlayer.png", fnc=merlinmusicplayerfilelist))
+       if config.plugins.merlinmusicplayer.idreamextendedpluginlist.value:
+               list.append(PluginDescriptor(name="iDream", description=_("Dreambox Music Database"), where = [PluginDescriptor.WHERE_EXTENSIONSMENU], fnc=main))
+       if config.plugins.merlinmusicplayer.merlinmusicplayerextendedpluginlist.value:
+               list.append(PluginDescriptor(name="Merlin Music Player", description=_("Merlin Music Player"), where = [PluginDescriptor.WHERE_EXTENSIONSMENU], fnc=merlinmusicplayerfilelist))
+       return list
+