#!/usr/bin/env python2.5

#
# Copyright 2009 Pete Foster (xMob)
#
# This file is part of mSideShow.
#
# mSideSHow is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# mSideShow is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with mSideShow.  If not, see <http://www.gnu.org/licenses/>.
#
# Contributors
# David Clark - Multiline text rendering (http://www.pygame.org/pcr/text_rect/index.php)
#
# Expect:
# Bugs
# Crashes
# Lockups
# Typos
# Bad weather

import time
import pygame
import bluetooth
import dbus
import logging
import uuid
import platform
import ConfigParser
import struct
import xml.dom.minidom
import threading

#import traceback

from cStringIO import StringIO

import ss_multiline as multiline

VERSION = "0.0.6"

SETUSERSTATE = 0x50
SETCURRENTUSER = 0x100
GETCURRENTUSER = 0x101
GETCAPABILITIES = 0x103
GETAPPLICATIONORDER = 0x104
SETAPPLICATIONORDER = 0x105
SETTIME = 0x108
SETSHORTDATEFORMAT = 0x109
SETLONGDATEFORMAT = 0x10a
SETSHORTTIMEFORMAT = 0x10b
ADDAPPLICATION = 0x10d
DELETEAPPLICATION = 0x10e
ADDCONTENTITEM = 0x114
DELETECONTENTITEM = 0x115
DELETEALLCONTENTITEMS = 0x116
GETSUPPORTEDENDPOINTS = 0x117
SETTIMEZONE = 0x118
SYNC = 0x502

SCF_EVENT_NAVIGATION = 1
SCF_EVENT_MENUACTION = 2
SCF_EVENT_CONTEXTMENU = 3

SCF_BUTTON_MENU = 1
SCF_BUTTON_SELECT = 2
SCF_BUTTON_UP = 3
SCF_BUTTON_DOWN = 4
SCF_BUTTON_LEFT = 5
SCF_BUTTON_RIGHT = 6
SCF_BUTTON_PLAY = 7
SCF_BUTTON_PAUSE = 8
SCF_BUTTON_FASTFORWARD = 9
SCF_BUTTON_REWIND = 10
SCF_BUTTON_STOP = 11
SCF_BUTTON_BACK = 65280

PROPERTYKEY = uuid.UUID('{8ABC88A8-857B-4ad7-A35A-B5942F492B99}')
SIDESHOW_CAPABILITY_DEVICE_ID = 1
SIDESHOW_CAPABILITY_SCREEN_TYPE = 2
SIDESHOW_CAPABILITY_SCREEN_WIDTH = 3
SIDESHOW_CAPABILITY_SCREEN_HEIGHT = 4
SIDESHOW_CAPABILITY_COLOR_DEPTH = 5
SIDESHOW_CAPABILITY_COLOR_TYPE = 6
SIDESHOW_CAPABILITY_DATA_CACHE = 7
SIDESHOW_CAPABILITY_SUPPORTED_LANGUAGES = 8
SIDESHOW_CAPABILITY_CURRENT_LANGUAGE = 9
SIDESHOW_CAPABILITY_SUPPORTED_THEMES = 10
SIDESHOW_CAPABILITY_SUPPORTED_IMAGE_FORMATS = 14
SIDESHOW_CAPABILITY_CLIENT_AREA_WIDTH = 15
SIDESHOW_CAPABILITY_CLIENT_AREA_HEIGHT =16

#if platform.machine() == "armv6l":
#	PLATFORM = "n800"
#else:
#	PLATFORM = "other"
# Hard coding this while beta testing is taking place.
PLATFORM = "n800"

if PLATFORM == "n800":
	import osso
	osso_c = osso.Context("osso_test_device_on", "0.0.1", False)
	device = osso.DeviceState(osso_c)

logging.basicConfig(level=logging.DEBUG,)
log = logging.getLogger("mSideShow")

class SideShowApp():
	def __init__(self):
		log.debug("Starting up")
		log.debug(platform.machine())
		
		log.debug("Reading config file")
		self.readConfig();
		
		self.CONNECTED = False
		self.packet_count = 0
		self.data = ""

		self.sid = "S-1-5-4"
		self.user = ""
		
		self.on_ac = False
		self.bat_level = 0
		
		self.apps_guid = []
		self.apps_name = []
		self.apps_icon = []
		self.apps_glance = []
		self.apps_content = []
		self.apps_rect = []

		self.buttons_keys = []
		self.buttons_ids = []
		self.buttons_text = []

		self.time_dif = 0
		self.time_bias = 0

		self.msg = ""
		self.msg_time = time.time()

		self.num_pages = 0
		self.page_num = 0
		self.page_time = time.time()

		self.gadget_selected = 0

		self.breadcrumb = []

		self.current_menu = []
		self.menu_s = None
		self.content_s = None
		self.selected_menu = None
		self.current_guid = None
		self.current_cid = None

		self.REDRAW = True
		self.upd_GUID = None
		self.upd_CID = None

		pygame.init()
	
		if PLATFORM == "n800":
			device.display_state_on()
			device.display_blanking_pause()
			self.screen = pygame.display.set_mode((800, 480), pygame.FULLSCREEN)
			pygame.mouse.set_visible(False)
		else:
			self.screen = pygame.display.set_mode((800, 480))
			
		self.bg = pygame.image.load("/usr/share/pixmaps/ss_bg.png")
		self.splash = pygame.image.load("/usr/share/pixmaps/ss_splash.png")
		self.bar_bg = pygame.image.load("/usr/share/pixmaps/ss_bar.png")
		self.box_bg = pygame.image.load("/usr/share/pixmaps/ss_front_box.png")
		self.box_bg_sel = pygame.image.load("/usr/share/pixmaps/ss_front_box_sel.png")
		self.msg_box_bg = pygame.image.load("/usr/share/pixmaps/ss_msg_box.png")
		self.icon_exit = pygame.image.load("/usr/share/pixmaps/ss_icon_exit.png")
		self.icon_bt = pygame.image.load("/usr/share/pixmaps/ss_icon_bt.png")
		self.icon_bat_charging = pygame.image.load("/usr/share/pixmaps/ss_icon_bat_charging.png")
		self.icon_bat_0 = pygame.image.load("/usr/share/pixmaps/ss_icon_bat_0.png")
		self.icon_bat_25 = pygame.image.load("/usr/share/pixmaps/ss_icon_bat_25.png")
		self.icon_bat_50 = pygame.image.load("/usr/share/pixmaps/ss_icon_bat_50.png")
		self.icon_bat_75 = pygame.image.load("/usr/share/pixmaps/ss_icon_bat_75.png")
		self.icon_bat_100 = pygame.image.load("/usr/share/pixmaps/ss_icon_bat_100.png")
		self.no_bt = pygame.image.load("/usr/share/pixmaps/ss_bt_service.png")
		self.dpad = pygame.image.load("/usr/share/pixmaps/ss_dpad.png")
		
		self.start_time = time.time()

		self.show_no_bt = False

		self.version_f = pygame.font.SysFont(None, 12, bold = False)
		self.small_f = pygame.font.SysFont(None, 14, bold = False)
		self.def_f = pygame.font.SysFont(None, 18, bold = False)
		self.defbold_f = pygame.font.SysFont(None, 18, bold = True)
		self.user_f = pygame.font.SysFont(None, 24, bold = True)
		self.menu_f = pygame.font.SysFont(None, 18, bold = False)
		self.clock_f = pygame.font.Font("/usr/share/fonts/DigitalDream.ttf", 24)

		self.RUNNING = True
		
		self.drawFront()
		
		self.newMsg("Starting Bluetooth services", time.time())
		
		self.initBT()
		
	def run(self):
		self.drawFront()
		last_redraw = time.time()
		####last_packet = time.time()

		threading.Thread(target=self.listenerThread).start()

		# Just a temp loop while we get things set up
		while self.RUNNING:
			#This stops 100% CPU usage
			time.sleep(0.01)

			if (time.time() - self.page_time) >= self.page_swap:
				self.page_num = self.page_num + 1
				self.page_time = time.time()
				if self.page_num >= self.num_pages:
					self.page_num = 0
			if (time.time() - last_redraw) >= 5:
				last_redraw = time.time()
				self.REDRAW = True
			#	if not self.CONNECTED:
			#		self.newMsg("Retrying connection to SideShow server", time.time())
			#		self.BTclient()
			
			events = pygame.event.get()
			self.processEvent(events)
			
			
			####if self.CONNECTED:
				# Are we still connected?
				####if (time.time() - last_packet) >= 30:
				####	self.newMsg("Checking connection", time.time())
				####	self.send_PING()
				####try:
				####	self.data = self.client_sock.recv(32768)
				####except:
				####	self.data = ""
				####if len(self.data) != 0:
				####	last_packet = time.time()
				####	if PLATFORM == "n800":
				####		device.display_state_on()
				####		device.display_blanking_pause()
				####	self.listener()
				####	self.drawFront()
				
			# Let's see if we can check the battery here
			if PLATFORM == "n800":
				bus = dbus.SystemBus()
				hal_obj = bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
				hal = dbus.Interface(hal_obj, 'org.freedesktop.Hal.Manager')
				dev_obj = bus.get_object("org.freedesktop.Hal", hal.FindDeviceByCapability("battery")[0])
				dev = dbus.Interface(dev_obj, "org.freedesktop.Hal.Device")
				#props = dev.GetAllProperties()
				#log.debug(props)
				self.bat_level = dev.GetProperty('battery.charge_level.percentage')
				if dev.GetProperty('battery.rechargeable.is_charging'):
					self.on_ac = True
				else:
					self.on_ac = False
			else:
				bus = dbus.SystemBus()
				hal_obj = bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
				hal = dbus.Interface(hal_obj, 'org.freedesktop.Hal.Manager')
				dev_obj = bus.get_object("org.freedesktop.Hal", hal.FindDeviceByCapability("ac_adapter")[0])
				dev = dbus.Interface(dev_obj, "org.freedesktop.Hal.Device")
				if dev.GetProperty('ac_adapter.present'):
					self.on_ac = True
				else:
					self.on_ac = False
					dev_obj = bus.get_object("org.freedesktop.Hal", hal.FindDeviceByCapability("battery")[0])
					dev = dbus.Interface(dev_obj, "org.freedesktop.Hal.Device")
					self.bat_level = dev.GetProperty('battery.charge_level.percentage')
		
	def processEvent(self, events):

		#try:
		#	self.data = self.client_sock.recv(32768)
		#except:
		#	self.data = ""
		#if len(self.data) != 0:
		#	self.listener()

		if self.upd_GUID != None:
			#log.debug("Content for current cid")
			self.selected_menu = None
			self.current_guid = None
			self.current_cid = None
			self.showContent(self.upd_GUID, self.upd_CID)
			self.upd_GUID = None
			self.upd_CID = None
			self.REDRAW = True

		if self.REDRAW == True:
			self.drawFront()
			self.REDRAW = False

		for event in events:		
			if event.type == pygame.QUIT:
				self.byebye()
			elif event.type == pygame.MOUSEBUTTONUP:
				if self.icon_exit_r.collidepoint(event.pos):
					self.byebye()
				
				# Click menu
				#if self.menu_s:
				#	for i in range(len(self.menu_rect)):
				#		if self.menu_rect[i][2].collidepoint(event.pos):
				#			#log.debug(str(self.menu_rect[i][0]) + " : " + str(self.menu_rect[i][1]))
				#			self.breadcrumb.append(self.menu_rect[i][1])
				#			self.showContent(self.menu_rect[i][0], self.menu_rect[i][1])
				#			self.drawFront()
				
				# Click gadget
				if not self.menu_s:
					if (self.page_num * 5) + 5 > len(self.apps_guid):
						page_bot = len(self.apps_guid)
					else:
						page_bot = (self.page_num * 5) + 5
					for i in range(self.page_num*5, page_bot):
						if self.apps_rect[i].collidepoint(event.pos):
							self.breadcrumb.append(1)
							self.showContent(self.apps_guid[i], 1)
							self.REDRAW = True
				
			elif event.type == pygame.KEYUP:
				if (len(self.buttons_keys) != 0) and (not self.menu_s):
					if (event.key == pygame.K_LEFT):
						try:
							i = self.buttons_keys.index("left")
							target = int(self.buttons_ids[i])
							self.send_BUTTONACTION(self.apps_guid[self.gadget_selected], self.breadcrumb[-1], target, SCF_BUTTON_LEFT)
							if target != self.current_cid:
								self.showContent(self.current_guid, target)
							return
						except:
							return
					if (event.key == pygame.K_RIGHT):
						try:
							i = self.buttons_keys.index("right")
							target = int(self.buttons_ids[i])
							self.send_BUTTONACTION(self.apps_guid[self.gadget_selected], self.breadcrumb[-1], target, SCF_BUTTON_RIGHT)
							if target != self.current_cid:
								self.showContent(self.current_guid, target)
							return
						except:
							return
					if (event.key == pygame.K_RETURN):
						try:
							i = self.buttons_keys.index("enter")
							target = int(self.buttons_ids[i])
							self.send_BUTTONACTION(self.apps_guid[self.gadget_selected], self.breadcrumb[-1], target, SCF_BUTTON_SELECT)
							if target != self.current_cid:
								self.showContent(self.current_guid, target)
							return
						except:
							return

				if (not self.menu_s) and (not self.content_s):
					if (event.key == pygame.K_RETURN):
						self.breadcrumb.append(1)
						self.showContent(self.apps_guid[self.gadget_selected], 1)
						self.REDRAW = True
						return
					if (event.key == pygame.K_UP):
						self.gadget_selected = self.gadget_selected - 1
						if self.gadget_selected < 0:
							self.gadget_selected = len(self.apps_guid) - 1
							self.page_num = self.num_pages - 1
						if self.gadget_selected < (self.page_num * 5):
							self.page_num = self.page_num -1
						self.page_time = time.time()
						self.REDRAW = True
						return
					if (event.key == pygame.K_DOWN):
						self.gadget_selected = self.gadget_selected + 1
						if self.gadget_selected >= len(self.apps_guid):
							self.gadget_selected = 0
							self.page_num = 0
						if self.gadget_selected >= ((self.page_num * 5) + 5):
							self.page_num = self.page_num + 1
							if self.page_num >= self.num_pages:
								self.page_num = 0
						self.page_time = time.time()
						self.REDRAW = True
						return

				if self.menu_s:
					if (event.key == pygame.K_RETURN):
						pass_sel = self.selected_menu
						if self.current_menu[5][pass_sel]:
							self.send_APPLICATIONEVENT(self.current_menu[4], SCF_EVENT_MENUACTION, int(self.current_menu[2][pass_sel]), int(self.current_menu[2][pass_sel]), SCF_BUTTON_SELECT, int(self.current_menu[5][pass_sel]))
							####try:
							####	self.data = self.client_sock.recv(32768)
							####except:
							####	self.data = ""
							####if len(self.data) != 0:
							####	self.listener()
						else:
							self.breadcrumb.append(int(self.current_menu[2][pass_sel]))
						self.selected_menu = None
						self.showContent(self.current_menu[4], int(self.current_menu[2][pass_sel]))
						self.REDRAW = True
						return
					if (event.key == pygame.K_DOWN):
						self.selected_menu = self.selected_menu + 1
						self.display_menu(self.current_menu[0],self.current_menu[1], self.current_menu[2], self.current_menu[3], self.current_menu[4], self.current_menu[5])
						self.REDRAW = True
						return
						
					if (event.key == pygame.K_UP):
						self.selected_menu = self.selected_menu - 1
						self.display_menu(self.current_menu[0],self.current_menu[1], self.current_menu[2], self.current_menu[3], self.current_menu[4], self.current_menu[5])
						self.REDRAW = True
						return
				
				if (event.key == pygame.K_ESCAPE):
					if len(self.breadcrumb) != 0:
						del self.breadcrumb[-1]
						if len(self.breadcrumb) !=0:
							self.showContent(self.current_guid, self.breadcrumb[-1])
							self.REDRAW = True
						else:
							self.content_s = None
							self.current_menu = []
							self.selected_menu = None
							self.menu_s = None
							self.current_guid = None
							self.current_cid = None
							self.buttons_keys = []
							self.buttons_ids = []
							self.buttons_text = []
							self.REDRAW = True
					if self.menu_s:
						#del self.breadcrumb[-1]
						if len(self.breadcrumb) !=0:
							self.showContent(self.current_guid, self.breadcrumb[-1])
							self.REDRAW = True
						else:
							self.content_s = None
							self.current_menu = []
							self.selected_menu = None
							self.menu_s = None
							self.current_guid = None
							self.current_cid = None
							self.buttons_keys = []
							self.buttons_ids = []
							self.buttons_text = []
							self.REDRAW = True
						return

				if (event.key == pygame.K_F6):
					pygame.display.toggle_fullscreen()
					return
				if (event.key == pygame.K_F7):
					self.page_swap = self.page_swap + 1
					if self.page_swap > 60:
						self.page_swap = 60
					self.newMsg("Page delay set to " + str(self.page_swap) + " seconds", time.time())
					self.REDRAW = True
					return
				if (event.key == pygame.K_F8):
					self.page_swap = self.page_swap - 1
					if self.page_swap < 1:
						self.page_swap = 1
					self.newMsg("Page delay set to " + str(self.page_swap) + " seconds", time.time())
					self.REDRAW = True
					return

	def newMsg(self, msg, when):
		self.msg = msg
		self.msg_time = when
		self.REDRAW = True
						
	def byebye(self):
		self.RUNNING = False
		self.newMsg("Quitting", time.time())
		log.debug("Shutting down")
		self.endBT()
		self.writeConfig()

	def drawFront(self):
		self.bg_r = self.bg.get_rect()
		self.screen.blit(self.bg, self.bg_r)
		
		self.drawBar()
		
		self.drawGadgets()

		self.drawMsg()

		if self.show_no_bt == True:
			self.no_bt_r = self.no_bt.get_rect()
			self.no_bt_r.left = ((self.screen.get_width() / 2) - (self.no_bt_r.width / 2))
			self.no_bt_r.top = ((self.screen.get_height() / 2) - (self.no_bt_r.height / 2))
			self.screen.blit(self.no_bt, self.no_bt_r)
			self.no_bt_t = self.user_f.render("Have you enabled the SideShow service?", 1, (255, 255, 255))
			self.no_bt_t_r = self.no_bt_t.get_rect()
			self.no_bt_t_r.left = ((self.screen.get_width() / 2) - (self.no_bt_t_r.width / 2))
			self.no_bt_t_r.top = self.no_bt_r.top - 30
			self.screen.blit(self.no_bt_t, self.no_bt_t_r)

		if self.content_s:
			content_s_r = self.content_s.get_rect()
			content_s_r.top = 5
			content_s_r.left = (self.screen.get_width() / 2) - (content_s_r.width / 2)
			self.screen.blit(self.content_s, content_s_r)

		if self.menu_s:
			menu_s_r = self.menu_s.get_rect()
			menu_s_r.top = 20
			menu_s_r.left = (self.screen.get_width() / 2) - (menu_s_r.width / 2)
			self.screen.blit(self.menu_s, menu_s_r)

		if len(self.buttons_keys) != 0:
			self.drawButtons()

		if self.start_time > (time.time() - 5):
			self.splash_r = self.splash.get_rect()
			self.splash_r.left = ((self.screen.get_width() / 2) - (self.splash_r.width / 2))
			self.splash_r.top = ((self.screen.get_height() / 2) - (self.splash_r.height / 2))
			self.screen.blit(self.splash, self.splash_r)
		
		pygame.display.flip()
		
		if PLATFORM == "n800":
			device.display_state_on()
			device.display_blanking_pause()
		
	def drawBar(self):
		self.bar_bg_r = self.bar_bg.get_rect()
		self.bar_bg_r.left = 0
		self.bar_bg_r.top = (self.screen.get_height() - self.bar_bg_r.height)
		self.screen.blit(self.bar_bg, self.bar_bg_r)
		
		self.icon_exit_r = self.icon_exit.get_rect()
		self.icon_exit_r.left = 10
		self.icon_exit_r.top = (self.bar_bg_r.top + (self.bar_bg_r.height / 2)) - (self.icon_exit_r.height / 2)
		self.screen.blit(self.icon_exit, self.icon_exit_r)
		
		self.drawClock()
		
		self.drawBattery()
		
		if self.CONNECTED:
			self.icon_bt_r = self.icon_bt.get_rect()
			self.icon_bt_r.right = self.icon_bat_r.left - 3
			self.icon_bt_r.top = (self.bar_bg_r.top + (self.bar_bg_r.height / 2)) - (self.icon_bt_r.height / 2)
			self.screen.blit(self.icon_bt, self.icon_bt_r)
		
		if self.user != "":
			self.user_t = self.user_f.render(self.user, 1, (255, 255, 255))
			self.user_t_r = self.user_t.get_rect()
			self.user_t_r.left = self.icon_exit_r.right + 10
			self.user_t_r.top = (self.bar_bg_r.top + (self.bar_bg_r.height / 2)) - (self.user_t_r.height / 2)
			self.screen.blit(self.user_t, self.user_t_r)
			
		self.version_t = self.version_f.render(VERSION, 1, (255, 255, 255))
		self.version_t_r = self.version_t.get_rect()
		self.version_t_r.right = self.screen.get_width() - 2
		self.version_t_r.bottom = self.bar_bg_r.top - 2
		self.screen.blit(self.version_t, self.version_t_r)

	def drawBattery(self):
		if self.on_ac == True:
			self.icon_bat_r = self.icon_bat_charging.get_rect()
			self.icon_bat_r.right = self.clock_t_r.left - 10
			self.icon_bat_r.top = (self.bar_bg_r.top + (self.bar_bg_r.height / 2)) - (self.icon_bat_r.height / 2)
			self.screen.blit(self.icon_bat_charging, self.icon_bat_r)
		else:
			if self.bat_level >= 75:
				self.icon_bat_r = self.icon_bat_100.get_rect()
				bat_icon = self.icon_bat_100
			if self.bat_level <= 75:
				self.icon_bat_r = self.icon_bat_75.get_rect()
				bat_icon = self.icon_bat_75
			if self.bat_level <= 50:
				self.icon_bat_r = self.icon_bat_50.get_rect()
				bat_icon = self.icon_bat_50
			if self.bat_level <= 25:
				self.icon_bat_r = self.icon_bat_25.get_rect()
				bat_icon = self.icon_bat_25
			if self.bat_level <= 10:
				self.icon_bat_r = self.icon_bat_0.get_rect()
				bat_icon = self.icon_bat_0
			
			self.icon_bat_r.right = self.clock_t_r.left - 10
			self.icon_bat_r.top = (self.bar_bg_r.top + (self.bar_bg_r.height / 2)) - (self.icon_bat_r.height / 2)
			self.screen.blit(bat_icon, self.icon_bat_r)
		
	def drawClock(self):
		time_t = time.strftime("%H:%M", time.gmtime(time.time() + self.time_dif + (self.time_bias * 60)))
		self.clock_t = self.clock_f.render(time_t, 1, (255, 255, 255))
		self.clock_t_r = self.clock_t.get_rect()
		self.clock_t_r.right = (self.screen.get_width() - 10)
		self.clock_t_r.top = (self.bar_bg_r.top + (self.bar_bg_r.height / 2)) - (self.clock_t_r.height / 2)
		self.screen.blit(self.clock_t, self.clock_t_r)

	def drawButtons(self):
		ypos = 30
		for i in range(len(self.buttons_keys)):
			icon = self.dpad.copy()
			icon_r = icon.get_rect()
			if self.buttons_keys[i] == "enter":
				pos = (icon_r.width / 2, icon_r.height / 2)
				pygame.draw.circle(icon, (255, 0, 0, 128), (pos), 5, 0)
			if self.buttons_keys[i] == "left":
				pos = (icon_r.width / 4, icon_r.height / 2)
				pygame.draw.circle(icon, (255, 0, 0, 128), (pos), 5, 0)
			if self.buttons_keys[i] == "right":
				pos = (((icon_r.width / 4) * 3) + 3, icon_r.height / 2)
				pygame.draw.circle(icon, (255, 0, 0, 128), (pos), 5, 0)
			icon_r.top = ypos
			icon_r.left = 750 - (icon_r.width / 2)
			self.screen.blit(icon, icon_r)
			ypos = ypos + icon_r.height + 2
			if self.buttons_text[i] != None:
				but_txt = self.buttons_text[i]
			else:
				but_txt = " "
			but_t = self.small_f.render(but_txt, 1, (255, 255, 255))
			but_t_r = but_t.get_rect()
			but_t_r.top = ypos
			but_t_r.left = 750 - (but_t_r.width / 2)
			self.screen.blit(but_t, but_t_r)
			ypos = ypos + but_t_r.height + 6

	def drawMsg(self):
		if self.msg != "":
			if (time.time() - self.msg_time) <= 5:
				self.msg_box_bg_r = self.msg_box_bg.get_rect()
				self.msg_box_bg_r.left = 10
				self.msg_box_bg_r.bottom = self.bar_bg_r.top - 5
				self.screen.blit(self.msg_box_bg, self.msg_box_bg_r)
				
				self.msg_t = self.def_f.render(self.msg, 1, (255, 255, 255))
				self.msg_t_r = self.msg_t.get_rect()
				self.msg_t_r.left = 20
				self.msg_t_r.top = (self.msg_box_bg_r.top + (self.msg_box_bg_r.height / 2)) - (self.msg_t_r.height / 2)
				self.screen.blit(self.msg_t, self.msg_t_r)
			else:
				self.msg=""
		
	def drawGadgets(self):
		ypos = 10
		if (len(self.apps_guid)/5) != (len(self.apps_guid)/5.0):
			self.num_pages = (len(self.apps_guid)/5) + 1
		else:
			self.num_pages = (len(self.apps_guid)/5)

		if len(self.apps_guid) != 0:
			if (self.page_num * 5) + 5 > len(self.apps_guid):
				page_bot = len(self.apps_guid)
			else:
				page_bot = (self.page_num * 5) + 5
			got_gadget_page = False
			for i in range(self.page_num*5, page_bot):
				if self.gadget_selected == i:
					got_gadget_page = True
			if got_gadget_page == False:
				self.gadget_selected = self.page_num*5
			for i in range(self.page_num*5, page_bot):
				if self.gadget_selected == i:
					got_gadget_page = True
				self.box_bg_r = self.box_bg.get_rect()
				self.gadget_s = pygame.Surface(self.box_bg_r.size, pygame.SRCALPHA, 32)
				if self.gadget_selected == i:
					self.gadget_s.blit(self.box_bg_sel, self.box_bg_r)
				else:				
					self.gadget_s.blit(self.box_bg, self.box_bg_r)
				text = self.apps_glance[i]
				# Glance text
				my_rect = self.gadget_s.get_rect()
				my_rect.width = my_rect.width - 72
				my_rect.left = my_rect.left + 72
				my_rect.right = my_rect.right - 10
				my_rect.height = my_rect.height - 10
				my_rect.top = my_rect.top + 5
				rendered_text, text_height = multiline.render_textrect(text, self.def_f, my_rect, (255, 255, 255), None, 0)
				my_rect.top = (my_rect.top + (my_rect.height/2)) - (text_height/2)
				self.gadget_s.blit(rendered_text, my_rect)
				# Icon
				f = StringIO(self.apps_icon[i])
				icon = pygame.image.load(f, "icon.bmp")
				f.close()
				icon.set_colorkey((0, 0, 0))
				icon_r = icon.get_rect()
				icon_r.left = 10
				icon_r.top = (self.box_bg_r.top + (self.box_bg_r.height/2)) - (icon_r.height/2)
				self.gadget_s.blit(icon, icon_r)
				# Place gadget on screen
				self.gadget_s_r = self.gadget_s.get_rect()
				self.gadget_s_r.top = ypos
				self.gadget_s_r.left = 10
				self.screen.blit(self.gadget_s, self.gadget_s_r)
				ypos = ypos + (self.box_bg_r.height + 10)
				self.apps_rect[i] = self.gadget_s_r
		
	def showContent(self, guid, cid):
		#log.debug("Doing gadget : " + str(guid))
		self.current_guid = guid
		self.current_cid = cid

		self.buttons_keys = []
		self.buttons_ids = []
		self.buttons_text = []

		self.menu_s = None
		self.content_s = None
		
		cont = self.getContent(guid, cid)
		if cont == None:
			needit = True
		else:
			needit = False

		if needit == True:	
			#request missing content
			#self.newMsg("Content not yet available.  Requesting it.", time.time())
			self.send_CONTENTMISSING(guid, cid)
			while needit == True:
				####try:
				####	self.data = self.client_sock.recv(32768)
				####except:
				####	self.data = ""
				####if len(self.data) != 0:
				####	self.listener()
				try:
					isitthere = self.getContent(guid, cid)
					if isitthere:
						if isitthere != None:
							needit = False
				except:
					pass

		if cont:
			#log.debug(cont)
			try:
				xmldoc = xml.dom.minidom.parseString(cont.strip(chr(0)))
				try:
					menu = xmldoc.getElementsByTagName('menu')
				except:
					pass

				try:
					content_page = xmldoc.getElementsByTagName('content')
				except:
					pass

				if len(content_page) != 0:
					try:
						title = content_page[0].attributes["title"].value
					except:
						title = None

					ypos = 5
					self.content_s = pygame.Surface((600, 420), pygame.SRCALPHA, 32)
					self.content_s.fill((64, 64, 64, 192), (0, 0, 600, 420))

					txt_t = self.user_f.render(title, 1, (255, 255, 255))
					txt_t_r = txt_t.get_rect()
					txt_t_r.top = ypos
					txt_t_r.left = (self.content_s.get_width() / 2) - (txt_t_r.width / 2)
					self.content_s.blit(txt_t, txt_t_r)
					ypos = ypos + txt_t_r.height + 4
					
					lines = content_page[0].childNodes
					for line in lines:
						if line.nodeType == line.ELEMENT_NODE:
							line_cont = line.tagName
							if line_cont == "btn":
								target = line.attributes["target"].value
								button = line.attributes["key"].value
								self.buttons_keys.append(button)
								self.buttons_ids.append(target)
								try:
									self.buttons_text.append(line.firstChild.data)
								except:
									self.buttons_text.append(None)
							if line_cont == "img":
								img_data = self.getContent(guid, int(line.attributes["id"].value))
								if img_data != None:
									f = StringIO(img_data)
									img = pygame.image.load(f)
									f.close()
									img_r = img.get_rect()
									img_r.left = (self.content_s.get_width() / 2) - (img_r.width / 2)
									img_r.top = ypos
									self.content_s.blit(img, img_r)
									ypos = ypos + img_r.height + 4
								else:
									self.send_CONTENTMISSING(guid, int(line.attributes["id"].value))

							if line_cont == "txt":
								try:
									al = line.attributes["align"].value
									if al == "c":
										al = 1
									if al == "l":
										al = 0
									if al == "r":
										al = 2
								except:
									al = 0
								for row in line.childNodes:
									to_show = row.toxml()
									test_empty = ""
									test_empty = test_empty.join(to_show.split())
									if test_empty == "<em/>":
										test_empty = ""
									if  test_empty != "":
										to_show = to_show.replace("<![CDATA[" , "")
										to_show = to_show.replace("]]>" , "")
										to_show = to_show.replace("<br/>" , "\n")
										#txt_t = self.def_f.render(to_show, 1, (255, 255, 255))
										rect = self.content_s.get_rect()
										rect.width = rect.width - 8
										if (to_show[:4] == "<em>") and (to_show[-5:] == "</em>"):
											to_show = to_show.replace("<em>", "")
											to_show = to_show.replace("</em>", "")
											txt_t, text_height = multiline.render_textrect(to_show, self.defbold_f, rect, (255, 255, 255), None, al)
										else:
											txt_t, text_height = multiline.render_textrect(to_show, self.def_f, rect, (255, 255, 255), None, al)
										txt_t_r = txt_t.get_rect()
										txt_t_r.top = ypos
										txt_t_r.left = (self.content_s.get_width() / 2) - (txt_t_r.width / 2)
										self.content_s.blit(txt_t, txt_t_r)
										#ypos = ypos + txt_t_r.height + 4
										ypos = ypos + text_height + 4
							
					crop_r = self.content_s.get_rect()
					crop_r.height = ypos + 5
					crop_s = pygame.Surface((crop_r.width, crop_r.height), pygame.SRCALPHA, 32)
					crop_s.blit(self.content_s, crop_r)
					self.content_s = crop_s
			
						
				if len(menu) != 0:
					try:
						title = menu[0].attributes["title"].value
					except:
						title = None
					try:
						menu_action = menu[0].attributes["selectaction"].value
					except:
						menu_action = None
					menu_text = []
					menu_target = []
					menu_image = []
					menu_id = []
					items = menu[0].getElementsByTagName('item')
					for item in items:
						menu_text.append(item.firstChild.data)
						try:
							menu_id.append(item.attributes["id"].value)
						except:
							menu_id.append(None)

						try:
							menu_image.append(item.attributes["imgid"].value)
						except:
							menu_image.append(None)

						menu_target.append(item.attributes["target"].value)
						
					self.current_menu = []
					self.current_menu.append(title)
					self.current_menu.append(menu_text)
					self.current_menu.append(menu_target)
					self.current_menu.append(menu_image)
					self.current_menu.append(guid)
					self.current_menu.append(menu_id)
					self.display_menu(title, menu_text, menu_target, menu_image, guid, menu_id)
			except:
				log.debug("Error parsing xml data")
				self.newMsg("Content not yet available.  Requesting it.", time.time())
				#log.debug(traceback.print_exc())
		else:
			# Content not yet available.  Will request it.
			self.newMsg("Content not yet available.  Requesting it.", time.time())
		
	def display_menu(self, title, menu_text, menu_target, menu_image, guid, menu_id):
		#log.debug(title)
		menu_s_height = len(menu_text) * 27
		self.menu_s = pygame.Surface((400, menu_s_height), pygame.SRCALPHA, 32)
		ypos = 5
		if self.selected_menu == None:
			self.selected_menu = 0
		if self.selected_menu < 0:
			self.selected_menu = len(menu_text) - 1
		if self.selected_menu >= len(menu_text):
			self.selected_menu = 0
		range_start = 0
		range_end = len(menu_text)
		if self.selected_menu >= 15:
			range_end = self.selected_menu + 15
			range_start = self.selected_menu - 15
		if range_end > len(menu_text):
			range_end = len(menu_text)
		num_displayed = 0
		for i in range(range_start, range_end):
			#log.debug(menu_target[i] + " : " + menu_text[i])
			if i == self.selected_menu:
				self.menu_s.fill((128, 128, 128, 192), (0, ypos, 400, 22))
			else:
				self.menu_s.fill((64, 64, 64, 192), (0, ypos, 400, 22))
			menu_t = self.menu_f.render(menu_text[i], 1, (255, 255, 255))
			menu_t_r = menu_t.get_rect()
			menu_t_r.top = ypos + ((11) - (menu_t_r.height / 2))
			menu_t_r.left = 35
			self.menu_s.blit(menu_t, menu_t_r)
			menu_rect_r = self.menu_s.get_rect()
			menu_rect_r.left = (self.screen.get_width() / 2) - 200
			menu_rect_r.top = ypos + 20
			menu_rect_r.height = 22
			menu_rect_r.width = 400
			if menu_image[i]:
							
				menu_icon = self.getContent(guid, int(menu_image[i]))

				if menu_icon != None:
					f = StringIO(menu_icon)
					icon = pygame.image.load(f)
					f.close()
					#icon.set_colorkey((0, 0, 0))
					icon_r = icon.get_rect()
					icon_r.left = 10
					icon_r.top = ypos + ((11) - (icon_r.height / 2))
					self.menu_s.blit(icon, icon_r)
			ypos = ypos + 25
			num_displayed = num_displayed + 1
			if num_displayed == 16:
				break
		
	def initBT(self):
		self.BTserver()
		self.BTclient()
			
	def BTserver(self):
		self.server_sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
		
		#if PLATFORM == "n800":
			#port = bluetooth.get_available_port( bluetooth.RFCOMM )
			#self.server_sock.bind(("",port))
		self.server_sock.bind(("", bluetooth.PORT_ANY))
		(addr, port) = self.server_sock.getsockname();
		#else:
		#	self.server_sock.bind(("", bluetooth.PORT_ANY))
		#	(addr, port) = self.server_sock.getsockname();

		log.debug("Opening BT server")
		self.server_sock.listen(1)
		
		# Announce SideShow support
		log.debug("Advertising SideShow sevice")
		uuid = "5d9dda39-1e82-49c7-a0d6-6507ba9287ef"
		bluetooth.advertise_service( self.server_sock, "SideShow", service_id = uuid, service_classes = [ uuid ], profiles = [bluetooth.SERIAL_PORT_PROFILE] )
		
	def BTclient(self):
		# Get MAC address of BT adapter.  This is needed because SideShow creates a service ID based on it.
		log.debug("Getting local BT adapter MAC address")
		bus = dbus.SystemBus();
		obj = bus.get_object('org.bluez','/org/bluez')
		manager = dbus.Interface(obj,'org.bluez.Manager')
		obj = bus.get_object('org.bluez',manager.DefaultAdapter())
		adapter = dbus.Interface(obj,'org.bluez.Adapter')
		self.lmac_f = adapter.GetAddress()
		log.debug("Local address - " + self.lmac_f)
		
		self.newMsg("Looking for SideShow server", time.time())
		
		if self.last_mac != "":
			self.connectBT(self.last_mac)
		
		if self.CONNECTED == False:
			# I don't like getting a list of paired devices like this.
			# There MUST be a way to do it in dbus.
			f = open ("/var/lib/bluetooth/" + self.lmac_f + "/trusts","r")
			while self.RUNNING == True:
				events = pygame.event.get()
				self.processEvent(events)
				if self.RUNNING == False:
					break
				rmac = f.readline()
				if not rmac:
					break
				server_mac=rmac[:17]
				self.connectBT(server_mac)

			f.close()
		if self.CONNECTED == False:
			self.show_no_bt = True
			self.newMsg("Couldn't find SideShow service", time.time())
			log.debug("Couldn't find SideShow service")
			
	def connectBT(self, mac):
		log.debug("Finding SideShow service: " + mac)
		self.newMsg("Finding SideShow service: " + mac, time.time())
		lmac = self.lmac_f.split(':')
		ss_sdp = "5d9dda39-1e82-49c7-" + lmac[5] + lmac [4] + "-" + lmac[3] + lmac[2] + lmac[1] + lmac[0] + "87ef"
		services = bluetooth.find_service(uuid=ss_sdp, address=mac)
		if services:
			for i in range(len(services)):
				match=services[i]
				port=match["port"]
				name=match["name"]
				host=match["host"]		
				log.debug("Found " + name + " at " + host)
		
			log.debug("Connecting client to BT server")
			self.newMsg("Connecting to SideShow server", time.time())
			self.client_sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
			try:
				self.client_sock.connect((host,port))
				self.client_sock.setblocking(False)
				self.CONNECTED = True
				self.show_no_bt = False
				self.last_mac = mac
			except:
				log.debug("Some went wrong during connection")
			
	def endBT(self):
		if self.CONNECTED == True:
			log.debug("Closing BT client")
			self.client_sock.close()
			self.CONNECTED = False
		log.debug("Closing BT server")
		self.server_sock.close()

	def addContent(self, guid, cid, content):
		try:
			i = self.apps_guid.index(guid)
			content_list = self.apps_content[i]
			if content_list == None:
				cont_ids = []
				cont_cont = []
			else:
				cont_ids = content_list[0]
				cont_cont = content_list[1]
			#log.debug(cont_ids)
			try:
				i = cont_ids.index(cid)
				# There.  Change it.
				cont_cont[i] = content
			except:
				# Not there.  Add it.
				cont_ids.append(cid)
				cont_cont.append(content)
			i = self.apps_guid.index(guid)
			self.apps_content[i] = [cont_ids, cont_cont]
		except:
			pass

	def delContent(self, guid, cid):
		try:
			i = self.apps_guid.index(guid)
			content_list = self.apps_content[i]
			cont_ids = content_list[0]
			cont_cont = content_list[1]
			i = cont_ids.index(cid)
			del cont_ids[i]
			del cont_cont[i]
			i = self.apps_guid.index(guid)
			self.apps_content[i] = [cont_ids, cont_cont]
		except:
			pass

	def getContent(self, guid, cid):
		try:
			i = self.apps_guid.index(guid)
			content_list = self.apps_content[i]
			cont_ids = content_list[0]
			cont_cont = content_list[1]
			i = cont_ids.index(cid)
			content = cont_cont[i]
			return content
		except:
			return None
		
	def listener(self):
		#log.debug("Got " + str(len(self.data)) + " bytes")
		packet_size = len(self.data)
		header_size = struct.unpack('L', self.data[:4])[0]
		#log.debug(str(header_size))
		####while packet_size < header_size:
		####	events = pygame.event.get()
		####	self.processEvent(events)
		####	if self.RUNNING == False:
		####		break
		####	try:
		####		self.data = self.data + self.client_sock.recv(32768)
		####		packet_size = len(self.data)
		####	except:
		####		self.data = self.data
					
		if packet_size >= header_size:
			packet_type = struct.unpack('L', self.data[4:8])[0]
			packet_num = struct.unpack('H', self.data[8:10])[0]
			self.packet_count = packet_num
			packet_data = ""
			for msgb in range(10, header_size):
				packet_data = packet_data + self.data[msgb]

			#log.debug(hex(packet_type))

			####
			self.data = self.data[header_size:]
			####
			
			if packet_type == SETUSERSTATE:
				self.resp_SETUSERSTATE(packet_type, packet_num, packet_data)
				self.REDRAW = True
				return

			if packet_type == SETCURRENTUSER:
				self.resp_SETCURRENTUSER(packet_type, packet_num, packet_data)
				return

			if packet_type == GETCURRENTUSER:
				self.resp_GETCURRENTUSER(packet_type, packet_num, packet_data)
				return

			if packet_type == GETCAPABILITIES:
				self.resp_GETCAPABILITIES(packet_type, packet_num, packet_data)
				return

			if packet_type == GETAPPLICATIONORDER:
				self.resp_GETAPPLICATIONORDER(packet_type, packet_num, packet_data)
				return

			if packet_type == SETAPPLICATIONORDER:
				self.resp_SETAPPLICATIONORDER(packet_type, packet_num, packet_data)
				return
				
			if packet_type == SETTIME:
				self.resp_SETTIME(packet_type, packet_num, packet_data)
				return
				
			if packet_type == SETSHORTDATEFORMAT:
				self.resp_SETSHORTDATEFORMAT(packet_type, packet_num, packet_data)
				return

			if packet_type == SETLONGDATEFORMAT:
				self.resp_SETLONGDATEFORMAT(packet_type, packet_num, packet_data)
				return
				
			if packet_type == SETSHORTTIMEFORMAT:
				self.resp_SETSHORTTIMEFORMAT(packet_type, packet_num, packet_data)
				return
				
			if packet_type == ADDAPPLICATION:
				self.resp_ADDAPPLICATION(packet_type, packet_num, packet_data)
				return
				
			if packet_type == DELETEAPPLICATION:
				self.resp_DELETEAPPLICATION(packet_type, packet_num, packet_data)
				return
							
			if packet_type == ADDCONTENTITEM:
				self.resp_ADDCONTENTITEM(packet_type, packet_num, packet_data)
				return
				
			if packet_type == DELETECONTENTITEM:
				self.resp_DELETECONTENTITEM(packet_type, packet_num, packet_data)
				return
				
			if packet_type == DELETEALLCONTENTITEMS:
				self.resp_DELETEALLCONTENTITEMS(packet_type, packet_num, packet_data)
				return
				
			if packet_type == GETSUPPORTEDENDPOINTS:
				self.resp_GETSUPPORTEDENDPOINTS(packet_type, packet_num, packet_data)
				return

			if packet_type == SETTIMEZONE:
				self.resp_SETTIMEZONE(packet_type, packet_num, packet_data)
				return
				
			if packet_type == SYNC:
				self.resp_SYNC(packet_type, packet_num, packet_data)
				return
				
			if hex(packet_type)[:6] == "0x8000":
				#log.debug("Got an ACK")
				####if len(self.data) > header_size:
				####	delit = len(self.data)
				####	self.data = self.data[-(delit-header_size):]
				####	self.listener()
				return
				
			
			log.debug("Got an unknown packet type: " + hex(packet_type))
	
	
	# 0x1 Send ping
	def send_PING(self):
		log.debug("Sending ping")
		ping = ""
		ping = chr(0x1 % 0x100) + chr((0x1 >> 8) % 0x100) + chr((0x1 >> 16) % 0x100) + chr(((0x1 >> 24) % 0x100))
		ping = ping + self.pack_num(self.packet_count + 1)
		ping_len = len(ping) + 4
		ping = self.pack_len(ping_len) + ping
		try:
			self.client_sock.sendall(ping)
		except:
			self.CONNECTED = False

	# 0x4000
	def send_CONTENTMISSING(self, guid, cid):
		cm = ""
		cm = chr(0x4000 % 0x100) + chr((0x4000 >> 8) % 0x100) + chr((0x4000 >> 16) % 0x100) + chr(((0x4000 >> 24) % 0x100))
		cm = cm + self.pack_num(self.packet_count + 1)
		cm = cm + guid.bytes_le
		scf = uuid.UUID('{A9A5353F-2D4B-47ce-93EE-759F3A7DDA4F}')
		cm = cm + scf.bytes_le
		cm = cm + chr(cid % 0x100) + chr((cid >> 8) % 0x100) + chr((cid >> 16) % 0x100) + chr(((cid >> 24) % 0x100))
		cm_len = len(cm) + 4
		cm = self.pack_len(cm_len) + cm
		self.client_sock.sendall(cm)

	# 0x4001
	def send_APPLICATIONEVENT(self, guid, eventid, ppg, tpg, but, item):
		#log.debug("Sending APPLICATIONEVENT")
		ae = ""
		ae = chr(0x4001 % 0x100) + chr((0x4001 >> 8) % 0x100) + chr((0x4001 >> 16) % 0x100) + chr(((0x4001 >> 24) % 0x100))
		ae = ae + self.pack_num(self.packet_count + 1)
		ae = ae + guid.bytes_le
		scf = uuid.UUID('{A9A5353F-2D4B-47ce-93EE-759F3A7DDA4F}')
		ae = ae + scf.bytes_le
		# Event ID.  2 for menu action
		ae = ae + chr(eventid % 0x100) + chr((eventid >> 8) % 0x100) + chr((eventid >> 16) % 0x100) + chr(((eventid >> 24) % 0x100))
		# Hard coded event data size
		ae = ae + chr(16 % 0x100) + chr((16 >> 8) % 0x100) + chr((16 >> 16) % 0x100) + chr(((16 >> 24) % 0x100))
		# Event data
		# Previous page.  Target page
		ae = ae + chr(ppg % 0x100) + chr((ppg >> 8) % 0x100) + chr((ppg >> 16) % 0x100) + chr(((ppg >> 24) % 0x100))
		ae = ae + chr(tpg % 0x100) + chr((tpg >> 8) % 0x100) + chr((tpg >> 16) % 0x100) + chr(((tpg >> 24) % 0x100))
		# Event button. 2 for select
		ae = ae + chr(but % 0x100) + chr((but >> 8) % 0x100) + chr((but >> 16) % 0x100) + chr(((but >> 24) % 0x100))
		# ItemID.  Using passed eventid
		ae = ae + chr(item % 0x100) + chr((item >> 8) % 0x100) + chr((item >> 16) % 0x100) + chr(((item >> 24) % 0x100))
		ae_len = len(ae) + 4
		ae = self.pack_len(ae_len) + ae
		self.client_sock.sendall(ae)

	# 0x4001 (Again - this one is for button events.  Functions will eventually be merged.)
	def send_BUTTONACTION(self, guid, ppg, tpg, button):
		ba = ""
		ba = chr(0x4001 % 0x100) + chr((0x4001 >> 8) % 0x100) + chr((0x4001 >> 16) % 0x100) + chr(((0x4001 >> 24) % 0x100))
		ba = ba + self.pack_num(self.packet_count + 1)
		ba = ba + guid.bytes_le
		scf = uuid.UUID('{A9A5353F-2D4B-47ce-93EE-759F3A7DDA4F}')
		ba = ba + scf.bytes_le
		ba = ba + chr(SCF_EVENT_NAVIGATION % 0x100) + chr((SCF_EVENT_NAVIGATION >> 8) % 0x100) + chr((SCF_EVENT_NAVIGATION >> 16) % 0x100) + chr(((SCF_EVENT_NAVIGATION >> 24) % 0x100))
		ba = ba + chr(12 % 0x100) + chr((12 >> 8) % 0x100) + chr((12 >> 16) % 0x100) + chr(((12 >> 24) % 0x100))
		ba = ba + chr(ppg % 0x100) + chr((ppg >> 8) % 0x100) + chr((ppg >> 16) % 0x100) + chr(((ppg >> 24) % 0x100))
		ba = ba + chr(tpg % 0x100) + chr((tpg >> 8) % 0x100) + chr((tpg >> 16) % 0x100) + chr(((tpg >> 24) % 0x100))
		ba = ba + chr(button % 0x100) + chr((button >> 8) % 0x100) + chr((button >> 16) % 0x100) + chr(((button >> 24) % 0x100))
		ba_len = len(ba) + 4
		ba = self.pack_len(ba_len) + ba
		self.client_sock.sendall(ba)

	# 0x50
	def resp_SETUSERSTATE(self, packet_type, packet_num, packet_data):
		sid_size = struct.unpack('L', packet_data[:4])[0]
		bytepos = 4
		sid = ""
		# This is REALLY dirty.  I can't quite get my head around sending 2 byte unicode
		for uni in range(sid_size * 2):
			bytepos+=1
			if ord(packet_data[4 + uni]) != 0:
				sid = sid + packet_data[4+uni]
		#
		#log.debug(sid)
		
		user_size = struct.unpack('L', packet_data[bytepos:bytepos+4])[0]
		bytepos+=4
		self.user = ""
		# This is REALLY dirty.  I can't quite get my head around sending 2 byte unicode
		for uni in range(bytepos, (bytepos + user_size * 2)):
			bytepos+=1
			if ord(packet_data[uni]) != 0:
				self.user = self.user + packet_data[uni]
		#
		#log.debug(self.user)
		user_state = struct.unpack('L', packet_data[bytepos:bytepos+4])[0]
				
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)

	# 0x100
	def resp_SETCURRENTUSER(self, packet_type, packet_num, packet_data):
		sid_size = struct.unpack('L', packet_data[:4])[0]
		bytepos = 4
		sid = ""
		# This is REALLY dirty.  I can't quite get my head around sending 2 byte unicode
		for uni in range(sid_size * 2):
			bytepos+=1
			if ord(packet_data[4 + uni]) != 0:
				sid = sid + packet_data[4+uni]
		#
		#log.debug(sid)
		self.sid = sid
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)
			
	# 0x101	
	def resp_GETCURRENTUSER(self, packet_type, packet_num, packet_data):
		sid = self.sid
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp = resp + self.pack_len(len(sid))
		#resp = resp + sid
		# This is REALLY dirty.  I can't quite get my head around sending 2 byte unicode
		for uni in range(len(sid)):
				resp = resp + sid[uni]
				resp = resp + chr(0)
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)

	# 0x103
	def resp_GETCAPABILITIES(self, packet_type, packet_num, packet_data):
		guid = uuid.UUID(bytes_le=packet_data[:16])
		if guid == PROPERTYKEY:
			variant = struct.unpack('L', packet_data[-4:])[0]
			log.debug("GETCAPABILITIES: " + str(variant))
		#	log.debug(str(guid) + " : " + str(pid))
		#resp = ""
		#resp = self.pack_type(packet_type)
		#resp = resp + self.pack_num(packet_num)
		
		#resp_len = len(resp) + 4
		#resp = self.pack_len(resp_len) + resp
		#self.client_sock.send(resp)

	# 0x104
	def resp_GETAPPLICATIONORDER(self, packet_type, packet_num, packet_data):
		applications = self.apps_guid
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp = resp + self.pack_len(len(applications))
		for app in applications:
			resp = resp + app.bytes_le
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)

	# 0x105
	def resp_SETAPPLICATIONORDER(self, packet_type, packet_num, packet_data):
		b = 4
		newguid = []
		newname = []
		newicon = []
		newglance = []
		newcontent = []
		newrect = []
		app_count = struct.unpack('L', packet_data[:4])[0]
		for i in range(0,app_count):
			guid = uuid.UUID(bytes_le=packet_data[b:b + 16])
			b = b + 16
			newguid.append(guid)
		for guid in newguid:
			i = self.apps_guid.index(guid)
			newname.append(self.apps_name[i])
			newicon.append(self.apps_icon[i])
			newglance.append(self.apps_glance[i])
			newcontent.append(self.apps_content[i])
			newrect.append(self.apps_rect[i])
		self.apps_guid = newguid
		self.apps_name = newname
		self.apps_icon = newicon
		self.apps_glance = newglance
		self.apps_content = newcontent
		self.apps_rect = newrect
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)
		
	# 0x108
	def resp_SETTIME(self, packet_type, packet_num, packet_data):
		host_time = struct.unpack('Q', packet_data[:8])[0]
		host_time = ( host_time - 0x19DB1DED53E8000 ) / 10000000
		self.time_dif = host_time - time.time()
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)
		
	# 0x109 - Needs handling
	def resp_SETSHORTDATEFORMAT(self, packet_type, packet_num, packet_data):
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)

	# 0x10a - Needs handling
	def resp_SETLONGDATEFORMAT(self, packet_type, packet_num, packet_data):
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)

	# 0x10b - Needs handling
	def resp_SETSHORTTIMEFORMAT(self, packet_type, packet_num, packet_data):
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)
	
	# 0x10d
	def resp_ADDAPPLICATION(self, packet_type, packet_num, packet_data):
		guid = uuid.UUID(bytes_le=packet_data[:16])
		if self.apps_guid.count(guid) == 0:
			ep = uuid.UUID(bytes_le=packet_data[16:32])
			name_size = struct.unpack('L', packet_data[32:36])[0]
			name_size=name_size*2
			app_name=packet_data[36:36+name_size]
			#log.debug(app_name)
			bp = 36+name_size+8
			lg_icon_size = struct.unpack('L', packet_data[bp:bp+4])[0]
			bp = bp+4
			lg_icon = packet_data[bp:bp+lg_icon_size]
			# We'll ignore the rest of the data for now.
			self.apps_guid.append(guid)
			self.apps_name.append(app_name)
			self.apps_icon.append(lg_icon)
			self.apps_glance.append("Waiting for data...")
			self.apps_content.append(None)
			self.apps_rect.append(None)

		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)
		
		self.REDRAW = True
		
	# 0x10e
	def resp_DELETEAPPLICATION(self, packet_type, packet_num, packet_data):
		guid = uuid.UUID(bytes_le=packet_data)
		#log.debug(str(guid))
		try:
			i = self.apps_guid.index(guid)
			del self.apps_guid[i]
			del self.apps_name[i]
			del self.apps_icon[i]
			del self.apps_glance[i]
			del self.apps_content[i]
			del self.apps_rect[i]
		except ValueError:
			#log.debug("Application not found")		
			pass
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)
		
		self.REDRAW = True
		
	# 0x114
	def resp_ADDCONTENTITEM(self, packet_type, packet_num, packet_data):
		guid = uuid.UUID(bytes_le=packet_data[:16])
		ep = uuid.UUID(bytes_le=packet_data[16:32])
		cont_id = struct.unpack('L', packet_data[32:36])[0]
		cont_sz = struct.unpack('L', packet_data[36:40])[0]
		cont = packet_data[-cont_sz:]
		if cont_id == 0:
			try:
				i = self.apps_guid.index(guid)
				self.apps_glance[i] = cont.strip(chr(0))
				#log.debug(cont.strip(chr(0)))
				self.REDRAW = True
				#log.debug(cont.strip(chr(0)))
			except:
				#log.debug("Got data for unknown application")
				#log.debug(str(guid))
				pass

		self.addContent(guid, cont_id, cont)

		if guid == self.current_guid:
			if cont_id == self.current_cid:
				####log.debug("Content for current cid")
				####self.selected_menu = None
				####self.current_guid = None
				####self.current_cid = None
				####self.showContent(guid, cont_id)
				self.upd_GUID = guid
				self.upd_CID = cont_id
		
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)
		
	# 0x115
	def resp_DELETECONTENTITEM(self, packet_type, packet_num, packet_data):
		guid = uuid.UUID(bytes_le=packet_data[:16])
		ep = uuid.UUID(bytes_le=packet_data[16:32])
		cont_id = struct.unpack('L', packet_data[32:36])[0]
		
		#try:
		#	i = self.apps_guid.index(guid)
		#	content = self.apps_content[i]
		#	content[cont_id] = None
		#	self.apps_content[i] = content
		#except:
		#	pass

		self.delContent(guid, cont_id)

		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)
		
		self.REDRAW = True
		
	# 0x116
	def resp_DELETEALLCONTENTITEMS(self, packet_type, packet_num, packet_data):
		guid = uuid.UUID(bytes_le=packet_data[:16])
		ep = uuid.UUID(bytes_le=packet_data[16:32])
		
		try:
			i = self.apps_guid.index(guid)
			self.apps_glance[i] = "Waiting for data..."
			self.apps_content[i] = None
		except:
			#log.debug("Asked to remove all data for unknown application")
			#log.debug(str(guid))
			pass
				
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)
		
		self.REDRAW = True
		
	# 0x117
	def resp_GETSUPPORTEDENDPOINTS(self, packet_type, packet_num, packet_data):
		scf = uuid.UUID('{A9A5353F-2D4B-47ce-93EE-759F3A7DDA4F}') #scf
		ical = uuid.UUID('{4DFF36B5-9DDE-4F76-9A2A-96435047063D}') #ical
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp = resp + self.pack_len(1)
		resp = resp + scf.bytes_le
		#resp = resp + ical.bytes_le
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)
		
	# 0x118
	def resp_SETTIMEZONE(self, packet_type, packet_num, packet_data):
		self.time_bias = struct.unpack('l', packet_data[:4])[0]
		self.time_bias = self.time_bias - struct.unpack('l', packet_data[-4:])[0]
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)
	
	# 0x502
	def resp_SYNC(self, packet_type, packet_num, packet_data):
		resp = ""
		resp = self.pack_type(packet_type)
		resp = resp + self.pack_num(packet_num)
		resp = resp + packet_data
		resp_len = len(resp) + 4
		resp = self.pack_len(resp_len) + resp
		self.client_sock.sendall(resp)
		
	def pack_type(self, packet_type):
		resp = ""
		resp = chr(packet_type % 0x100) + chr((packet_type >> 8) % 0x100) + chr((packet_type >> 16) % 0x100) + chr(((packet_type >> 24) % 0x100) | 128)
		return resp
		
	def pack_num(self, packet_num):
		resp = ""
		resp = chr(packet_num % 0x100) + chr(packet_num / 256)
		return resp
		
	def pack_len(self, pack_len):
		resp = ""
		resp = chr(pack_len % 0x100) + chr((pack_len >> 8) % 0x100) + chr((pack_len >> 16) % 0x100) + chr((pack_len >> 24) % 0x100)
		return resp
		
	def readConfig(self):
		self.config = ConfigParser.ConfigParser()
		self.config.read("/etc/msideshow.conf")
		try:
			self.last_mac = self.config.get("bluetooth", "last_mac")
		except:
			self.last_mac = ""
		try:
			self.page_swap = int(self.config.get("ui", "page_swap"))
		except:
			self.page_swap = 10
	
	def writeConfig(self):
		try:
			self.config.set("bluetooth", "last_mac", self.last_mac)
		except ConfigParser.NoSectionError:
			self.config.add_section("bluetooth")
			self.config.set("bluetooth", "last_mac", self.last_mac)
		try:
			self.config.set("ui", "page_swap", str(self.page_swap))
		except ConfigParser.NoSectionError:
			self.config.add_section("ui")
			self.config.set("ui", "page_swap", str(self.page_swap))
		configfile = open('/etc/msideshow.conf', 'wb')
		self.config.write(configfile)

	def listenerThread(self):
		last_packet = time.time()
		while self.CONNECTED:
			time.sleep(0.01)
			if (time.time() - last_packet) >= 30:
				self.newMsg("Checking connection", time.time())
				self.send_PING()
				last_packet = time.time()

			try:
				self.data = self.data + self.client_sock.recv(32768)
			except:
				self.data = self.data
			if len(self.data) != 0:
				last_packet = time.time()
				if PLATFORM == "n800":
					device.display_state_on()
					device.display_blanking_pause()
				self.listener()
				#self.drawFront()
				
app = SideShowApp()
app.run()
