#!/usr/bin/python
# coding=utf-8
#*********************************************************************
# $Id: mpdtouchgui.py 293 2008-08-18 15:29:08Z timo $
#
# PyMPDTouchGui
# Gui for controlling the MusicPlayDaemon on Touchscreens
#
# written by Timo Boettcher
# pympdtouchgui (near) spida (.) net
#
# (C) 2007,2008 Timo Boettcher
# This is free software. You may redistribute copies of it under the
# terms of the GNU General Public License (Version 2)
# <http://www.gnu.org/licenses/gpl.html>.
# There is NO WARRANTY, to the extent permitted by law.
#
#*********************************************************************


try:
	import sys
	import getopt
	import os
	import ConfigParser
	import pygame
	import time
	import datetime
	from pygame import image
	import pygame.locals
	import libpympdtouchgui.mpdclient3 as mpdclient3
	import libpympdtouchgui.events as events
	import libpympdtouchgui.gui as gui
	import gc
except ImportError, err:
	print "couldn't load module. %s"%(err)
	sys.exit(2)

PyLircFound = False
try:
	import pylirc
	PyLircFound = True
except ImportError, err:
	# Pylirc is optional, ignore the error, print a message later
	pass

#==============================================================================
class DisplayView:
	isVideoInitialized = False

	def __init__(self, evManager, Config):
		self.Config = Config

		self.evManager = evManager
		self.evManager.RegisterListener(self)

		ScreenSize = (self.Config.ScreenWidth, self.Config.ScreenHeight)

		pygame.display.init()
		pygame.font.init()


		#find the maximum supported window resolution
		try:
			modes = pygame.display.list_modes()
			self.isVideoInitialized = True
		except:
			self.isVideoInitialized = False

		if self.isVideoInitialized:
			MaxModeX = 0
			MaxModeY = 0
			for mode in modes:
				if mode[0] > MaxModeX:
					MaxModeX = mode[0]
					MaxModeY = mode[1]
				if mode[0] == MaxModeX:
					if mode[1] > MaxModeY:
						MaxModeY = mode[1]

			videoflags = 0
			if not self.Config.Fullscreen:
				videoflags = videoflags + pygame.RESIZABLE
			if self.Config.ScreenSizeAuto:
				self.window = pygame.display.set_mode((MaxModeX,MaxModeY), videoflags)
			else:
				self.window = pygame.display.set_mode(ScreenSize, videoflags)

			pygame.display.set_caption('MPD Client')
			if self.Config.Fullscreen:
				pygame.display.toggle_fullscreen()

			# Paint the Background
			background = pygame.Surface(self.window.get_size())
			background.fill(self.Config.Theme.ColorBackground)
			self.window.blit(background, (0,0))
			pygame.display.flip()

			self.Config.Sizes = Sizes(self.window.get_size())


	def CreateWidgets(self):
		self.display = Display(pygame.display, self.window, self.evManager, self.Config)


	def VideoInitialized(self):
		return self.isVideoInitialized

	def Notify(self, event):
		if self.isVideoInitialized:
			self.display.Notify(event)

#==============================================================================
class Display:
	WidgetInstanceList = []
	DEFAULTWIDGETS = [gui.MenuStartArea,gui.SongArea,gui.PlayControlArea]
	def __init__(self,display,window,evManager,Config):
		self.Config = Config
		self.evManager = evManager

		self.display = display
		self.window = window

		self.KeyboardToggle = None

		# start the default-widgets
		WIDGETS = self.DEFAULTWIDGETS[0:]
		WIDGETS.append(gui.InfoArea)
		for widget in WIDGETS:
			self.CreateWidgets(widget)

	def CreateWidgets(self, widget):
		Parent = "Screen"
		if widget == gui.SongArea:
			Size = self.Config.Sizes.MainAreaSize
			Position = self.Config.Sizes.MainAreaPosition
			mywidget = widget(Parent, Position, Size, self.Config, self.evManager)
			self.WidgetInstanceList.append(mywidget)
		elif widget == gui.InfoArea:
			Size = self.Config.Sizes.InfoAreaSize
			Position = self.Config.Sizes.InfoAreaPosition
			mywidget = widget(Parent, Position, Size, self.Config, self.evManager)
			self.WidgetInstanceList.append(mywidget)
		elif widget == gui.PlayControlArea:
			Size = self.Config.Sizes.ButtonAreaSize
			Position = self.Config.Sizes.ButtonAreaPosition
			mywidget = widget(Parent, Position, Size, self.Config, self.evManager)
			self.WidgetInstanceList.append(mywidget)
		elif widget == gui.MenuStartArea:
			Size = self.Config.Sizes.MenuStartButtonSize
			Position = self.Config.Sizes.MenuStartButtonPosition
			mywidget = widget(Parent, Position, Size, self.Config, self.evManager)
			self.WidgetInstanceList.append(mywidget)
		elif widget == gui.MenuDetailsArea:
			Size = self.Config.Sizes.MainAreaSize
			Position = self.Config.Sizes.MainAreaPosition
			mywidget = widget(Parent, Position, Size, self.Config, self.evManager)
			self.WidgetInstanceList.append(mywidget)
		else:
			print "Unknown Widget %s"%widget
			sys.exit(99)

	def Notify(self, event):
		MenuButtonSize = self.Config.Sizes.MenuButtonSize
		ScreenSize = self.Config.Sizes.ScreenSize

		if isinstance(event, events.DisplayUpdateEvent):
			self.Update()
		elif isinstance(event, events.MainAreaEvent):
			background = pygame.Surface(self.Config.Sizes.MainAreaSize)
			background.fill(self.Config.Theme.ColorBackground)
			self.window.blit(background, self.Config.Sizes.MainAreaPosition)
			self.display.flip()
			# find the mainareawidget and kill it
			RemoveList = []
			for WidgetInstance in self.WidgetInstanceList:
				if WidgetInstance.MainAreaWidget:
					# collect all widgets to kill in a separate list
					# killing right here would break the for-loop,
					# and only allow one widget to be killed
					RemoveList.append(WidgetInstance)
			for WidgetInstance in RemoveList:
				WidgetInstance.kill()
				self.WidgetInstanceList.remove(WidgetInstance)
				del(WidgetInstance)


			# do not show second info at the bottom if the mainareawidget already has the info
			ev = events.InfoareaEvent(event.widget != "Status")
			self.evManager.Notify(ev)

			# start the new widget
			mywidget = 0
			Size = self.Config.Sizes.MainAreaSize
			Position = self.Config.Sizes.MainAreaPosition
			Parent = "Screen"
			if event.widget != "Browse" and self.KeyboardToggle in self.WidgetInstanceList:
				# Keyboardtoggle is only used for Browse
				self.WidgetInstanceList.remove(self.KeyboardToggle)
				self.KeyboardToggle.kill()
				self.KeyboardToggle = None
			if event.widget == "Status":
				mywidget = gui.SongArea(Parent, Position, Size, self.Config, self.evManager)
			elif event.widget == "Search":
				mywidget = gui.SearchArea(Parent, Position, Size, self.Config, self.evManager, event.extended)
			elif event.widget == "SearchResult":
				mywidget = gui.SearchResultArea(Parent, Position, Size, self.Config, self.evManager)
			elif event.widget == "List":
				mywidget = gui.PlaylistArea(Parent, Position, Size, self.Config, self.evManager)
			elif event.widget == "AlarmClock":
				mywidget = gui.AlarmClockArea(Parent, Position, Size, self.Config, self.evManager)
			elif event.widget == "SleepClock":
				mywidget = gui.SleepClockArea(Parent, Position, Size, self.Config, self.evManager)
			elif event.widget == "Browse":
				mywidget = gui.BrowseArea(Parent, Position, Size, self.Config, self.evManager, event.extended)
				if self.Config.VirtualKeyboard and not (self.KeyboardToggle in self.WidgetInstanceList):
					# don't start new keyboardtoggle if there is one
					self.KeyboardToggle = gui.KeyboardToggleArea(Parent, self.Config.Sizes.KeyboardButtonPosition, self.Config.Sizes.KeyboardButtonSize, self.Config, self.evManager, event.extended)
					self.KeyboardToggle.set_Callback(mywidget.CallbackToggleKeyboard)
					self.WidgetInstanceList.append(self.KeyboardToggle)
			elif event.widget == "Menu":
				mywidget = gui.MenuDetailsArea(Parent, Position, Size, self.Config, self.evManager)
			elif event.widget == "SleepImage":
				mywidget = gui.SleepImageArea(Parent, Position, Size, self.Config, self.evManager)
			elif event.widget == "WakeupImage":
				mywidget = gui.WakeupImageArea(Parent, Position, Size, self.Config, self.evManager)
			if mywidget:
				self.WidgetInstanceList.append(mywidget)

			self.Update()
			if event.widget == "Browse":
				# populate browselist
				if event.extended != None:
					if isinstance(event.extended, dict):
						if event.extended.has_key("Path"):
							ev = events.BrowseEvent(event.extended["Path"])
						else:
							ev = events.BrowseEvent("")
					else:
						sys.exit(99)
						print "extended is expected to be a 3-dir"
				else:
					ev = events.BrowseEvent("")
				self.evManager.Notify(ev)
			elif event.widget == "List":
				ev = events.PlaylistEvent()
				self.evManager.Notify(ev)
			# cleanup now!
			gc.collect()
		elif isinstance(event, events.ScreensaverEvent):
			Parent = "Screen"

			# Cleanup
			background = pygame.Surface(self.Config.Sizes.ScreenSize)
			background.fill(self.Config.Theme.ColorBackground)
			self.window.blit(background, (0,0))
			self.display.flip()
			for WidgetInstance in self.WidgetInstanceList:
				WidgetInstance.kill()
				self.WidgetInstanceList.remove(WidgetInstance)
				del(WidgetInstance)
			if event.ScreensaverEnable:
				Size = self.Config.Sizes.ScreenSize
				Position = (0,0)
				mywidget = gui.ScreensaverImage(Parent, Position, Size, self.Config, self.evManager)
				self.WidgetInstanceList.append(mywidget)
			else:
				# start the default-widgets
				WIDGETS = self.DEFAULTWIDGETS[0:]
				WIDGETS.append(gui.InfoArea)
				for widget in WIDGETS:
					self.CreateWidgets(widget)

		elif isinstance(event, events.WindowResizeEvent):
			print "Got resized to %s,%s"%event.size #FIXME DEBUG
				
		elif not (isinstance(event, events.TickEvent) or isinstance(event, events.DisplayUpdateEvent) or isinstance(event, events.ServerUpdateEvent) ):
			for WidgetInstance in self.WidgetInstanceList:
				if isinstance(event, events.MouseClickEvent):
					WidgetInstance.Clicked(event.clickpos[0], event.clickpos[1])
				elif isinstance(event, events.InfraredEvent):
					WidgetInstance.HandleEvent(event)
				else:
					WidgetInstance.HandleEvent(event)

	def Update(self):
		for WidgetInstance in self.WidgetInstanceList:
			for S in WidgetInstance.Children():
				if isinstance(S,pygame.sprite.Sprite):
					S.update()
					self.window.blit(S.image, S.rect)
				else:
					print "* Not a sprite: %s"%S
		self.display.flip()

#==============================================================================
class TextLog:
	def __init__(self, evManager, Config):
		self.Config = Config
		self.evManager = evManager
		self.evManager.RegisterListener(self)

	def Notify(self, event):
		if self.Config.Debug:
			if not (isinstance(event, events.DisplayUpdateEvent) or isinstance(event, events.ServerUpdateEvent)):
				print "== Event:",event.name

#==============================================================================
class Connection(mpdclient3.mpd_connection):

	def __init__(self, host, port, password):
		mpdclient3.mpd_connection.__init__(self, host, port, password)
		mpdclient3.connect(host=host, port=port, password=password)
#==============================================================================
class ServerConnection(mpdclient3.mpd_connection):
	def __init__(self, evManager, Config):
		self.evManager = evManager
		self.evManager.RegisterListener(self)

		self.Config = Config

		self.Artist = ""
		self.Album = ""
		self.Title = ""

		self.connection = self.connect()

	def connect(self):
		try:
			print "Connecting to %s:%s"%(self.Config.ConnectHost,self.Config.ConnectPort)
			connection = Connection(self.Config.ConnectHost,self.Config.ConnectPort,self.Config.ConnectPassword)
			if connection:
				print "Connected Successfully"
				if self.Config.ConnectPassword:
					connection.do.password(self.Config.ConnectPassword)
			else:
				print "Connection Failed"
			return connection
		except (mpdclient3.socket.error, EOFError):
			return None

	def Notify(self, event):
		try:
			if not self.connection:
				self.connection = self.connect()
			if self.connection:
				if isinstance(event, events.DisplayUpdateEvent):
					status = self.connection.do.status()
					currentsong = self.connection.do.currentsong()
					event = events.PlayUpdateEvent(status,currentsong)
					self.evManager.Notify(event)

					if ((currentsong.has_key("artist")) and (currentsong.has_key("title")) and (currentsong.has_key("album"))):
						# normal file
						Artist = event.currentsong.artist.decode('utf-8')
						Album = event.currentsong.album.decode('utf-8')
						Title = event.currentsong.title.decode('utf-8')

						ChangedTitle = (self.Title != Title and self.Artist == Artist and self.Album == Album)
						ChangedAlbum = (self.Artist != Artist or self.Album != Album)
						event = events.CurrentSongInfoEvent(Title, Album, Artist, ChangedTitle, ChangedAlbum)
						self.evManager.Notify(event)
						self.Artist = Artist
						self.Album = Album
						self.Title = Title
					elif ((currentsong.has_key("file")) and (currentsong.has_key("title"))):
						# probably a stream
						Artist = ""
						Album = event.currentsong.file.decode('utf-8')
						Title = event.currentsong.title.decode('utf-8')
						ChangedTitle = (self.Title != Title and self.Artist == Artist and self.Album == Album)
						ChangedAlbum = (self.Artist != Artist or self.Album != Album)
						event = events.CurrentSongInfoEvent(Title, Album, Artist, ChangedTitle, ChangedAlbum)
						self.evManager.Notify(event)
						self.Artist = Artist
						self.Album = Album
						self.Title = Title
					else:
						self.Artist = ""
						self.Album = ""
						self.Title = ""
						event = events.CurrentSongInfoEvent("", "", "", True, True)
						self.evManager.Notify(event)
				elif isinstance(event, events.PreviousEvent):
					self.connection.do.previous()
				elif isinstance(event, events.StopEvent):
					self.connection.do.stop()
				elif isinstance(event, events.PlayEvent):
					self.connection.do.play()
				elif isinstance(event, events.PauseEvent):
					self.connection.do.pause(True)
				elif isinstance(event, events.NextEvent):
					self.connection.do.next()
				elif isinstance(event, events.VolumeQueryEvent):
					ev = events.VolumeStatusEvent(self.QueryVolume())
					self.evManager.Notify(ev)
				elif isinstance(event, events.VolumeSetEvent):
					self.SetVolume(event.volume,False)
				elif isinstance(event, events.VolumeDownEvent):
					self.SetVolume(-10)
				elif isinstance(event, events.MuteEvent):
					self.SetVolume(0,False)
				elif isinstance(event, events.VolumeUpEvent):
					self.SetVolume(10)
				elif isinstance(event, events.SearchEvent):
					searchresults = self.connection.do.search(event.searchtype,event.searchstring)
					ev = events.SearchResultEvent(event.searchtype,event.searchstring,searchresults)
					self.evManager.Notify(ev)
				elif isinstance(event, events.PlaylistEvent):
					playlist = self.connection.do.playlistinfo()
					ev = events.PlaylistResultEvent(playlist)
					self.evManager.Notify(ev)
				elif isinstance(event, events.BrowseEvent):
					browse = self.connection.do.lsinfo(event.path)
					ev = events.BrowseResultEvent(event.path,browse)
					self.evManager.Notify(ev)
				elif isinstance(event, events.PlaylistAddEvent):
					self.connection.do.add(event.path)
				elif isinstance(event, events.PlaylistClearEvent):
					self.connection.do.clear()
					playlist = self.connection.do.playlistinfo()
					ev = events.PlaylistResultEvent(playlist)
					self.evManager.Notify(ev)
				elif isinstance(event, events.PlaylistDelEvent):
					self.connection.do.deleteid(event.id)
					playlist = self.connection.do.playlistinfo()
					ev = events.PlaylistResultEvent(playlist)
					self.evManager.Notify(ev)
				elif isinstance(event, events.PlaylistMoveEvent):
					self.connection.do.moveid(event.moveid,event.insertbeforeid)
				elif isinstance(event, events.UpdateDatabaseEvent):
					self.connection.do.update("")
				elif isinstance(event, events.RandomEvent):
					self.connection.do.random(event.Random)
				elif isinstance(event, events.RepeatEvent):
					self.connection.do.repeat(event.Repeat)
		except (mpdclient3.socket.error, EOFError):
			self.connection = False
			print "Connection Lost"

	def SetVolume(self, VolumeChange, relative=True):
		Volume = int(self.connection.do.status().volume)
		if relative:
			Volume += VolumeChange
		else:
			Volume = VolumeChange
		if Volume < 0:
			Volume = 0
		if Volume > 100:
			Volume = 100
		self.connection.do.setvol(Volume)
	
	def QueryVolume(self):
		self.Volume = int(self.connection.do.status().volume)
		return self.Volume

#==============================================================================
class Input:
	def __init__(self, evManager, Config):
		self.evManager = evManager
		self.evManager.RegisterListener(self)

		self.Config = Config

	def Notify(self, event):
		if isinstance(event, events.TickEvent):
			#Handle Input Events
			for inputevent in pygame.event.get():
				if inputevent.type == pygame.QUIT:
					if self.Config.AllowQuit:
						event = events.QuitEvent()
						self.evManager.Notify(event)
				elif inputevent.type == pygame.KEYDOWN and inputevent.key == pygame.K_ESCAPE:
					if self.Config.AllowQuit:
						event = events.QuitEvent()
						self.evManager.Notify(event)
				elif inputevent.type == pygame.KEYUP:
					event = events.KeyboardEvent(inputevent.key,pygame.key.get_mods())
					self.evManager.Notify(event)
				elif inputevent.type == pygame.KEYDOWN:
					pass
				elif inputevent.type == pygame.ACTIVEEVENT:
					pass
				elif inputevent.type == pygame.MOUSEMOTION:
					pass
				elif inputevent.type == pygame.MOUSEBUTTONDOWN:
					pass
				elif inputevent.type == pygame.VIDEORESIZE:
					event = events.WindowResizeEvent(inputevent.size)
					self.evManager.Notify(event)
				elif inputevent.type == pygame.MOUSEBUTTONUP:
					event = events.MouseClickEvent(inputevent.button,inputevent.pos)
					self.evManager.Notify(event)
				else:
					print "Input: %s"%inputevent.type

#==============================================================================
class Infrared:
	def __init__(self, evManager, Config):
		self.evManager = evManager
		self.evManager.RegisterListener(self)

		self.Config = Config
		try:
			pylircinitresult = pylirc.init("mpdtouchgui", Config.LircrcPath, False)
			if not pylircinitresult:
				print "Could not initialize pylirc"
		except RuntimeError,err:
			if err == "Unable to initialize lirc!":
				print "Could not initialize pylirc"
		except IOError,err:
			if err == "Unable to read configuration!":
				print "could not read lircrc"
			


	def Notify(self, event):
		if isinstance(event, events.TickEvent):
			buttons = pylirc.nextcode(1)
			while buttons:
				for code in buttons:
					ev = events.InfraredEvent(code["config"],code["repeat"])
					self.evManager.Notify(ev)
				buttons = pylirc.nextcode(1)

	def kill(self):
		pylirc.exit()

#==============================================================================
class EventManager:
	def __init__(self):
		from weakref import WeakKeyDictionary
		self.listeners = WeakKeyDictionary()
		self.eventQueue = []

	def RegisterListener(self, listener):
		self.listeners[listener] = 1

	def UnregisterListener(self, listener):
		if listener in self.listeners.keys():
			del self.listeners[listener]

	def Notify(self, event):
		for listener in self.listeners.keys():
			if listener is None:
				del self.listeners[listener]
				continue
			listener.Notify(event)

#==============================================================================
class PowerManager:
	def __init__(self, evManager, Config):
		self.evManager = evManager
		self.evManager.RegisterListener(self)

		self.Config = Config
	
	def PowerOff(self):
		self.ExecuteCommand(self.Config.CommandSleep)

	def PowerOn(self):
		self.ExecuteCommand(self.Config.CommandWakeup)

	def Notify(self, event):
		if isinstance(event, events.PowerEvent):
			if event.PowerDown:
				self.PowerOff()
			else:
				self.PowerOn()

	def ExecuteCommand(self,command):
		if command != "":
			if os.path.isfile(command):
				exe = os.path.split(command)[1]
				result = os.spawnlp(os.P_NOWAIT, command, exe)

#==============================================================================
class ClockManager:
	def __init__(self, evManager, Config):
		self.evManager = evManager
		self.evManager.RegisterListener(self)

		self.Config = Config

		self.VolumeNormal = 0
		self.StepCount = 1
		self.StepsDone = 0
		self.VolumeStepSize = 0
		self.VolumeDuration = 1

		#Amplifier
		self.LastPlayTime = "00:000"
		self.LastPowerState = True # FIXME Find out Powerstate from hardware
		self.LastPlayingTime = datetime.datetime.now()

		#Screensaver
		self.LastInputTime = datetime.datetime.now()
		self.ScreensaverActive = False
		self.LastScreensaverImageChange = datetime.datetime.now()

		#Alarmclock
		self.Today = datetime.datetime.now().day
		self.waketimetoday = datetime.datetime.now()
		self.waketimetomorrow = datetime.datetime.now()
		self.AlarmRinging = False
		self.Sleeping = False
		self.AlarmTodayDone = True
		self.AlarmWaitingForPlay = True
		self.AlarmPlayStartTime = datetime.datetime.now()

		self.UpdateTimes(True)
		self.CheckIfAlarm(True)

	def Notify(self, event):
		if isinstance(event, events.PlayUpdateEvent):
			if self.AlarmWaitingForPlay:
				if event.status.has_key("state") and event.status.has_key("time"):
					# if status is playing, but time marker does not advance. File not loaded up to cachelimit yet?
					if event.status["state"] == "play" and event.status["time"] != self.LastPlayTime:
						self.AlarmWaitingForPlay = False
						self.AlarmPlayStartTime = datetime.datetime.now()
					self.LastPlayTime = event.status["time"]
			if self.Config.PowerOffTimeoutEnabled:
				if event.status.has_key("state"):
					if event.status["state"] == "play":
						self.LastPlayingTime = datetime.datetime.now()
						if not self.LastPowerState:
							self.LastPowerState = True
							ev = events.MainAreaEvent("Status")
							self.evManager.Notify(ev)
							ev = events.PowerEvent(False) # PowerOn
							self.evManager.Notify(ev)
					elif event.status["state"] == "stop":
						if self.LastPlayingTime + self.Config.PowerOffTimeout < datetime.datetime.now():
							if self.LastPowerState:
								self.LastPowerState = False
								ev = events.MainAreaEvent("SleepImage")
								self.evManager.Notify(ev)
								ev = events.PowerEvent(True) # PowerOff
								self.evManager.Notify(ev)
		elif (isinstance(event, events.MouseClickEvent) or isinstance(event, events.KeyboardEvent) or isinstance(event, events.InfraredEvent)):
		# FIXME Mousemoveevent
			if self.Config.ScreensaverMode != "none":
				self.LastInputTime = datetime.datetime.now()
			if self.ScreensaverActive:
				self.ScreensaverActive = False
				#FIXME jump to last active window
				self.LastScreensaverImageChange = datetime.datetime.now()
				ev = events.ScreensaverEvent(False)
				self.evManager.Notify(ev)
				
		elif isinstance(event, events.ServerUpdateEvent):
			self.UpdateTimes()
			self.CheckIfAlarm()
			self.CheckIfSleep()
			if self.AlarmRinging and self.Config.AlarmClock.ClockSwitchStyle != "hard":
				diff = datetime.datetime.now() - self.AlarmPlayStartTime
				StepsDone = int(diff.seconds/self.VolumeDuration)
				ev = events.VolumeSetEvent(int(StepsDone * self.VolumeStepSize))
				self.evManager.Notify(ev)
				if StepsDone >= self.StepCount:
					self.AlarmRinging = False
					ev = events.VolumeSetEvent(self.VolumeNormal)
					self.evManager.Notify(ev)
			if self.Sleeping and self.Config.AlarmClock.ClockSwitchStyle != "hard":
				diff = datetime.datetime.now() - self.Config.AlarmClock.SleepClockTime
				StepsDone = int(diff.seconds/self.VolumeDuration)
				ev = events.VolumeSetEvent(int((self.StepCount-StepsDone) * self.VolumeStepSize))
				self.evManager.Notify(ev)
				if StepsDone >= self.StepCount:
					self.Sleeping = False
					ev = events.StopEvent()
					self.evManager.Notify(ev)
					ev = events.PowerEvent()
					self.evManager.Notify(ev)
					ev = events.VolumeSetEvent(self.VolumeNormal)
					self.evManager.Notify(ev)
			if self.Config.ScreensaverMode != "none":
				if self.LastInputTime + self.Config.ScreensaverTimeout < datetime.datetime.now():
					if not self.ScreensaverActive:
						self.ScreensaverActive = True
						ev = events.ScreensaverEvent()
						self.evManager.Notify(ev)
			if self.LastScreensaverImageChange + self.Config.ScreensaverRefreshTimeout < datetime.datetime.now():
				ev = events.ScreensaverChangeEvent()
				self.evManager.Notify(ev)
				self.LastScreensaverImageChange = datetime.datetime.now()
		elif isinstance(event, events.VolumeStatusEvent):
			self.VolumeNormal = event.volume
		elif isinstance(event, events.ReloadConfigEvent):
			self.UpdateTimes(True)
			self.CheckIfAlarm(True)

	def GetNormalVolume(self):
		event = events.VolumeQueryEvent()
		self.evManager.Notify(event)

	def UpdateTimes(self, InitMode=False):
		# Load the AlarmClock Time for the Next day?
		if self.Today != datetime.datetime.now().day or InitMode:
			now = datetime.datetime.now()
			self.waketimetoday = datetime.datetime(now.year,now.month,now.day,self.Config.AlarmClock.AlarmClockTime[now.weekday()][0],self.Config.AlarmClock.AlarmClockTime[now.weekday()][1])

			# timedelta is (days, seconds, microseconds, milliseconds, minutes, hours, weeks)
			tomorrow = now + datetime.timedelta(1)
			self.waketimetomorrow = datetime.datetime(tomorrow.year,tomorrow.month,tomorrow.day,self.Config.AlarmClock.AlarmClockTime[tomorrow.weekday()][0],self.Config.AlarmClock.AlarmClockTime[tomorrow.weekday()][1])
			self.AlarmTodayDone = False

	def CheckIfAlarm(self, InitMode=False):
		difference = self.waketimetoday - datetime.datetime.now()
		if difference < datetime.timedelta(0,0,0):
			if not self.AlarmTodayDone:
				if not InitMode:
					if self.Config.AlarmClock.AlarmClockEnabled[datetime.datetime.now().weekday()]:
						self.GetNormalVolume()
						self.Alarm(self.VolumeNormal,self.Config.AlarmClock.ClockSwitchStyle, self.Config.AlarmClock.ClockSwitchDuration)
				self.AlarmTodayDone = True

	def CheckIfSleep(self):
		if self.Config.AlarmClock.SleepClockEnabled:
			difference = self.Config.AlarmClock.SleepClockTime - datetime.datetime.now()
			if difference < datetime.timedelta(0,0,0):
				self.Config.AlarmClock.SleepClockEnabled = False
				self.GetNormalVolume()
				self.Sleep(self.VolumeNormal,self.Config.AlarmClock.ClockSwitchStyle, self.Config.AlarmClock.ClockSwitchDuration)

	def Wakeup(self, Volume, SwitchStyle="hard", SwitchDuration=40):
		self.Alarm(self, Volume, SwitchStyle, SwitchDuration)

	def Alarm(self, Volume, SwitchStyle="hard", SwitchDuration=40):
		ev = events.MainAreaEvent("WakeupImage")
		self.evManager.Notify(ev)
		if SwitchStyle != "hard":
			self.StepCount = min(Volume,SwitchDuration)
			if self.StepCount == 0:
				self.StepCount = 1
			self.VolumeStepSize = Volume/float(self.StepCount)
			self.VolumeDuration = int(SwitchDuration/self.StepCount)

			self.AlarmRinging = True
			self.AlarmWaitingForPlay = True
			ev = events.VolumeSetEvent(0)
			self.evManager.Notify(ev)
		ev = events.PowerEvent(False) # PowerOn
		self.evManager.Notify(ev)
		ev = events.PlayEvent()
		self.evManager.Notify(ev)
		
	def Sleep(self, Volume, SwitchStyle="hard", SwitchDuration=40, Command=""):
		ev = events.MainAreaEvent("SleepImage")
		self.evManager.Notify(ev)
		if SwitchStyle != "hard":
			self.StepCount = min(Volume,SwitchDuration)
			if self.StepCount == 0:
				self.StepCount = 1
			self.VolumeStepSize = Volume/float(self.StepCount)
			self.VolumeDuration = int(SwitchDuration/self.StepCount)

			self.Sleeping = True
		else:
			ev = events.StopEvent()
			self.evManager.Notify(ev)
			ev = events.PowerEvent(True) # PowerOff
			self.evManager.Notify(ev)

				
#==============================================================================
class CPUSpinner:
	def __init__(self, evManager, Config):
		self.evManager = evManager
		self.evManager.RegisterListener(self)

		self.Config = Config

		self.CountForServerUpdate = 0
		self.CountForDisplayUpdate = 0
		self.CountForDisplayUpdateBlink = 0
		self.keepGoing = True

	def Run(self):
		try:
			while self.keepGoing:
				runtime = pygame.time.wait(self.Config.ClockFreq) # return cpu to scheduler
				self.CountForServerUpdate -= runtime
				self.CountForDisplayUpdate -= runtime
				self.CountForDisplayUpdateBlink -= runtime
				event = events.TickEvent()
				self.evManager.Notify(event)
				if self.CountForDisplayUpdate <= 0:
					event = events.DisplayUpdateEvent()
					self.evManager.Notify(event)
					self.CountForDisplayUpdate = self.Config.FreqDisplayUpdate
				if self.CountForDisplayUpdateBlink <= 0:
					event = events.DisplayUpdateBlinkEvent()
					self.evManager.Notify(event)
					self.CountForDisplayUpdateBlink = self.Config.FreqDisplayUpdateBlink
				if self.CountForServerUpdate <= 0:
					event = events.ServerUpdateEvent()
					self.evManager.Notify(event)
					self.CountForServerUpdate = self.Config.FreqServerUpdate
		except KeyboardInterrupt:
			self.keepGoing = False

	def Notify(self, event):
		if isinstance(event, events.QuitEvent):
			self.keepGoing = False

#==============================================================================
class Config:
	def __init__(self, ConfigFiles, argv):
		# Defaults for VideoOptions
		self.Fullscreen = False
		self.VirtualKeyboard = False
		self.ScreenSizeAuto = True
		self.ScreenWidth = 0
		self.ScreenHeight = 0

		# Subsections of Config
		self.Sizes = None
		self.Theme = None
		self.AlarmClock = None
		self.ClockStateFile = "/var/lib/pympdtouchgui/clock-state"

		# Defaults for ServerOptions
		self.ConnectHost = "127.0.0.1"
		self.ConnectPort = 6600
		self.ConnectPassword = ""

		# Defaults for AlbumartOptions
		self.Debug = False
		self.AlbumArtDir = ""
		self.AlbumArtFromAmazon = False
		self.AmazonID = "0MR5G85VBCCM2KS8RK82"

		# Defaults for MiscOptions
		self.ThemeDir = os.path.expanduser("/usr/share/pympdtouchgui/themes/default")
		self.CommandlineConfigFile = ""
		self.AllowQuit = True
		self.PowerOffTimeoutEnabled = False
		self.PowerOffTimeout = datetime.timedelta(0,1200) # 20 Minutes
		self.CommandWakeup = ""
		self.CommandSleep = ""

		self.ScreensaverTimeout = datetime.timedelta(0,600) # 10 Minutes
		self.ScreensaverRefreshTimeout = datetime.timedelta(0,60) # 1 Minute
		self.ScreensaverPath = os.path.expanduser("~/pictures")
		self.ScreensaverMode = "none"
		# timedelta is (days, seconds, microseconds, milliseconds, minutes, hours, weeks)

		self.FontName = None
		self.FontAntialias = True

		self.Lirc = False
		self.LircrcPath = os.path.expanduser("~/.lircrc")

		self.Browser = "firefox"

		# Frequencies in milliseconds
		self.ClockFreq = 400                # This is the main loop
		self.FreqServerUpdate = 800         # How often do we poll the mpd-server
		self.FreqDisplayUpdate = 400        # How often do we redraw the display
		self.FreqDisplayUpdateBlink = 400   # How fast does the prompt blink

		for ConfigFile in ConfigFiles:
			self.ConfigFileParse(ConfigFile)
		self.ConfigOptParse(argv)
		if self.CommandlineConfigFile:
			self.ConfigFileParse(self.CommandlineConfigFile)


	def ConfigFileParse(self,ConfigFile):
		conf = ConfigParser.ConfigParser()
		filename = os.path.realpath(os.path.expanduser(ConfigFile))
		isfile = os.path.isfile(filename)
		if isfile:
			print "Using Configuration from %s"%os.path.expanduser(ConfigFile)
			conf.read(filename)
			if conf.has_section("connection"):
				if conf.has_option("connection", "host"):
					self.ConnectHost = conf.get("connection", "host")
				if conf.has_option("connection", "port"):
					self.ConnectPort = conf.getint("connection", "port")
				if conf.has_option("connection", "password"):
					self.ConnectPassword = conf.get("connection", "password")

			if conf.has_section("display"):
				if conf.has_option("display", "fullscsreen"):
					self.Fullscreen = conf.getboolean("display", "fullscreen")
				if conf.has_option("display", "width"):
					self.ScreenWidth = conf.getint("display", "width")
				if conf.has_option("display", "height"):
					self.ScreenHeight = conf.getint("display", "height")

			if conf.has_section("timer"):
				if conf.has_option("timer", "clockfreq"):
					self.ClockFreq = conf.getint("timer", "clockfreq")
				if conf.has_option("timer", "freqserverpoll"):
					self.FreqServerUpdate = conf.getint("timer", "freqserverpoll")
				if conf.has_option("timer", "freqdisplayupdate"):
					self.FreqDisplayUpdate = conf.getint("timer", "freqdisplayupdate")
				if conf.has_option("timer", "freqdisplayupdateblink"):
					self.FreqDisplayUpdateBlink = conf.getint("timer", "freqdisplayupdateblink")

			if conf.has_section("albumart"):
				if conf.has_option("albumart", "dir"):
					self.AlbumArtDir = os.path.expanduser(conf.get("albumart", "dir"))
				if conf.has_option("albumart", "fetchfromamazon"):
					self.AlbumArtFromAmazon = conf.getboolean("albumart", "fetchfromamazon")
				if conf.has_option("albumart", "amazonid"):
					self.AmazonID = conf.get("albumart", "amazonid")

			if conf.has_section("alarmclock"):
				if conf.has_option("alarmclock", "statefile"):
					self.ClockStateFile = os.path.expanduser(conf.get("alarmclock", "statefile"))

			if conf.has_section("other"):
				if conf.has_option("other", "themedir"):
					self.ThemeDir = os.path.expanduser(conf.get("other", "themedir"))
				if conf.has_option("other", "onscreenkeyboard"):
					self.VirtualKeyboard = conf.getboolean("other", "onscreenkeyboard")
				if conf.has_option("other", "browser"):
					self.Browser = os.path.expanduser(conf.get("other", "browser"))
				if conf.has_option("other", "lirc"):
					self.Lirc = conf.getboolean("other", "lirc")
				if conf.has_option("other", "lircrc"):
					self.LircrcPath = os.path.expanduser(conf.get("other", "lircrc"))
				if conf.has_option("other", "allowquit"):
					self.AllowQuit = conf.getboolean("other", "allowquit")
				if conf.has_option("other", "powerofftimeoutenabled"):
					self.PowerOffTimeoutEnabled = conf.getboolean("other", "powerofftimeoutenabled")
				if conf.has_option("other", "powerofftimeout"):
					# timedelta is (days, seconds, microseconds, milliseconds, minutes, hours, weeks)
					self.PowerOffTimeout = datetime.timedelta(0,conf.getint("other", "powerofftimeout"))
				if conf.has_option("other", "commandwakeup"):
					self.CommandWakeup = os.path.expanduser(conf.get("other", "commandwakeup"))
				if conf.has_option("other", "commandsleep"):
					self.CommandSleep = os.path.expanduser(conf.get("other", "commandsleep"))

				if conf.has_option("other", "screensavertimeout"):
					# timedelta is (days, seconds, microseconds, milliseconds, minutes, hours, weeks)
					self.ScreensaverTimeout = datetime.timedelta(0,conf.getint("other", "screensavertimeout"))
				if conf.has_option("other", "screensaverrefresh"):
					# timedelta is (days, seconds, microseconds, milliseconds, minutes, hours, weeks)
					self.ScreensaverRefreshTimeout = datetime.timedelta(0,conf.getint("other", "screensaverrefresh"))
				if conf.has_option("other", "screensaverpath"):
					self.ScreensaverPath = os.path.expanduser(conf.get("other", "screensaverpath"))
				if conf.has_option("other", "screensavermode"):
					self.ScreensaverMode = conf.get("other", "screensavermode")
					if self.ScreensaverMode not in ["none", "linear", "random", "randombydir"]:
						print "Invalid ScreensaverMode in configfile"
						sys.exit(123)

			if self.ScreenWidth and self.ScreenHeight:
				self.ScreenSizeAuto = False
		return isfile

	def ConfigOptParse(self,argv):
		try:
			opts,args=getopt.getopt(argv, "i:p:P:kfs:c:a:AI:t:b:hlL:C:S:T:", ["help","fullscreen","keyboard","size=","password=","connect-ip=","connect-port=","album-art-dir=","themedir","configfile=","amazon-help","lirc","lircrc=","clockstatefile=","screensaverpath","screensavertimeout"])
		except getopt.GetoptError,message:
			self.opterr(message)

		for opt,arg in opts:
			if opt in ("-i","--connect-ip"):
				try:
					self.ConnectHost = arg
				except:
					opterr("invalid parameter for --connect-ip")
			if opt in ("-p","--connect-port"):
				try:
					self.ConnectPort = int(arg)
					assert self.ConnectPort >= 0 and self.ConnectPort <= 65535
				except:
					self.opterr("invalid parameter for --connect-port")
			if opt in ("-P","--password"):
				self.ConnectPassword = arg
			if opt in ("-k","--keyboard"):
				self.VirtualKeyboard = True
			if opt in ("-f","--fullscreen"):
				self.Fullscreen = True
			if opt in ("-s","--size"):
				try:
					self.ScreenWidth,self.ScreenHeight = map(int,arg.split("x"))
					assert self.ScreenWidth >= 320 and self.ScreenWidth < 4096
					assert self.ScreenHeight >= 200 and self.ScreenHeight < 4096
					self.ScreenSizeAuto = False
				except:
					opterr("invalid parameter for --size")
			if opt in ("-c","--configfile"):
				self.CommandlineConfigFile = arg
			if opt in ("-l","--lirc"):
				self.Lirc = True
			if opt in ("-L","--lircrc"):
				self.LircrcPath = arg
			if opt in ("-C","--clockstatefile"):
				self.ClockStateFile = arg
			if opt in ("-a","--album-art-dir"):
				#FIXME test if dir exists
				self.AlbumArtDir = arg
			if opt in ("-A","--album-art-from-amazon"):
				self.AlbumArtFromAmazon = True
			if opt in ("-I","--amazon-id"):
				self.AmazonID = arg
			if opt in ("-S","--screensaverpath"):
				#FIXME test if dir exists
				self.ScreensaverPath = arg
				if self.ScreensaverMode == "none":
					self.ScreensaverMode = "randombydir"
			if opt in ("-T","--screensavertimeout"):
				try:
					self.ScreensaverTimeout = int(arg)
					if self.ScreensaverMode == "none":
						self.ScreensaverMode = "randombydir"
					assert self.ScreensaverTimeout > 0 and self.ScreensaverTimeout <= 43200 # does it make sense to use a screensaver after more than 12 hours?
				except:
					opterr("invalid parameter for --screensavertimeout")
			if opt in ("-t","--theme-dir"):
				self.ThemeDir = arg
			if opt in ("-h","--help"):
				self.helpexit()
		if len(args) > 0:
			self.opterr("don't know what to do with additional arguments")

	def ChangeTheme(self, Theme):
		self.Theme = Theme

	def RecalculateSizes(self):
		self.Sizes.Positions["PlayControlButton"] = self.Theme.PositionPlayControlButton
		self.Sizes.Positions["InfoArea"] = self.Theme.PositionInfoArea
		self.Sizes.Positions["MenuButton"] = self.Theme.PositionMenuButton
		self.Sizes.Positions["VirtualKeyboardButton"] = self.Theme.PositionVirtualKeyboardButton
		self.Sizes.Resize()

	def opterr(self,msg):
		print "command line parse error:",msg
		print "use `%s -h' to get help"%sys.argv[0]
		sys.exit(1)

	def helpexit(self):
		print "Usage `%s [option]'"%sys.argv[0]
		print ""
		print "Valid Options are:"
		print "  -i, --connect-ip             ip/hostname to connect to"
		print "  -p, --connect-port           port to connect to"
		print "  -P, --password               password to authenticate with"
		print "  -k, --keyboard               enable onscreen-keyboard"
		print "  -f, --fullscreen             fullscreen"
		print "  -s, --size WIDTHxHEIGHT      viewable area"
		print "  -l, --lirc                   enable infrared"
		print "  -L, --lircrc                 path to lircrc"
		print "  -a, --album-art-dir          directory for Album-Art"
		print "  -A, --album-art-from-amazon  fetch Album-Art from Amazon"
		print "  -S, --screensaverpath        directory that contains images"
		print "                               to be used for screensaver"
		print "  -T  --screensavertimeout     timeout for screensaver"
		print "  -c, --configfile             configuration file"
		print "  -C, --clockstatefile         alarmclock configuration file"
		print "  -t, --themedir               theme directory "
		print "  -h, --help                   shows this help and exits"
		print ""
		print ""
		print "SDL honours the environment variable SDL_VIDEODRIVER "
		print "to select a Video Driver."
		print ""
		print "Possible Values for SDL_VIDEODRIVER on windows are"
		print "     windib, directx"
		print "Possible Values for SDL_VIDEODRIVER on Linux are"
		print "     x11, dga, fbcon, directfb, ggi, vgl, svgalib, aalib"
		sys.exit(0)

#==============================================================================
class AlarmClockConfig:
	def __init__(self,ConfigFile):
		# Defaults for AlarmClockOptions
		self.AlarmClockEnabled = {}
		self.AlarmClockTime    = {}
		for day in xrange(0,7):
			self.AlarmClockEnabled[day] = False
			self.AlarmClockTime[day]    = (7,01)

		self.ClockSwitchStyle = "hard"
		self.ClockSwitchDuration = 120

		self.SleepClockEnabled = False
		self.SleepClockTime    = datetime.datetime.now() + datetime.timedelta(0,0,0,0,30) # 30 Minutes
		# timedelta is (days, seconds, microseconds, milliseconds, minutes, hours, weeks)

		self.ConfigFile = ConfigFile

		self.ConfigFileParse()

	def ConfigFileParse(self):
		conf = ConfigParser.ConfigParser()
		filename = os.path.realpath(os.path.expanduser(self.ConfigFile))
		isfile = os.path.isfile(filename)
		if isfile:
			print "Using Configuration from %s"%filename
			conf.read(filename)
			if conf.has_section("alarmclock"):
				if conf.has_option("alarmclock", "enabled"):
					self.AlarmClockEnabled = self.AlarmclockParseEnabled(conf.get("alarmclock", "enabled"))
				if conf.has_option("alarmclock", "time"):
					self.AlarmClockTime = self.AlarmclockParseTime(conf.get("alarmclock", "time"))
				if conf.has_option("alarmclock", "switchstyle"):
					self.ClockSwitchStyle = self.AlarmclockParseSwitchStyle(conf.get("alarmclock", "switchstyle"))
				if conf.has_option("alarmclock", "switchduration"):
					self.ClockSwitchDuration = conf.getint("alarmclock", "switchduration")

	def ConfigFileWrite(self):
		if self.ConfigFile:
			filename = os.path.expanduser(self.ConfigFile)
			if os.path.isfile(filename):
				conf = ConfigParser.ConfigParser()
				print "Updating Configfile %s"%filename
				conf.read(filename)
				if not conf.has_section("alarmclock"):
					conf.add_section("alarmclock")

				AlarmClockEnabled = []
				AlarmClockTime = []
				for day in xrange(0,7):
					AlarmClockEnabled.append(str(self.AlarmClockEnabled[day]))
					AlarmClockTime.append("%02d:%02d"%self.AlarmClockTime[day])

				textenabled = ",".join(AlarmClockEnabled)
				conf.set("alarmclock","enabled",textenabled)

				texttime = ','.join(AlarmClockTime)
				conf.set("alarmclock","time",texttime)

				try:
					f = open(filename,"w")
					conf.write(f)
					f.close()
				except:
					print "Could not write clockstate %s"%filename

	def AlarmclockParseEnabled(self, string):
		parts = string.split(",")
		if not len(parts) == 7:
			print "Time not parseable (Week is expected to have 7 Days, but got only %s sets of Data)"%len(parts)
			sys.exit(99)
		else:
			newparts = {}
			for i in xrange(0,7):
				newparts[i] = (parts[i].lower() == "true")
			return newparts

	def AlarmclockParseTime(self, string):
		parts = string.split(",")
		if not len(parts) == 7:
			print "Time not parseable (Week is expected to have 7 Days, but got only %s sets of Data)"%len(parts)
			sys.exit(99)
		else:
			newparts = {}
			for i in xrange(0,7):
				parts2 = parts[i].split(":")
				if not len(parts2) == 2:
					print "Time not parseable (expecting a hour:minute pair, but got a %s-tuple)"%len(parts2)
					sys.exit(99)
				else:
					newparts[i] = (int(parts2[0]),int(parts2[1]))
			return newparts

	def AlarmclockParseSwitchStyle(self, string):
		ClockSwitchStyles = ["hard", "linear"]
		if string not in ClockSwitchStyles:
			print "Clockswitchstyle can be only 'hard' or 'linear', not '%s'."%string
			sys.exit(99)
		return string

#==============================================================================
class Sizes:
	def __init__(self, ScreenSize):
		self.MenuButtonSize = 0

		self.MainAreaSize = (0,0)
		self.MainAreaPosition = (0,0)
		self.FontSizeStatus = 0
		self.FontSizeBrowse = 0
		self.FontSizePlaylist = 0
		self.FontSizeSearch = 0
		self.FontSizeKeyboardSearch = 0
		self.FontSizeKeyboardBrowse = 0
		self.FontSizeSearchResult = 0
		self.FontSizeVirtualKeyboard = 0
		self.FontSizeInfoArea = 0
		self.FontSizeAlarmClock = 0
		self.FontSizeSleepClock = 0

		self.MenuStartButtonPosition = (0,0)
		self.MenuStartButtonSize = (0,0)

		self.InfoAreaSize = (0,0)
		self.InfoAreaPosition = (0,0)
		self.FontSizeInfoArea = 0

		self.ButtonAreaSize = (0,0)
		self.ButtonAreaPosition = (0,0)

		self.KeyboardButtonSize = (0,0)
		self.KeyboardButtonPosition = (0,0)

		self.Positions={}
		self.Positions["PlayControlButton"] = ("Edge",("Bottom","Center"))
		self.Positions["InfoArea"] = ("Edge",("Top","Center"))
		self.Positions["MenuButton"] = ("Corner",("Bottom","Left"))
		self.Positions["VirtualKeyboardButton"] = ("Corner",("Bottom","Right"))

		self.ScreenSize = ScreenSize
		self.Resize()

	def Resize(self):
		self.MenuButtonSize = int(min(self.ScreenSize[0]/10, self.ScreenSize[1]/8))

		self.FontSizeStatus = int(self.MenuButtonSize/4*3)
		self.FontSizeBrowse = int(self.FontSizeStatus /3*2)
		self.FontSizePlaylist = int(self.FontSizeStatus /3*2)
		self.FontSizeSearch = self.FontSizeStatus
		self.FontSizeKeyboardSearch = self.FontSizeSearch
		self.FontSizeKeyboardBrowse = int(self.FontSizeKeyboardSearch /3 *2)
		self.FontSizeSearchResult = int(self.FontSizeStatus/3*2)
		self.FontSizeVirtualKeyboard = self.FontSizeStatus
		self.FontSizeInfoArea = int(self.FontSizeStatus/4*3)
		self.FontSizeAlarmClock = self.FontSizeStatus
		self.FontSizeSleepClock = self.FontSizeStatus

		#FIXME
		if not self.Positions.has_key("PlayControlButton"):
			pass
		if not self.Positions.has_key("InfoArea"):
			pass
		if not self.Positions.has_key("MenuButton"):
			pass
		if not self.Positions.has_key("VirtualKeyboardButton"):
			pass



		# Check if no Position is occupied more than once
		PositionEdgeOccupied={}
		PositionEdgeOccupied["Bottom"] = False
		PositionEdgeOccupied["Left"] = False
		PositionEdgeOccupied["Right"] = False
		PositionEdgeOccupied["Top"] = False
		PositionCornerOccupied={}
		PositionCornerOccupied["BottomLeft"] = False
		PositionCornerOccupied["TopLeft"] = False
		PositionCornerOccupied["BottomRight"] = False
		PositionCornerOccupied["TopRight"] = False

		for PositionKey in self.Positions:
			PositionEntry = self.Positions[PositionKey]
			if PositionEntry[0] == "Edge":
				if PositionEntry[1][0] in PositionEdgeOccupied.keys():
					if PositionEdgeOccupied[PositionEntry[1][0]]:
						print "The %s Edge is used twice"%PositionEntry[1][0]
						sys.exit(99)
					else:
						PositionEdgeOccupied[PositionEntry[1][0]] = True
				else:
					print "Position %s not known "%PositionEntry[1][0]
					sys.exit(99)
			elif PositionEntry[0] == "Corner":
				if PositionEntry[1][0]+PositionEntry[1][1] in PositionCornerOccupied.keys():
					if PositionCornerOccupied[PositionEntry[1][0]+PositionEntry[1][1]]:
						print "The %s Corner is used twice"
						sys.exit(99)
					else:
						PositionCornerOccupied[PositionEntry[1][0]+PositionEntry[1][1]] = True
				elif PositionEntry[1][1]+PositionEntry[1][0] in PositionCornerOccupied.keys():
					if PositionCornerOccupied[PositionEntry[1][1]+PositionEntry[1][0]]:
						print "The %s Corner is used twice"
						sys.exit(99)
					else:
						PositionCornerOccupied[PositionEntry[1][1]+PositionEntry[1][0]] = True
				else:
					print "Position %s not known "%PositionEntry[1][0]
					sys.exit(99)
			else:
				print "PositionType %s not known"%PositionEntry[0]


		# Now calculate sizes
		if self.Positions["MenuButton"][0] == "Edge":
			print "Placing Buttons on a Edge is notsupported"
			sys.exit(99)
		elif self.Positions["MenuButton"][0] == "Corner":
			if self.Positions["MenuButton"][1][0] == "Left" and self.Positions["MenuButton"][1][1] == "Top"\
				or self.Positions["MenuButton"][1][1] == "Left" and self.Positions["MenuButton"][1][0] == "Top":
				self.MenuStartButtonPosition = (0, 0)
			elif self.Positions["MenuButton"][1][0] == "Right" and self.Positions["MenuButton"][1][1] == "Top"\
				or self.Positions["MenuButton"][1][1] == "Right" and self.Positions["MenuButton"][1][0] == "Top":
				self.MenuStartButtonPosition = (self.ScreenSize[0] - self.MenuButtonSize, 0)
			elif self.Positions["MenuButton"][1][0] == "Left" and self.Positions["MenuButton"][1][1] == "Bottom"\
				or self.Positions["MenuButton"][1][1] == "Left" and self.Positions["MenuButton"][1][0] == "Bottom":
				self.MenuStartButtonPosition = (0, self.ScreenSize[1] - self.MenuButtonSize)
			elif self.Positions["MenuButton"][1][0] == "Right" and self.Positions["MenuButton"][1][1] == "Bottom"\
				or self.Positions["MenuButton"][1][1] == "Right" and self.Positions["MenuButton"][1][0] == "Bottom":
				self.MenuStartButtonPosition = (self.ScreenSize[0] - self.MenuButtonSize, self.ScreenSize[1] - self.MenuButtonSize)
		self.MenuStartButtonSize = (self.MenuButtonSize,self.MenuButtonSize)

		if self.Positions["PlayControlButton"][0] == "Edge":
			if self.Positions["PlayControlButton"][1][0] == "Bottom":
				if PositionCornerOccupied["BottomLeft"] or PositionCornerOccupied["BottomRight"]:
					self.ButtonAreaSize = (self.ScreenSize[0] - self.MenuButtonSize * 2, self.MenuButtonSize)
					self.ButtonAreaPosition = (self.MenuButtonSize, self.ScreenSize[1]-self.MenuButtonSize)
				else:
					self.ButtonAreaSize = (self.ScreenSize[0], self.MenuButtonSize)
					self.ButtonAreaPosition = (0, self.ScreenSize[1]-self.MenuButtonSize)
			elif self.Positions["PlayControlButton"][1][0] == "Top":
				if PositionCornerOccupied["TopLeft"] or PositionCornerOccupied["TopRight"]:
					self.ButtonAreaSize = (self.ScreenSize[0] - self.MenuButtonSize * 2, self.MenuButtonSize)
					self.ButtonAreaPosition = (self.MenuButtonSize,0)
				else:
					self.ButtonAreaSize = (self.ScreenSize[0], self.MenuButtonSize)
					self.ButtonAreaPosition = (0,0)
			elif self.Positions["PlayControlButton"][1][0] == "Right":
				if PositionCornerOccupied["BottomRight"] or PositionCornerOccupied["TopRight"]:
					self.ButtonAreaSize = (self.MenuButtonSize, self.ScreenSize[1] - self.MenuButtonSize * 2)
					self.ButtonAreaPosition = (self.ScreenSize[0] - self.MenuButtonSize,self.MenuButtonSize)
				else:
					self.ButtonAreaSize = (self.MenuButtonSize, self.ScreenSize[1])
					self.ButtonAreaPosition = (self.ScreenSize[0] - self.MenuButtonSize,0)
			elif self.Positions["PlayControlButton"][1][0] == "Left":
				if PositionCornerOccupied["BottomLeft"] or PositionCornerOccupied["TopLeft"]:
					self.ButtonAreaSize = (self.MenuButtonSize, self.ScreenSize[1] - self.MenuButtonSize * 2)
					self.ButtonAreaPosition = (0,self.MenuButtonSize)
				else:
					self.ButtonAreaSize = (self.MenuButtonSize, self.ScreenSize[1])
					self.ButtonAreaPosition = (0,0)
			else:
				pass #ERROR!
		elif self.Positions["PlayControlButton"][0] == "Corner":
			print "The PlayControlbuttons are too many to be placed in a corner"
			sys.exit(99)

		if self.Positions["InfoArea"][0] == "Edge":
			if self.Positions["InfoArea"][1][0] == "Bottom":
				if PositionCornerOccupied["BottomLeft"] or PositionCornerOccupied["BottomRight"]:
					self.InfoAreaSize = (self.ScreenSize[0] - self.MenuButtonSize * 2, self.MenuButtonSize)
					self.InfoAreaPosition = (self.MenuButtonSize, self.ScreenSize[1])
				else:
					self.InfoAreaSize = (self.ScreenSize[0], self.MenuButtonSize)
					self.InfoAreaPosition = (0, self.ScreenSize[1])
			elif self.Positions["InfoArea"][1][0] == "Top":
				if PositionCornerOccupied["TopLeft"] or PositionCornerOccupied["TopRight"]:
					self.InfoAreaSize = (self.ScreenSize[0] - self.MenuButtonSize * 2, self.MenuButtonSize)
					self.InfoAreaPosition = (self.MenuButtonSize,0)
				else:
					self.InfoAreaSize = (self.ScreenSize[0], self.MenuButtonSize)
					self.InfoAreaPosition = (0,0)
			elif self.Positions["InfoArea"][1][0] == "Right":
				if PositionCornerOccupied["BottomRight"] or PositionCornerOccupied["TopRight"]:
					self.InfoAreaSize = (self.MenuButtonSize, self.ScreenSize[1] - self.MenuButtonSize * 2)
					self.InfoAreaPosition = (self.ScreenSize[0] - self.MenuButtonSize,self.MenuButtonSize)
				else:
					self.InfoAreaSize = (self.MenuButtonSize, self.ScreenSize[1])
					self.InfoAreaPosition = (self.ScreenSize[0] - self.MenuButtonSize,0)
			elif self.Positions["InfoArea"][1][0] == "Left":
				if PositionCornerOccupied["BottomLeft"] or PositionCornerOccupied["TopLeft"]:
					self.InfoAreaSize = (self.MenuButtonSize, self.ScreenSize[1] - self.MenuButtonSize * 2)
					self.InfoAreaPosition = (0,self.MenuButtonSize)
				else:
					self.InfoAreaSize = (self.MenuButtonSize, self.ScreenSize[1])
					self.InfoAreaPosition = (0,0)
			else:
				pass #ERROR!
		elif self.Positions["InfoArea"][0] == "Corner":
			print "The InfoArea is too large to be placed in a corner"
			sys.exit(99)

		if self.Positions["VirtualKeyboardButton"][0] == "Edge":
			print "Placing Buttons on a Edge is notsupported"
			sys.exit(99)
		elif self.Positions["VirtualKeyboardButton"][0] == "Corner":
			if self.Positions["VirtualKeyboardButton"][1][0] == "Left" and self.Positions["VirtualKeyboardButton"][1][1] == "Top"\
				or self.Positions["VirtualKeyboardButton"][1][1] == "Left" and self.Positions["VirtualKeyboardButton"][1][0] == "Top":
				self.KeyboardButtonPosition = (0, 0)
			elif self.Positions["VirtualKeyboardButton"][1][0] == "Right" and self.Positions["VirtualKeyboardButton"][1][1] == "Top"\
				or self.Positions["VirtualKeyboardButton"][1][1] == "Right" and self.Positions["VirtualKeyboardButton"][1][0] == "Top":
				self.KeyboardButtonPosition = (self.ScreenSize[0] - self.MenuButtonSize, 0)
			elif self.Positions["VirtualKeyboardButton"][1][0] == "Left" and self.Positions["VirtualKeyboardButton"][1][1] == "Bottom"\
				or self.Positions["VirtualKeyboardButton"][1][1] == "Left" and self.Positions["VirtualKeyboardButton"][1][0] == "Bottom":
				self.KeyboardButtonPosition = (0, self.ScreenSize[1] - self.MenuButtonSize)
			elif self.Positions["VirtualKeyboardButton"][1][0] == "Right" and self.Positions["VirtualKeyboardButton"][1][1] == "Bottom"\
				or self.Positions["VirtualKeyboardButton"][1][1] == "Right" and self.Positions["VirtualKeyboardButton"][1][0] == "Bottom":
				self.KeyboardButtonPosition = (self.ScreenSize[0] - self.MenuButtonSize, self.ScreenSize[1] - self.MenuButtonSize)
			self.KeyboardButtonSize = (self.MenuButtonSize,self.MenuButtonSize)

		# Heuristics for single Buttons in Corners
		if PositionCornerOccupied["TopRight"] and ((not PositionEdgeOccupied["Top"]) and (not PositionEdgeOccupied["Right"])):
			if PositionEdgeOccupied["Bottom"]:
				PositionEdgeOccupied["Top"] = True
			else:
				PositionEdgeOccupied["Right"] = True
		if PositionCornerOccupied["TopLeft"] and ((not PositionEdgeOccupied["Top"]) and (not PositionEdgeOccupied["Left"])):
			if PositionEdgeOccupied["Bottom"]:
				PositionEdgeOccupied["Top"] = True
			else:
				PositionEdgeOccupied["Left"] = True
		if PositionCornerOccupied["BottomRight"] and ((not PositionEdgeOccupied["Bottom"]) and (not PositionEdgeOccupied["Right"])):
			if PositionEdgeOccupied["Top"]:
				PositionEdgeOccupied["Bottom"] = True
			else:
				PositionEdgeOccupied["Right"] = True
		if PositionCornerOccupied["BottomLeft"] and ((not PositionEdgeOccupied["Bottom"]) and (not PositionEdgeOccupied["Left"])):
			if PositionEdgeOccupied["Top"]:
				PositionEdgeOccupied["Bottom"] = True
			else:
				PositionEdgeOccupied["Left"] = True

		self.MainAreaSize = (self.ScreenSize[0], self.ScreenSize[1])
		self.MainAreaPosition = (0,0)
		if PositionEdgeOccupied["Left"]:
			self.MainAreaSize = (self.MainAreaSize[0] - self.MenuButtonSize,self.MainAreaSize[1])
			self.MainAreaPosition = (self.MainAreaPosition[0] + self.MenuButtonSize,self.MainAreaPosition[1])
		if PositionEdgeOccupied["Right"]:
			self.MainAreaSize = (self.MainAreaSize[0] - self.MenuButtonSize,self.MainAreaSize[1])
		if PositionEdgeOccupied["Top"]:
			self.MainAreaSize = (self.MainAreaSize[0],self.MainAreaSize[1] - self.MenuButtonSize)
			self.MainAreaPosition = (self.MainAreaPosition[0],self.MainAreaPosition[1] + self.MenuButtonSize)
		if PositionEdgeOccupied["Bottom"]:
			self.MainAreaSize = (self.MainAreaSize[0],self.MainAreaSize[1] - self.MenuButtonSize)

#==============================================================================
class Theme:
	def __init__(self):
		self.ColorBackground = (0,0,0)
		# Status
		self.ColorForegroundStatus = (255,255,255)
		# Info
		self.ColorForegroundInfo = (255,255,255)
		# Menu
		self.ColorForegroundMenu = (255,255,255)
		self.ColorForegroundButtons = (255,255,255)
		# Browse
		self.ColorForegroundBrowseText = (255,255,255)
		self.ColorBackgroundBrowseCursorLine = (255,0,0)
		self.ColorForegroundBrowseCursorLine = (255,255,255)
		self.ColorBackgroundBrowseSelectLine = (255,0,0)
		self.ColorForegroundBrowseSelectLine = (255,255,255)
		# Search
		self.ColorForegroundSearchText = (255,255,255)
		# Playlist
		self.ColorBackgroundPlaylistHighlightLine = (255,0,0)
		self.ColorForegroundPlaylistHighlightLine = (255,255,255)
		self.ColorBackgroundPlaylistCursorLine = (255,0,0)
		self.ColorForegroundPlaylistCursorLine = (255,255,255)
		self.ColorForegroundPlaylistText = (255,255,255)
		# Scroll
		self.ColorForegroundScrollLines = (255,255,255)
		self.ColorForegroundScrollMiddleSlider = (255,255,255)
		self.ColorForegroundScrollFirstLastSlider = (0,0,0)
		# VirtualKeyboard
		self.ColorBackgroundVirtualKeyboardSelect = (255,0,0)
		self.ColorForegroundVirtualKeyboardSelect = (255,255,255)
		self.ColorForegroundVirtualKeyboardText = (255,255,255)

		# Positions
		self.PositionPlayControlButton = ("Edge",("Bottom","Center"))
		self.PositionInfoArea = ("Edge",("Top","Center"))
		self.PositionMenuButton = ("Corner",("Bottom","Left"))
		self.PositionVirtualKeyboardButton = ("Corner",("Bottom","Right"))

	def LoadTheme(self, ThemeDir):
		ColorSectionName="Colors"
		PositionSectionName="Position"
		conf = ConfigParser.ConfigParser()
		ThemeConf = os.path.join(ThemeDir,"themeconfig")
		if os.path.isfile(ThemeConf):
			print "Using Theme from %s"%ThemeConf
			conf.read(ThemeConf)
			if conf.has_option(ColorSectionName, "Background"):
				self.ColorBackground = self.ParseColor(conf.get(ColorSectionName, "Background"))
			# Status
			if conf.has_option(ColorSectionName, "ForegroundStatus"):
				self.ColorForegroundStatus = self.ParseColor(conf.get(ColorSectionName, "ForegroundStatus"))
			# Info
			if conf.has_option(ColorSectionName, "ForegroundInfo"):
				self.ColorForegroundInfo = self.ParseColor(conf.get(ColorSectionName, "ForegroundInfo"))
			# Menu
			if conf.has_option(ColorSectionName, "ForegroundMenu"):
				self.ColorForegroundMenu = self.ParseColor(conf.get(ColorSectionName, "ForegroundMenu"))
			if conf.has_option(ColorSectionName, "ForegroundButtons"):
				self.ColorForegroundButtons = self.ParseColor(conf.get(ColorSectionName, "ForegroundButtons"))
			# Browse
			if conf.has_option(ColorSectionName, "ForegroundBrowseText"):
				self.ColorForegroundBrowseText = self.ParseColor(conf.get(ColorSectionName, "ForegroundBrowseText"))
			if conf.has_option(ColorSectionName, "BackgroundBrowseCursorLine"):
				self.ColorBackgroundBrowseCursorLine = self.ParseColor(conf.get(ColorSectionName, "BackgroundBrowseCursorLine"))
			if conf.has_option(ColorSectionName, "ForegroundBrowseCursorLine"):
				self.ColorForegroundBrowseCursorLine = self.ParseColor(conf.get(ColorSectionName, "ForegroundBrowseCursorLine"))
			# Search
			if conf.has_option(ColorSectionName, "ForegroundSearchText"):
				self.ColorForegroundSearchText = self.ParseColor(conf.get(ColorSectionName, "ForegroundSearchText"))
			# Playlist
			if conf.has_option(ColorSectionName, "BackgroundPlaylistHighlightLine"):
				self.ColorBackgroundPlaylistHighlightLine = self.ParseColor(conf.get(ColorSectionName, "BackgroundPlaylistHighlightLine"))
			if conf.has_option(ColorSectionName, "ForegroundPlaylistHighlightLine"):
				self.ColorForegroundPlaylistHighlightLine = self.ParseColor(conf.get(ColorSectionName, "ForegroundPlaylistHighlightLine"))
			if conf.has_option(ColorSectionName, "BackgroundPlaylistCursorLine"):
				self.ColorBackgroundPlaylistCursorLine = self.ParseColor(conf.get(ColorSectionName, "BackgroundPlaylistCursorLine"))
			if conf.has_option(ColorSectionName, "ForegroundPlaylistCursorLine"):
				self.ColorForegroundPlaylistCursorLine = self.ParseColor(conf.get(ColorSectionName, "ForegroundPlaylistCursorLine"))
			if conf.has_option(ColorSectionName, "ForegroundPlaylistText"):
				self.ColorForegroundPlaylistText = self.ParseColor(conf.get(ColorSectionName, "ForegroundPlaylistText"))
			# Scroll
			if conf.has_option(ColorSectionName, "ForegroundScrollLines"):
				self.ColorForegroundScrollLines = self.ParseColor(conf.get(ColorSectionName, "ForegroundScrollLines"))
			if conf.has_option(ColorSectionName, "ForegroundScrollMiddleSlider"):
				self.ColorForegroundScrollMiddleSlider = self.ParseColor(conf.get(ColorSectionName, "ForegroundScrollMiddleSlider"))
			if conf.has_option(ColorSectionName, "ForegroundScrollFirstLastSlider"):
				self.ColorForegroundScrollFirstLastSlider = self.ParseColor(conf.get(ColorSectionName, "ForegroundScrollFirstLastSlider"))
			# VirtualKeyboard
			if conf.has_option(ColorSectionName, "BackgroundVirtualKeyboardSelect"):
				self.ColorBackgroundVirtualKeyboardSelect = self.ParseColor(conf.get(ColorSectionName, "BackgroundVirtualKeyboardSelect"))
			if conf.has_option(ColorSectionName, "ForegroundVirtualKeyboardSelect"):
				self.ColorForegroundVirtualKeyboardSelect = self.ParseColor(conf.get(ColorSectionName, "ForegroundVirtualKeyboardSelect"))
			if conf.has_option(ColorSectionName, "ForegroundVirtualKeyboardText"):
				self.ColorForegroundVirtualKeyboardText = self.ParseColor(conf.get(ColorSectionName, "ForegroundVirtualKeyboardText"))

			# Positions
			if conf.has_option(PositionSectionName, "PlayControlButtons"):
				self.PositionPlayControlButton = self.ParsePosition(conf.get(PositionSectionName, "PlayControlButtons"))
			if conf.has_option(PositionSectionName, "InfoArea"):
				self.PositionInfoArea = self.ParsePosition(conf.get(PositionSectionName, "InfoArea"))
			if conf.has_option(PositionSectionName, "MenuButton"):
				self.PositionMenuButton = self.ParsePosition(conf.get(PositionSectionName, "MenuButton"))
			if conf.has_option(PositionSectionName, "VirtualKeyboardButton"):
				self.PositionVirtualKeyboardButton = self.ParsePosition(conf.get(PositionSectionName, "VirtualKeyboardButton"))

	def ParseColor(self, ColorString):
		# expecting a colortriple like "(123,123,123)"
		if ColorString[0]=="(" and ColorString[-1]==")":
			rgb = ColorString[1:-1].split(",")
			if len(rgb) == 3:
				return (int(rgb[0]),int(rgb[1]),int(rgb[2]))
			else:
				print "In ThemeConfigfile: Colorvalue is supposed to be a comma separated RGB Triple like `(123,123,123)' but was a %s-Tuple `%s'"%(len(rgb),ColorString)
				sys.exit(123)
		else:
			print "In ThemeConfigfile: Colorvalue is supposed to be a RGB Triple in round brackets, but at least one bracket is missing in `%s'"%ColorString
			sys.exit(123)

	def ParsePosition(self, PostionString):
		# expecting something like "Edge,Bottom,Center"
		PositionArray = PostionString.split(",")
		if len(PositionArray) == 3:
			if PositionArray[0] in ["Edge","Corner"]:
				PositionType = PositionArray[0]
				if PositionArray[1] in ["Top","Bottom", "Left","Right"]:
					PositionPrimary = PositionArray[1]
					if PositionArray[0] == "Corner":
						if PositionArray[2] in ["Top","Bottom", "Left","Right"]:
							PositionSecondary = PositionArray[2]
							return (PositionType,(PositionPrimary,PositionSecondary))
						else:
							print "Position in ThemeConfigfile is supposed to be a comma separated triple with a Position (Top, Bottom, Left or Right) at the third place. Found `%s'"%PositionArray[2]
							sys.exit(123)
					elif PositionArray[0] == "Edge":
						if PositionArray[2] in ["Top","Bottom", "Left","Right","Center","Middle"]:
							PositionSecondary = PositionArray[2]
							return (PositionType,(PositionPrimary,PositionSecondary))
						else:
							print "Position in ThemeConfigfile is supposed to be a comma separated triple with a Position (Top, Bottom, Left, Right, Center or Middle) at the third place. Found `%s'"%PositionArray[2]
							sys.exit(123)
					else:
						# Not possible due to earlier checks, error anyway
						print "This Error should have been caught earlier."
						sys.exit(123)
				else:
					print "Position in ThemeConfigfile is supposed to be a comma separated triple with a Position (Top, Bottom, Left or Right) at the second place. Found `%s'"%PositionArray[1]
					sys.exit(123)
			else:
				print "Position in ThemeConfigfile is supposed to be a comma separated triple with a Position Type (Edge or Corner) at the first place. Found `%s'"%PositionArray[0]
				sys.exit(123)
		else:
			print "Position in ThemeConfigfile is supposed to be a comma separated triple. Found `%s'"%PostionString
			sys.exit(123)

#==============================================================================
def videoerror():
	print "Couldn't initialize Video"
	print "Either you specified a wrong SDL_VIDEODRIVER in your environment,"
	print "or SDL doesn't support the specified SDL_VIDEODRIVER"
	print "Possible Values for SDL_VIDEODRIVER on windows are"
	print "     windib, directx"
	print "Possible Values for SDL_VIDEODRIVER on Linux are"
	print "     x11, dga, fbcon, directfb, ggi, vgl, svgalib, aalib"
	sys.exit(1)

def main(argv):
	version='0.309' #This is automatically replaced by maintainer-scripts
	print "PyMPDTouchGUI %s, Copyright (C) 2007,2008 Timo Boettcher"%version
	print "PyMPDTouchGUI comes with ABSOLUTELY NO WARRANTY."
	print "This is free software, and you are welcome to redistribute it"
	print "under certain conditions; see shipped license (GPL2) for details."
	print ""

	# Read Config and Theme
	MyConfig = Config(["/etc/mpdtouchguirc","~/.mpdtouchgui/config"],argv)
	MyConfig.PyLircFound = PyLircFound
	MyAlarmClockConfig = AlarmClockConfig(MyConfig.ClockStateFile)
	MyConfig.AlarmClock = MyAlarmClockConfig
	MyTheme = Theme()
	MyTheme.LoadTheme(MyConfig.ThemeDir)
	MyConfig.ChangeTheme(MyTheme)

	evManager = EventManager()

	# Find a working Screenresolution and activate it
	MyDisplay = DisplayView(evManager, MyConfig)
	if not MyDisplay.VideoInitialized():
		videoerror()
	# Calculate sizes for Widgets in current Screenresolution
	MyConfig.RecalculateSizes()
	# Create Widgets
	MyDisplay.CreateWidgets()

	input = Input(evManager, MyConfig)
	if MyConfig.Lirc:
		if MyConfig.PyLircFound:
			print "Infrared support enabled"
			infrared = Infrared(evManager, MyConfig)
		else:
			print "Infrared support disabled, pylirc not found"
	spinner = CPUSpinner(evManager,MyConfig)

	serverConnection = ServerConnection(evManager, MyConfig)
	textLog = TextLog(evManager, MyConfig)

	myClockmananger = ClockManager(evManager, MyConfig)
	Powermananger = PowerManager(evManager, MyConfig)

	spinner.Run()
	sys.exit(0)


if __name__=="__main__":
	main(sys.argv[1:])

