#!/usr/bin/python
# x11_server.py is the server (linux) part of RusticVNC
# (C) 2007 Michele Andreoli, GPL

"""
========================================================
vnc_server.py create (and advertise) a
bluetooth service called VNC, on the linux box.

Using the client part, vnc_client.py, a Symbian S60 phone 
can connect to this service ed requires mouse mouvements,
sound control, shell commands, periodic screenshots, etc.

Requimentes: pyBluez (bluetooth for Python), stream.py, python-xlib
========================================================

"""

from version import VERSION

import traceback,sys,os,time

# some required external modules is in the dir ./ext

for p in ('.', './ext', '/usr/local/vnc60/ext'):
	if os.path.isdir(p):
		sys.path.append(p)

try:
	from Xlib import X, display 
	from Xlib.protocol import request
	display = display.Display()
	screen=display.screen()
	root=screen.root
	window=root
except:
	print "withou python-Xlib, mouse will works!"
	root=window=display=0
	X='boh?'

import traceback

try:
	from Xlib.ext.xtest import FakeInput
except:
	FakeInput=lambda *args: "fakeinput unsupported %s" % args[0]
	print "Xlib.ext.xtest missing: the SELECT button will not works"

try:
	from stream import Stream
except:
	print "stream.py module is required. Abort."
	
#-------------------
# amarok commands
#-------------------

playing='dcop amarok player nowPlaying' 
vol='dcop amarok player getVolume' 

amarok={
'PLAY':"dcop amarok player playPause; %s"%playing,
'PREVIOUS':"dcop amarok player prev; %s"%playing,
'NEXT':"dcop amarok player next; %s"%playing,
'STOP':"dcop amarok player prev; %s"%playing,
'VOLUME-UP':"dcop amarok player volumeUp; %s"%vol,
'VOLUME-DOWN':"dcop amarok player volumeDown; %s"%vol,
} 

#-------------------------
# execute a linux command, returning  the stdout
#-------------------------

def execute(cmd):
	f=os.popen(cmd,'r')
	r=f.read()
	f.close()
	if len(r)<=1: r='ok\n'
	return r.strip() 

#--------------------
# get the absolute pointer coordinate (x,y)
#--------------------

def get_pointer():
	info = request.QueryPointer(display = display.display, window = root)
        x=info._data['root_x'];
        y=info._data['root_y']
        print "pointer x=%d y=%d" %(x,y)
	return (x,y)

#--------------------------------
# send fake input to XWindow
#--------------------------------

def x11_input(pos,cmd=X.ButtonPress):
	(x,y)=pos
	FakeInput(display = display.display,
              opcode = display.display.get_extension_major('XTEST'),
              event_type = cmd,
              detail = X.Button1,
              time = X.CurrentTime,
              root = root,
              x = x,
              y =y
	      )

#--------------------------------
# check requirements on the linux box 
#--------------------------------

check_list={
'ImageMagick not found (suggested)':'r=`which import 2>/dev/null`; [ "$r" ]',
'xhost not foun (required)':'r=`which xhost 2>/dev/null`; [ "$r" ]',
'dcop not found (required)':'r=`which dcop 2>/dev/null`; [ "$r" ]',
'amarok not found (suggested)':'r=`which amarok 2>/dev/null`; [ "$r" ]',
'uname not found (suggested)':'r=`which uname 2>/dev/null`; [ "$r" ]',
'XWindows is not running (strongly required)':' [ "$DISPLAY" ]',
}

def check_requirements():
	print "Checking requiments ..."
	for k in check_list.keys():	
		r=os.system(check_list[k])
		if r>0:
			print "\tAttention,please: %s" % k

#==============================
# MAIN
#=============================

print '='*40 
print "vnc_server.py for Linux v%s" % VERSION
print '='*40 
check_requirements()

image={'x11':"/tmp/x11.jpg", 'phone':"/tmp/phone.jpg"}
image={'x11':"/tmp/x11.jpg", 'phone':"/srv/www/htdocs/reserved/n70/webcam.jpg"}

os.system("xhost +localhost")

def main():
    global conn
    conn=Stream(mode='BT');
    conn.accept(service='VNC')
    print "Connection enstablished with the phone"
    while 1:
	data=None
	data=conn.read()
	if data==None: continue
	if len(data)!=0:
		#print "received [%s]" % data
		pass
        if data=="END":
		print "client finished"
		break
        if data=="PING":
		print "PING received"
	#---------------
	# amarok control
	#----------------
        if data=='PLAY':
		r=execute(amarok['PLAY'])
		conn.write(r)
        if data=='NEXT':
		r=execute(amarok['NEXT'])
		conn.write(r)
        if data=='PREVIOUS':
		r=execute(amarok['PREVIOUS'])
		conn.write(r)
        if data=='STOP':
		r=execute(amarok['STOP'])
		conn.write(r)
        if data=='VOLUME-UP':
		r=execute(amarok['VOLUME-UP'])
		conn.write(r)
        if data=='VOLUME-DOWN':
		r=execute(amarok['VOLUME-DOWN'])
		conn.write(r)
	#------------------------------------------
	# shell commands request. Protocol: CMD,cmd 
	#------------------------------------------
	if data[:4]=="CMD,":
		(op,cmd)=data.split(',')
		# execute linux commands and return stdout 
		result=execute(cmd)
		print "command %s -> result [%s]" %(cmd,result)
		conn.write(result)
	#------------------------------------------------------
	# X11->Phone screen request. Protocol: GET_SCREEN,width,height,rotation 
	#-------------------------------------------------------
	if data[:11]=="GET_SCREEN,":
		# read resolution, etc
		(op,w,h,rot)=data.split(',')
		print "screenshot required %sx%s, rot=%s .." %(w,h,rot)
		g='800x600'
		cmd="import -silent -window root -depth 8 -geometry %s \
		-rotate %s -resize %sx%s %s" %(g,rot,w,h,image['x11'])
		os.system(cmd)
		print "sendind X11 screenshot [%s] ..." % image['x11']
		conn.sendfile(image['x11'])
		print "screen shot sent."
		continue
        #------------------------------------------------------
        # Phone->X11 screen request. Protocol: SEND_SCREEN
        #-------------------------------------------------------
	# currently disabled in vnc_client.py, because not useful
        if data[:11]=="SEND_SCREEN":
                print "screenshot from phone incoming ..." 
                conn.recfile(image['phone'])
                print "screenshot received [%s]" % image['phone']
                continue

	#------------------------------------
	# Mouse motion commands 
	#------------------------------------
        if data=="UP":
  	    print "UP"
            display.warp_pointer(0,-3)
            display.sync()
        if data=="LEFT":
  	    print "LEFT"
            display.warp_pointer(-3,0)
            display.sync()
        if data=="RIGHT":
  	    print "RIGHT"
            display.warp_pointer(3,0)
            display.sync()
        if data=="DOWN":
  	    print "DOWN"
            display.warp_pointer(0,3)
            display.sync()
        if data=="SELECT":
	    position=get_pointer()
  	    print "SELECT %s" % str(position)
	    x11_input(position,X.ButtonPress)
	    time.sleep(0.1)
	    x11_input(position,X.ButtonRelease)
            display.sync()

    conn.close()
    conn.shutdown()

if __name__=='__main__':
	stop=False
	while not stop :
		try:
			main()
		except KeyboardInterrupt:
			print "control-C received"
			stop=True
    			conn.close()
    			conn.shutdown()
		except:
    			conn.close()
    			conn.shutdown()
			pass

# End
