#!/usr/bin/env python

"""
v 5.10

gAnyRemote
GTK-based GUI for anyRemote - a bluetooth remote for your PC.

Copyright (C) 2007,2008,2009 Mikhail Fedotov <anyremote@mail.ru>

This program 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 2 of the License, or
(at your option) any later version.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
"""

import locale
import gettext
import getopt
import gobject
import os
import re
import pango
import pygtk
import signal
import socket
import sys
import threading
import thread
import time
import httplib
import Queue

signal.signal(signal.SIGINT, signal.SIG_DFL)
pygtk.require('2.0')

#Translation stuff

#Get the local directory since we are not installing anything
dirpath = os.path.dirname(sys.argv[0])
local_path = os.path.realpath(os.path.join(dirpath,'mo'))

# try ../share/locale/ (Linux)
if not os.path.exists(local_path):
    local_path = os.path.realpath(os.path.join(dirpath,'../share/locale/'))

# try ../lib/locale/ (Sun)
if not os.path.exists(local_path):
    local_path = os.path.realpath(os.path.join(dirpath,'../lib/locale/'))

# last resort ... try /usr/share/locale
if not os.path.exists(local_path):
    local_path = os.path.realpath('/usr/share/locale/')

langs = []

lc = ''
encoding = ''
try:
    lc, encoding = locale.getdefaultlocale()
except ValueError, cmd:
   print 'Error: ',cmd,'\nCorrect $LANG or $LANGUAGE first !!!'
   quit()

if lc:
    #If we have a default, it's the first in the list
    langs = [lc]

# Now lets get all of the supported languages on the system
language = os.environ.get('LANGUAGE', None)
if language:
    langs += language.split(":")

APP_NAME = "ganyremote"

gettext.bindtextdomain(APP_NAME, local_path)
gettext.textdomain(APP_NAME)

# Get the language to use
lang = gettext.translation(APP_NAME, local_path, languages=langs, fallback = True)

_ = lang.gettext

#
# String constants (not all!)
#
AR_NOTINSTALLED = _('Not installed')

AR_NOINFO   = _('No information')
AR_AVAIL    = _('Available')
AR_NOTAVAIL = _('Not available')
AR_MANAGED  = _('Managed')
AR_RUNNING  = _('Running')

AR_CONN_DEV = _('Connecting to device')
AR_WAIT_OPS = _('Wait other operations to finish')
AR_SEL_DIR  = _('Directory selection')

AR_OK       = _('OK')
AR_CANCEL   = _('Cancel')
AR_ADD      = _('Add')
AR_DELETE   = _('Delete')
AR_CHOOSE   = _('Choose')
AR_ALL      = _('All')
AR_FILE     = _('File')
AR_CLOSE    = _('Close')

AR_MODE     = _('Mode')
AR_STATUS   = _('Status')
AR_APP      = _('Application')
AR_CUSTOM   = _('Custom')
AR_EXAMPLE  = _('Example')

AR_STOPPED  = _('anyRemote stopped')
AR_DISCONN  = _('Disconnected from phone')
AR_CONNECT  = _('Connected to phone')
AR_CONNECT2 = _('Connected')

try:
   import gtk
except ImportError:
   print _('Install PyGTK first !!!')
   quit()

pybluez = True 
try:
    import bluetooth
except ImportError:
   pybluez = False

##################################################################################
#
# Java client uploader
#
##################################################################################
class JCUploader(threading.Thread):

    def __init__(self):
	threading.Thread.__init__(self) 

    def run(self):
        global debug,jup
	
        if debug: print 'JCUploader starting'
    
	self.run = True
	
        stopPBar()
        startPBar(_('Downloading')+' anyRemote-16.jad',30)
         
	ret = True
 
        if self.run:         ret = uploadJavaWebGui("anyRemote-16.jad", True)
	if self.run and ret: ret = uploadJavaWebGui("anyRemote-16.jar")
	
        if self.run and ret: ret = uploadJavaWebGui("anyRemote-16b.jad", True)
        if self.run and ret: ret = uploadJavaWebGui("anyRemote-16b.jar")
	
        if self.run and ret: ret = uploadJavaWebGui("anyRemote-32.jad", True)
        if self.run and ret: ret = uploadJavaWebGui("anyRemote-32.jar")
	
        if self.run and ret: ret = uploadJavaWebGui("anyRemote-32b.jad", True)
        if self.run and ret: ret = uploadJavaWebGui("anyRemote-32b.jar")

        if self.run and ret: ret = uploadJavaWebGui("anyRemote-48.jad", True)
        if self.run and ret: ret = uploadJavaWebGui("anyRemote-48.jar")
	
        if self.run and ret: ret = uploadJavaWebGui("anyRemote-48b.jad", True)
        if self.run and ret: ret = uploadJavaWebGui("anyRemote-48b.jar")
	
        if self.run and ret: ret = uploadJavaWebGui("anyRemote-64.jad", True)
        if self.run and ret: ret = uploadJavaWebGui("anyRemote-64.jar")

        if self.run and ret: ret = uploadJavaWebGui("anyRemote-64b.jad", True)
        if self.run and ret: ret = uploadJavaWebGui("anyRemote-64b.jar")

        if self.run and ret: ret = uploadJavaWebGui("anyRemote.jad", True)
        if self.run and ret: ret = uploadJavaWebGui("anyRemote.jar")
	
        if self.run and ret: ret = uploadJavaWebGui("anyRemote-nojsr82.jad", True)
        if self.run and ret: ret = uploadJavaWebGui("anyRemote-nojsr82.jar")
    
        if self.run: stopPBar()
	
	if debug: print 'JCUploader: upload done'
	
	jup = None

    def stop(self):
        global debug
        if debug: print 'stop JCUploader'
	
	self.run = False

def stopJCUploader():
    global jup
    try:
        if jup != None:
            jup.stop()
    except NameError:
        pass

##################################################################################
#
# Java client verifier
#
##################################################################################
class JCVerifier(threading.Thread):

    def __init__(self, force):
	threading.Thread.__init__(self) 
	self.anyway = force

    def run(self):
        global debug
	
        if debug: print 'JCVerifier starting'
	
	curdate = time.strftime("%d%m", time.gmtime())
	
	if self.anyway:
            startPBar(_('Checking java client updates'),30)
	else:
	    try:
	        f = open(os.environ.get("HOME")+os.sep+'.anyRemote'+os.sep+'javaclient.checked', 'r')
	        date = f.read() 
	        f.close()	
	        date = date.replace('\n','')
	    	
                if debug: print 'JCVerifier',date,curdate
	    
	        if date == curdate:
	            if debug: print 'JCVerifier: already checked. Exiting'
		    self = None
		    return

	    except IOError:
	        pass
	    
        if debug: print 'JCVerifier: check new version'

	os.system('echo \"'+curdate+'\" > $HOME/.anyRemote/javaclient.checked')
	newver = checkJavaClientUpdate();
	
	if debug: print 'JCVerifier: upload done '+newver
	
	if self.anyway: stopPBar()
	
	if newver == "":
	    if self.anyway: infoMessage(_("No updates for java client were found."))
	else:
	    putToMainQueue(['UPDATE_AVAIL'])
	
	self = None
       
##################################################################################
#
# BT communication thread
#
##################################################################################

# Beware:
# Can not run more than one command on BT adapter at once, since it could hungs 

class BtComm(threading.Thread):

    def __init__(self, jDir):
	threading.Thread.__init__(self) 
	self.midletDir = jDir

    def run(self):
        global debug, bt_devices, cmd_array
	
	self.keepRun = True
	
	if debug:
	    print 'BtComm: run'
	
	while self.keepRun:
	
	    ctype = ''
	    cdata = ''
            gtk.gdk.threads_enter()
	    try:
                item = cmd_array[0]
	        del cmd_array[0] 
	        ctype = item[0]
	        cdata = item[1]
 	    except NameError:
	        pass
 	    except TypeError:
	        pass
	    except IndexError:
	        pass
            gtk.gdk.threads_leave()
	    
	    if debug and ctype != '':
	        print 'BtComm: (#',len(cmd_array),') got command',ctype,cdata
	 
	    if ctype == 'scan':
	        self.doScan(cdata)
	    elif ctype == 'ping':
	        self.doPing(cdata)
	    elif ctype.startswith('pushjar'):
	        self.doPush(cdata,ctype[7:],False)
	    elif ctype.startswith('pushjad'):
	        self.doPush(cdata,ctype[7:],True)
	    elif ctype == 'info':
	        self.doInfo(cdata)
	    elif ctype == 'test_at':
	        self.doAT(cdata)
	    else:
	        time.sleep(3)
		
    def setStatus(self, address, status):
        global debug, bt_devices
        
	if debug: print 'set for',address,status

        gtk.gdk.threads_enter()
        treeiter = bt_devices.get_iter_first()
        gtk.gdk.threads_leave()

        while treeiter != None:
            gtk.gdk.threads_enter()
            addr = bt_devices.get_value(treeiter, 0)
            gtk.gdk.threads_leave()
    	
            if address == addr:
                gtk.gdk.threads_enter()
                if status != bt_devices.get_value(treeiter, 4):
		
	       	    bt_devices.set_value(treeiter,4,status)
		     		
		needRun = bt_devices.get_value(treeiter,3)  
                gtk.gdk.threads_leave()
		
		if status == AR_AVAIL and needRun != '':
		    if debug: 
		        print 'run anyRemote with',needRun
		    startAnyRemote(needRun, False)
		
    	        return
    	
    	    gtk.gdk.threads_enter()
    	    treeiter = bt_devices.iter_next(treeiter)
    	    gtk.gdk.threads_leave()

    def doScan(self,force):
	global debug
	if debug: print 'BtComm: scan devices'
		    
	timer = 0
	existing = getDevSet()
	
	# Search new devices
	nearby_devices = []
	try:
	    nearby_devices = bluetooth.discover_devices(lookup_names = True)
	except bluetooth.BluetoothError,msg:
	    if debug: print "BtComm: BluetoothError",msg
	    
	    # sleep additional 5 sec
	    t2 = 0
	    while self.keepRun and t2 < 5:
	    	time.sleep(0.1)
		t2 = t2 + 0.1
	
	if debug: print "BtComm: found %d devices" % len(nearby_devices)

	availSet = getAvailableSet()
	
	for addr,name in nearby_devices:
	    if debug:
		print "  %s - %s" % (addr, name)
	    
	    if addr not in existing:
	        showDetailsWin(addr, name, name, '', True)
	    else:
		if addr in availSet:
		    availSet.remove(addr)
		else:
		    self.setStatus(addr,AR_AVAIL)
	    
	for rest in availSet:
	    self.setStatus(rest, '')
	
	if debug: print 'BtComm: verify done'
	
	if force == 'T':
	    stopPBar()

    def doPing(self, data):
	global debug
	if debug: print 'BtComm: ping device'
	
	putToDevWQueue(['SET_STATUS',''])
	writePBar(AR_CONN_DEV)
	
	os.system('killall -9 hcitool')
	if debug: print 'hcitool name '+data
	ret = getResult('hcitool name '+data,'browser')
	
	stopPBar()
	if (ret == ''):
	    putToDevWQueue(['SET_STATUS',_('Ping failed !')])
	else:
	    putToDevWQueue(['SET_STATUS',_('Ping OK !')])

    def doPush(self, data, size, usejad):
	global debug
	if debug: print 'BtComm: obex push ',data,size,usejad
	
	putToDevWQueue(['SET_STATUS',''])
	stopPBar()    
	if not os.path.exists(self.midletDir):        
	    putToDevWQueue(['SET_STATUS',_('Can not find anyremote-J2ME-client installation !')])
	    return
	
	dash = '-'
	if size == '':
	    dash = ''
	midlet = 'anyRemote' + dash + size + '.jar'
	path = self.midletDir + os.sep + midlet
	if not os.path.isfile(path):
	    putToDevWQueue(['SET_STATUS',_('Can not find java midlet ('+midlet+_(') to upload !'))])
	    return
	
	sender = ''    
	if (isInstalled('gnome-obex-send') == 'OK'):
	    sender = 'gnome-obex-send -d '
	elif (isInstalled('bluetooth-sendto') == 'OK'):
	    sender = 'bluetooth-sendto --dest='
	elif (isInstalled('kbtobexclient') == 'OK'):
	    sender = 'kbtobexclient'
	else:
	    putToDevWQueue(['SET_STATUS',_('None of gnome-obex-send, bluetooth-sendto and kbtobexclient are installed !')])
	    return

	ret = getResult(sender+data+' '+path+' &','browser')
	
	if usejad:
	    jad = 'anyRemote' + dash + size + '.jad'
	    path = self.midletDir + os.sep + jad
	    if not os.path.isfile(path):
	        putToDevWQueue(['SET_STATUS',_('Can not find JAD file ('+jad+_(') to upload !'))])
	        return
	
	    ret = getResult(sender+data+' '+path+' &','browser')
	
    def doInfo(self,data):
	global debug
	if debug: print 'BtComm: get info'

	writePBar(AR_CONN_DEV)
	
	services = bluetooth.find_service(address=data)

	if len(services) > 0:
            print "found %d services on %s" % (len(services), data)
            print
	else:
            print "no services found"

	for svc in services:
	    print "Service Name: %s"    % svc["name"]
	    print "    Host:        %s" % svc["host"]
	    print "    Description: %s" % svc["description"]
	    print "    Provided By: %s" % svc["provider"]
	    print "    Protocol:    %s" % svc["protocol"]
	    print "    channel/PSM: %s" % svc["port"]
	    print "    svc classes: %s "% svc["service-classes"]
	    print "    profiles:    %s "% svc["profiles"]
	    print "    service id:  %s "% svc["service-id"]
	    print

    def getSerialPort(self,addr):
	services = bluetooth.find_service(address=addr)
	for svc in services:
	    print svc
	    try:
	        if svc["name"] == 'Serial Port' or svc["name"].startswith('COM ') or svc["name"].startswith('Dial-up'):
	            return svc["port"]
            except AttributeError, NameError:
    	        pass
	return None
	
    def send_at(self,sock,cmd):
	if len(cmd) == 0: 
	    return ''
	
	data = cmd+'\r'
	print "send",cmd
	
	sock.send(cmd+'\r')
	time.sleep(0.5)
	data = sock.recv(1024)

	print "got",data
	return data

    def doAT(self,data):
        global debug
	if debug: print 'BtComm: doAT'
	
	putToDevWQueue(['SET_STATUS',''])
	writePBar(AR_CONN_DEV)	
	
    	port = self.getSerialPort(data)
	if debug: print 'BtComm: port',port
        
	if port == None:
	    putToDevWQueue(['SET_STATUS',_('Can not get port to connect to. Is there any device available ?')])
	else:
	    
	    sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
	    try:
	        sock.connect((data, port))
 	    except bluetooth.BluetoothError,msg:
		d = str(msg)
		if debug: print d
		
		stopPBar()
	        if d.startswith('(111,'):
	            putToDevWQueue(['SET_STATUS',_('Connection refused')])
	        return

  	    ret = self.send_at(sock,"ATZ")
  	    ret = self.send_at(sock,"ATE0")
  	    ret = self.send_at(sock,"AT+CMER=?")
	    
	    status = '' 
	    if ret.find('ERROR') == -1:
	        ret = ret[ret.index('+CMER'):]
	        ret = (ret.split('\n'))[0]
	    
	        AT_CMER=ret.replace(' ','').replace('\r','')
	    
	        #+CMER: (0,3),(0),(0),(0,1,2),(0)	<- bad
		#+CMER: (0,3),(0,1,2),(0),(0,1,2),(0)	<- OK
		s1 = (AT_CMER.split('('))[2]
		s2 = (s1.split(')'))[0]
		
		status = AT_CMER
		if s2 == '0':
		    status = _('AT mode is not supported by phone (')+status+')'
		else:
		    status = _('AT mode could be supported by phone (')+status+')'
	    else:
	    	status = _('AT mode is not supported by phone (ERROR response)')
		
	    putToDevWQueue(['SET_STATUS',status])
            sock.close()

	stopPBar()
   
    def stop(self):
        global debug
	if debug: print 'BtComm stop'
	self.keepRun = False

##################################################################################
#
# DeviceDetail window
#
##################################################################################

class DeviceDetail(gtk.Window):

    def __init__(self, ba, m, n, act, is_new, jDir):
        global debug 
	
	gtk.Window.__init__(self)
	
	self.model     = m.replace('\n','')
	self.dname     = n.replace('\n','')
	self.btAddress = ba
	self.cfile     = act
	self.isNew     = is_new
	self.midletDir = jDir
	
        self.initWindow() 

    def initWindow(self):
        global debug
	
        self.connect("destroy", self.close)
	
	capt = _('Device Parameters')
	if self.isNew:
	    capt = _('New device')
	    
        self.set_title(capt)
	
        vbox = gtk.VBox(False, 0)
        self.add(vbox)

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	
        label = gtk.Label('')
        hbox.pack_start(label, 0, True, 0)

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	
	label = gtk.Label('  '+_('Device Name')+': '+self.model+'       ')
        hbox.pack_start(label, 0, True, 0)

        label = gtk.Label(_('BT Address')+': '+self.btAddress+'         ')
        hbox.pack_end(label, 0, True, 0)
	
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	    
        label = gtk.Label('')
        hbox.pack_start(label, 0, True, 0)

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        label = gtk.Label(_('Specify Name')+': ')
        hbox.pack_start(label, 0, True, 0)

        self.pname = gtk.Entry()
        self.pname.set_max_length(64)
        hbox.pack_start(self.pname, True, True, 0)
	self.pname.set_text(self.dname)
		
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	
        label = gtk.Label('')
        hbox.pack_start(label, 0, True, 0)

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

	self.run_when = gtk.CheckButton(_('Run anyRemote when discovered'), False)
        hbox.pack_start(self.run_when, 0, True, 0)
	self.run_when.set_active((self.cfile != '')) 
	self.run_when.connect('toggled', self.doWhen)
	
	tts = gtk.Tooltips()
	tts.set_tip(self.run_when,_('anyRemote will start only if no other instances of anyRemote are running'))
	
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        self.cfgFile = gtk.Entry()
        self.cfgFile.set_max_length(64)
        hbox.pack_start(self.cfgFile, True, True, 0)
	self.cfgFile.set_text(self.cfile)
	self.cfgFile.set_editable(False)
	self.cfgFile.set_sensitive((self.cfile != ''))
	self.cfgFile.set_position(len(self.cfile))
	
        self.choose = gtk.Button(label=AR_CHOOSE)
        self.choose.connect("clicked", self.chooseAction)
        hbox.pack_end(self.choose, False, True, 0)
	self.choose.set_sensitive((self.cfile != ''))

	################
	self.sBar = gtk.Statusbar()
	vbox.add(self.sBar)
	vbox.set_child_packing(self.sBar, 0, 1, 0, gtk.PACK_END)
	self.cid = self.sBar.get_context_id('a')
	self.sBar.show()

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        label = gtk.Label('')
        hbox.pack_start(label, 0, True, 0)

        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()

	################
        hbox = gtk.HBox(False, 4)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
                                                             
        vbox1 = gtk.VBox(False, 0)
        hbox.add(vbox1)

        vbox2 = gtk.VBox(False, 0)
        hbox.add(vbox2)

        hbox1 = gtk.HBox(False, 4)
        vbox1.add(hbox1)
	vbox1.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        hbox2 = gtk.HBox(False, 4)
        vbox2.add(hbox2)
	vbox2.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        self.btnUp = gtk.Button(label=_('Upload Java'))
        self.btnUp.connect("clicked", self.upload)
        hbox1.pack_start(self.btnUp, False, True, 0)
	
	label = gtk.Label(_(' with icon set '))
        hbox1.pack_start(label, 0, True, 0)
	
	dummy = gtk.Label('')
        vbox1.pack_start(dummy, 0, True, 0)

	self.sz16 = gtk.RadioButton(None,'16x16', False)
	self.sz16.set_active(True)
        hbox2.pack_start(self.sz16, 0, True, 0)
	self.sz32 = gtk.RadioButton(self.sz16,'32x32', False)
        hbox2.pack_start(self.sz32, 0, True, 0)
	self.sz48 = gtk.RadioButton(self.sz16,'48x48', False)
        hbox2.pack_start(self.sz48, 0, True, 0)
	self.sz64 = gtk.RadioButton(self.sz16,'64x64', False)
        hbox2.pack_start(self.sz64, 0, True, 0)
	
	self.szAll = gtk.RadioButton(self.sz16,_('with all icon sets'), False)
        vbox2.pack_start(self.szAll, 0, True, 0)

	self.sz32.set_active(True)
        self.szAll.connect("clicked", self.clicked_szAll)

	################
        hbox = gtk.HBox(False, 4)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	
	
	self.uplJad = gtk.CheckButton(_('Also upload JAD'), False)
	self.uplJad.set_active(False)
        hbox.pack_start(self.uplJad, 0, True, 0)
	
 	tj = gtk.Tooltips()
	tj.set_tip(self.uplJad,_('Can be useful for Samsung phones'))

	self.bigTitleIcon = gtk.CheckButton(_('use big title icon'), False)
        hbox.pack_start(self.bigTitleIcon, 0, True, 0)
        self.bigTitleIcon.connect("clicked", self.clicked_bti)
	ts = gtk.Tooltips()
	ts.set_tip(self.bigTitleIcon,_('16x16 and 64x64 title icons are available'))

	################
        hbox = gtk.HBox(False, 4)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

	self.noJsr82 = gtk.CheckButton(_('use version without JSR-82'), False)
        hbox.pack_start(self.noJsr82, 0, True, 0)
        self.noJsr82.connect("clicked", self.clicked_nojsr82)
	ts = gtk.Tooltips()
	ts.set_tip(self.noJsr82,_('Can be used on WinMobile devices'))
	
	if not os.path.isdir(self.midletDir): 
	    self.btnUp.set_sensitive(False)
	    self.bigTitleIcon.set_sensitive(False)
	    self.sz16.set_sensitive(False)
	    self.sz32.set_sensitive(False)
	    self.sz48.set_sensitive(False)
	    self.sz64.set_sensitive(False)
	    tj = gtk.Tooltips()
	    tj.set_tip(self.btnUp,_('It needs to install anyremote-J2ME-client package first'))
	
	################
        hbox = gtk.HBox(False, 4)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_END)

        self.btnPing = gtk.Button(label=_('Ping'))
        self.btnPing.connect("clicked", self.ping)
        hbox.pack_start(self.btnPing, False, True, 0)

        self.btnAT = gtk.Button(label=_('Test AT'))
        self.btnAT.connect("clicked", self.test_at)
        hbox.pack_start(self.btnAT, False, True, 0)

        btn = gtk.Button(label=AR_OK)
	addIconToButton(btn,gtk.STOCK_OK)
        btn.connect("clicked", self.ok)
        hbox.pack_end(btn, False, True, 0)
	
        btn = gtk.Button(label=AR_CLOSE)
	addIconToButton(btn,gtk.STOCK_CLOSE)
        btn.connect("clicked", self.close)
        hbox.pack_end(btn, False, True, 0)
 
 
 	bt = btVerify(False)
	if bt == 'NOK':
	    if debug: print 'DeviceDetail: Bluetooth not active'

            self.btnPing.set_sensitive(False)
            self.btnAT.set_sensitive(False)
	    self.btnUp.set_sensitive(False)
	    
	    tj = gtk.Tooltips()
	    tj.set_tip(self.btnPing,_('Bluetooth service is not active'))
	    tj.set_tip(self.btnAT,_('Bluetooth service is not active'))

	self.set_size_request(530,320)
	self.show_all()
	
	self.isShown = True
	
	self.ddQueueTimer = gobject.timeout_add(300, self.checkQueue)

    def ok(self,w):
    	global bt_devices
	
	gtk.gdk.threads_enter()
	treeiter = bt_devices.get_iter_first()
	gtk.gdk.threads_leave()
	    
	while treeiter != None:
	    gtk.gdk.threads_enter()
	    addr = bt_devices.get_value(treeiter, 0)
	    gtk.gdk.threads_leave()
	    
	    if self.btAddress == addr:
	        gtk.gdk.threads_enter()
	    	if self.pname.get_text() != bt_devices.get_value(treeiter, 2):
	            bt_devices.set_value(treeiter,2,self.pname.get_text())
		    
	    	if self.model != bt_devices.get_value(treeiter, 1):
	            bt_devices.set_value(treeiter,1,self.model)

		cf = self.cfgFile.get_text()
	    	if cf != bt_devices.get_value(treeiter, 3):
	            bt_devices.set_value(treeiter,3,cf)
		gtk.gdk.threads_leave()
		
		self.close(w)
		return
	    
	    gtk.gdk.threads_enter()
	    treeiter = bt_devices.iter_next(treeiter)
	    gtk.gdk.threads_leave()

	gtk.gdk.threads_enter()
	bt_devices.append([self.btAddress,self.model,self.pname.get_text(),self.cfgFile.get_text(),AR_AVAIL])
	gtk.gdk.threads_leave()
	
    	self.close(w)

    def close(self,w):
        global debug
        self.isShown = False
    	self.hide()
        try:
            gobject.source_remove(self.ddQueueTimer)
        except AttributeError, NameError:
            if debug: print 'Exception: gobject.source_remove(gui.ddQueueTimer)'

    def chooseAction(self,w):
    	self.choose.set_sensitive(False)
	cfgChooser(self)

    def clicked_szAll(self,w):
        if self.szAll.get_active():
	   self.bigTitleIcon.set_active(False)
	   
    def clicked_bti(self,w):
        if self.szAll.get_active() and not self.noJsr82.get_active():
	   self.bigTitleIcon.set_active(False)
	   
        if not self.bigTitleIcon.get_active():
	   self.noJsr82.set_active(False)
	   
    def clicked_nojsr82(self,w):
    
        self.szAll.set_sensitive(not self.noJsr82.get_active())
        self.sz16.set_sensitive (not self.noJsr82.get_active())
        self.sz32.set_sensitive (not self.noJsr82.get_active())
        self.sz48.set_sensitive (not self.noJsr82.get_active())
        self.sz64.set_sensitive (not self.noJsr82.get_active())

        if self.noJsr82.get_active():
           self.bigTitleIcon.set_active(True)
	
    def test_at(self,w):
        global debug, cmd_array
	if debug: print 'test_at'
	stopPBar() 
	startPBar(AR_WAIT_OPS,30)
	queueBT('test_at',self.btAddress)

    def ping(self,w):
        global debug, cmd_array
	if debug: print _('Queue ping request')

	stopPBar() 
	startPBar(_('Wait ping results'),20)
	queueBT('ping',self.btAddress)
	    
    def upload(self,w):
        global debug, cmd_array, pbar
	if debug: print _('Queue push request')
	 
	sz = '16'   
	if self.noJsr82.get_active():
	    sz = 'nojsr82'
	elif self.szAll.get_active():
	    sz = ''
	else:
	    if self.sz32.get_active():
	        sz = '32'
	    elif self.sz48.get_active():
	        sz = '48'
	    elif self.sz64.get_active():
	        sz = '64'
	    
	    if self.bigTitleIcon.get_active():
	        sz = sz+'b'
	    
	stopPBar() 
	startPBar(AR_WAIT_OPS,20)
	
	push = 'pushjar'
	if self.uplJad.get_active():
	    push = 'pushjad'
	    
	queueBT(push+sz,self.btAddress)
   	
    def doWhen(self,w):
        global debug
	if debug: print 'doWhen'
	
	if self.run_when.get_active():
	    self.choose.set_sensitive(True)
	    self.cfgFile.set_sensitive(True)
	else: 
	    self.choose.set_sensitive(False)
	    self.cfgFile.set_text('')
	    self.cfgFile.set_sensitive(False)
	    
	if debug: print 'doWhen', self.cfgFile.get_text()

    def setStatustext(self,text):
	self.sBar.pop(self.cid)
	self.sBar.push(self.cid,'  ' + text)

    def checkQueue(self):
        global ddQueue
	try:
	    data = ddQueue.get(False)
	    
	    if data[0] == 'SET_STATUS':
	        self.setStatustext(data[1])
	    
	except Queue.Empty:
            pass
	return True
	    
##################################################################################
#
# Progressbar
#
##################################################################################

def startPBar(text,timeout):
    putToMainQueue(['PBAR_START',text,timeout])

def writePBar(text):
    putToMainQueue(['PBAR_WRITE',text])

def stopPBar():
    putToMainQueue(['PBAR_STOP'])

def progress_timeout(pbobj):
    pbobj.pbar.pulse()
    return True

class PBar(gtk.Window):
    def __init__(self, text, size, filename=None):
    
	gtk.Window.__init__(self)

        self.reset   = False
	 
    	self.text    = text
    	self.tmout   = size
    	self.fname   = filename

        self.set_resizable(True)

        self.set_title('')
        self.set_border_width(0)

        vbox = gtk.VBox(False, 5)
        vbox.set_border_width(10)
        self.add(vbox)

        align = gtk.Alignment(0.5, 0.5, 0, 0)
        vbox.pack_start(align, False, False, 5)

        self.pbar = gtk.ProgressBar()
        align.add(self.pbar)
	self.timer = gobject.timeout_add (100, progress_timeout, self)
	
	self.pbar.set_pulse_step(0.05)
	self.pbar.set_text(self.text)
	self.pbar.set_orientation(gtk.PROGRESS_LEFT_TO_RIGHT)

        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, False, 0)
	
        self.show_all()

    def set_text(self, t):
        self.text = t
        self.pbar.set_text(self.text)
	
    def stop(self):
        try:
            gobject.source_remove(self.timer)
        except AttributeError, NameError:
            print 'Exception: Pbar gobject.source_remove(gui.timer)'
    	    pass
        self.destroy()

##################################################################################
#
# Application status updater
#
##################################################################################
class StatusUpdater(threading.Thread):

    def __init__(self, timeout):
	threading.Thread.__init__(self) 
	self.tmout = timeout

    def run(self):
        global debug, liststore
	
	self.runUpdater =  True
	
	if debug: print 'StatusUpdater',self.tmout
	
	while self.runUpdater:
	    timer = 0
	    
	    # catch stop event without waiting full timeout
	    while self.runUpdater and timer < self.tmout:
	        time.sleep(0.1)
		timer = timer + 0.1
	    
	    if self.runUpdater:
	        if debug: print 'StatusUpdater: verify start'
	    
	        gtk.gdk.threads_enter()
	        treeiter = liststore.get_iter_first()
	        gtk.gdk.threads_leave()
	    
	    while self.runUpdater and treeiter != None:
	        gtk.gdk.threads_enter()
		aRun = liststore.get_value(treeiter, 3)
	        gtk.gdk.threads_leave()
		
	        if aRun != '':
	    	    isRun  = getResult(aRun,'updater')
		    
	            gtk.gdk.threads_enter()
	    	    status = liststore.get_value(treeiter, 5)
		    
		    if status == AR_MANAGED and isRun == 'NOK':
	    	        status = AR_AVAIL
		    elif status == AR_AVAIL and isRun == 'OK':
	    	        status = AR_RUNNING
		    elif status == AR_RUNNING and isRun == 'NOK':
	    	        status = AR_AVAIL
		    #else:
		    #    status = ''
		    
		    strIter = liststore.get_string_from_iter(treeiter)
		    
		    # PyGTK works non stable with threads_enter/threads_leave
		    #liststore.set_value(treeiter, 5, status)    
		    gtk.gdk.threads_leave()
		    
		    putToMainQueue(['UPDATE_LIST',strIter,status])
		
		gtk.gdk.threads_enter()   
	        treeiter = liststore.iter_next(treeiter)
		gtk.gdk.threads_leave()
		
	    if debug: print 'StatusUpdater: verify done'
		
    def stop(self):
        global debug
	
	if debug: print 'StatusUpdater: stop'
	self.runUpdater = False

##################################################################################
#
# Reader of cfg. files
#
##################################################################################
class CfgFileReader(threading.Thread):

    def __init__(self, cfgDirs, all, apps, cust, ex, at, srv, bm):
	threading.Thread.__init__(self) 
	
	global cfgFileReaderFlag
	
	cfgFileReaderFlag = True
	
	self.cfgDirs  = cfgDirs      
	self.all   = all      
	self.apps = apps      
	self.cust = cust      
	self.ex   = ex      
	self.at   = at     
	self.srv  = srv      
	self.bm   = bm      

    def run(self):
        global debug, liststore, gui, cfgFileReaderFlag
        
	gtk.gdk.threads_enter()
        gui.treeview.set_model(None);
	liststore.clear()
        gtk.gdk.threads_leave()
        
	self.regExp  = re.compile("^[^a-zA-Z0-9]*Gui")
	self.regExpB  = re.compile("^[^a-zA-Z0-9%]*VERS[^=]*=.+$")
	self.regExpAT = re.compile("^[^a-zA-Z0-9%]*Device[^=]*=/dev/[a-zA-Z0-9]+$")
        
	numProcessed = 0
	for cfgDir in self.cfgDirs:
	    if cfgDir == '':
	        continue
	    if debug: print 'Collect files in '+cfgDir
	    
	    if os.path.isfile(cfgDir):
	        self.processOneFile(cfgDir)
		
		numProcessed = numProcessed+1
		putToMainQueue(['LOADED',numProcessed])
		
	    else:
	        for root, dirs, files in os.walk(cfgDir):
	            for cfgFile in files:
		    
		    	nameext = cfgFile.split('.')
			ext = nameext[len(nameext)-1]
			
			if ext == 'png' or ext == 'sh' or ext == 'py' or ext == 'gz':
			    if debug: print 'Not a configuration file '+cfgFile
			    continue
		    
	    	        self.processOneFile(root + os.sep + cfgFile)
			
			numProcessed = numProcessed+1
			putToMainQueue(['LOADED',numProcessed])
	
	putToMainQueue(['SET_STATUS','S'])
	gtk.gdk.threads_enter()
        if gui.treeview.get_model() == None:
            gui.treeview.set_model(liststore)
        
	ti  = liststore.get_iter_first()
	while ti != None: 
	    fName = liststore.get_value(ti, 4)
            
 	    if fName == gui.lastCfgFile:
                try:
 	            gui.treeview.get_selection().select_iter(ti)
		except AttributeError:
                    pass
                break
		
	    ti = liststore.iter_next(ti)

	gtk.gdk.threads_leave()
	
	cfgFileReaderFlag = False
	
	    
    def processOneFile(self,cfgFile):
        global icons, debug, gui, liststore
	
        fd = None
        try:
	    fd = open(cfgFile,'r')
        except IOError:
            pass
         
	if fd:
	    aName    = None
	    aInst    = ''
	    aRun     = ''
	    aIcon    = ''
	    aType    = None
	    aDesc    = ''
	    aVers    = ''
	    aModes   = ''
	    aDevice  = ''
	    aBemused = ''
	
            for line in fd:
	
		if self.regExp.match(line):
	    	
	    	    p = re.search("^[^a-zA-Z0-9]*GuiAppName[^=]*=(.+)$", line)
	    	    if p != None:
	    		aName = p.group(1)

	    	    p = re.search("^[^a-zA-Z0-9]*GuiAppBinary[^=]*=(.+)$", line)
	    	    if p != None:
	    		aInst = p.group(1)
	    	
	    	    p = re.search("^[^a-zA-Z0-9]*GuiAppRun[^=]*=(.+)$", line)
	    	    if p != None:
	    		aRun = p.group(1)
	       
	    	    p = re.search("^[^a-zA-Z0-9]*GuiAppIcon[^=]*=(.+)$", line)
	    	    if p != None:
	    		aIcon = p.group(1)

	    	    p = re.search("^[^a-zA-Z0-9]*GuiAppType[^=]*=(.+)$", line)
	    	    if p != None:
	    		aType = p.group(1)
			
	    	    p = re.search("^[^a-zA-Z0-9]*GuiAppDesc[^=]*=(.+)$", line)
	    	    if p != None:
	    		aDesc = p.group(1)

	    	    p = re.search("^[^a-zA-Z0-9]*GuiAppVersion[^=]*=(.+)$", line)
	    	    if p != None:
	    		aVers = p.group(1)

		    # deprecated, use GuiAppProtocols	
	    	    p = re.search("^[^a-zA-Z0-9]*GuiAppModes[^=]*=(.+)$", line)
	    	    if p != None:
	    		aModes = p.group(1)

		    p = re.search("^[^a-zA-Z0-9]*GuiAppProtocols[^=]*=(.+)$", line)
	    	    if p != None:
	    		aModes = p.group(1)
			
	    	if self.regExpAT.match(line):
	    	    aDevice = 'a'
	    	
	    	if self.regExpB.match(line):
	    	    aBemused = 1
	
            if (not aName) and (not aType):
               if debug: print 'Not a configuration file. Skip '+cfgFile
               fd.close()
               return
            
	    aMode = ['Server']    
	    if aModes == '': 
	        if aBemused == 1:
		    aMode = ['Bemused']
	        elif aDevice == 'a':
		    aMode = ['AT']
	    else:
	        aMode = [] 
		# not use aModes.split(',') to make more strict control
	        if aModes.find('Server') >= 0:
		    aMode.append('Server')

	        if aModes.find('Bemused') >= 0:
		    aMode.append('Bemused')
	        
		if aModes.find('AT') >= 0:
		    aMode.append('AT')
		
		# not add it since iViever support is still experimental    
	        #if aModes.find('iViewer') >= 0:
		#    aMode.append('iViewer'
	    	
	    if aName == '' or aName == None:
	    	aName = os.path.basename(cfgFile)
	    	
            app = aInst
	    if aInst == '':
	    	isInst = 'OK'
	    else:
                cnt = aInst.count(' ')
                
                if cnt > 0: # treat this like a command to execute
                    app = getResult(aInst, 'bin')
	        
	    	isInst = isInstalled(app)

	    show  = 1
	    show1 = 1
	    show2 = 1
	    status = AR_NOTAVAIL
	    if isInst == 'OK':
	    	status = AR_AVAIL
		
		# check version if requested
		if aVers != '':
		    version = reqVersion(aVers)

		    if version == 'NOK':
		        isInst = 'NOK'
			status = AR_NOTAVAIL
	    
	    if isInst == 'NOK' and not self.all:
	        show1 = 0
	    elif isInst == AR_NOINFO:
	    	status = ''
	    
	    if not self.all:

		if 'Server' in aMode and not self.srv:
	    	    aMode.remove('Server')
	    	
		if 'AT' in aMode and not self.at:
	    	    aMode.remove('AT')
 	        
		if 'Bemused' in aMode and not self.bm:
	    	    aMode.remove('Bemused')
		    
		if len(aMode) > 0:
		    show = 1
	        else:
		    show = 0
		    
	        if aType == 'Application' and not self.apps:
	            show2 = 0
	        elif aType == 'Custom' and not self.cust:
	            show2 = 0
	        elif aType == 'Example' and not self.ex :
	            show2 = 0
	        elif aType == '':
	            show2 = 0
	    
	    if show == 1 and show1 == 1 and show2 == 1:
		if debug: print 'Proceed '+aName
	
	    	if aIcon == '':
	    	    aIcon = 'fileopen.png'
	    
	    	pbuf = findIcon(aIcon)
	    		    	
	    	if aRun == '':
	    	    isRun = AR_NOINFO
	    	else:
	    	    isRun  = getResult(aRun,'reader')
		
		if status == AR_AVAIL and isRun == 'OK':
	    	    status = AR_RUNNING
	    		
	    	gtk.gdk.threads_enter()
		for oneMode in aMode: 
		    item = liststore.append([aName, pbuf, app, aRun, cfgFile, status, _(oneMode), _(aType), aDesc])
		gtk.gdk.threads_leave()
		
	    else:
		if debug: print 'Skip '+aName
	    	
	    fd.close()

##################################################################################
#
# Choose cfg. file 
#
##################################################################################
class cfgChooser (gtk.Window):

    def __init__(self, details_win):
        global debug, liststore
	
	gtk.Window.__init__(self)

	self.dw = details_win
    
        self.set_title(_('Choose application'))
	self.connect("destroy", self.closePressed)
	
        vbox = gtk.VBox(False, 0)
        self.add(vbox)
        vbox.show()

        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 1, 1, 0, gtk.PACK_START)
        hbox.show()
	
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        hbox.add(scrolledwin)
	hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PACK_START)
	scrolledwin.show()

        self.treeview  = gtk.TreeView(liststore)
       
        self.column_app    = gtk.TreeViewColumn(AR_APP)
        self.column_mode   = gtk.TreeViewColumn(AR_MODE)
        
	self.column_app.set_resizable(True)
	self.column_mode.set_resizable(True) 

	self.column_app.set_expand(True)
	
	self.column_app.set_spacing(5)
	self.column_mode.set_spacing(5)
  
	self.treeview.append_column(self.column_app)
        self.treeview.append_column(self.column_mode)

        self.cell0 = gtk.CellRendererPixbuf()
        self.cell1 = gtk.CellRendererText()
        self.cell2 = gtk.CellRendererText()

        self.column_app.pack_start   (self.cell0, False)
        self.column_app.pack_start   (self.cell1, True)
        self.column_mode.pack_end    (self.cell2, False)
	
        self.column_app.set_attributes   (self.cell0, pixbuf=1)
        self.column_app.set_attributes   (self.cell1, text=0)
        self.column_mode.set_attributes  (self.cell2, text=6)

        self.treeview.set_search_column(0)
        self.column_app.set_sort_column_id(0)
 	
        scrolledwin.add(self.treeview)
	self.treeview.connect("row_activated",  self.rowActivateAction)
	
	self.treeview.show()
	
	################
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()
  
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        b = gtk.Button(label=AR_OK)
        b.connect("clicked", self.okPressed)
        hbox.pack_start(b, True, True, 0)

        b = gtk.Button(label=AR_CLOSE)
        b.connect("clicked", self.closePressed)
        hbox.pack_start(b, True, True, 0)
	
	self.set_size_request(400, 300)
	
	self.show_all()

    def rowActivateAction(self, treeview, path, view_column):
	treeiter = liststore.get_iter(path)
	self.quitOk(treeiter)

    def closePressed(self, widget):
	self.dw.choose.set_sensitive(True)
        self.destroy()

    def okPressed(self, widget):
    
	(model, titer) = self.treeview.get_selection().get_selected()
	self.quitOk(titer)
	
    def quitOk(self, treeiter):
        global liststore
	
	try:
            s = liststore.get_value(treeiter, 4)
        except TypeError:
	    # nothing was chosen
	    return
	    
	self.dw.cfgFile.set_text(s)
	self.dw.cfgFile.set_sensitive(True)
	self.dw.cfgFile.set_position(len(s))
	self.dw.choose.set_sensitive(True)
        self.destroy()
    
##################################################################################
#
# Front-End to anyRemote
#
##################################################################################

class FrontEnd(threading.Thread):
    def __init__(self): 
        global debug
    	threading.Thread.__init__(self)        
    	if debug: print 'FrontEnd init'

    def stop(self):
        global debug
    	if debug: print 'FrontEnd stop'
    	self.isRun = False

    def run(self):
    	global port, debug
    	
    	self.isRun = True
    	if debug: print 'FrontEnd thread is running', port

    	s = None
    	for res in socket.getaddrinfo('localhost', port, socket.AF_INET, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
    	    af, socktype, proto, canonname, sa = res
    	    
    	    try:
    		s = socket.socket(af, socktype, proto)
    		s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    		s.setblocking(0)
    	    except socket.error, msg:
    		s = None
    		continue
    	    if debug: print 'FrontEnd socket created'
    		
    	    try:
    		s.bind(sa)
    		s.listen(1)
    	    except socket.error, msg:
    		s.close()
    		s = None
    		continue
    	    if debug: print 'FrontEnd socket after listen'
    	    
    	    break
    	    
    	if s is None:
    	    if debug: print 'FrontEnd could not open socket'
    	    sys.exit(1)

    	while self.isRun:
    	    while self.isRun:
    		#print 'FrontEnd accepting connection'
    		try:
    		    conn, addr = s.accept()
    		    if debug: print 'accept', addr
    		    break
    		except socket.error,msg:
    		    #print 'accept err', msg
    		    time.sleep(0.1)
    	   
	    if self.isRun:
    	        self.processOneConnection(conn, addr)
    	
    	if debug: print 'Close server socket' 
    	s.close()
	    
    def processOneConnection(self,conn,addr):
	global gui, liststore, cmdToSend, debug
    	
        if debug: print 'FrontEnd processOneConnection', addr
	
	cfgFile = getResult('ps aux |grep anyremote|grep cfg|awk \'{n=split($0,arr);print arr[n];}\'', 'frontend')
	if cfgFile != '':
	    gtk.gdk.threads_enter()
	    ti  = liststore.get_iter_first()
	    while ti != None:
	        fName = liststore.get_value(ti, 4)
	        if fName == cfgFile:
		
		    strIter = liststore.get_string_from_iter(ti)
		    putToMainQueue(['UPDATE_LIST',strIter,AR_MANAGED])
		    break
		    
	        ti = liststore.iter_next(ti)
		
	    gtk.gdk.threads_leave()
    
        self.isConn = True
    	while self.isRun and self.isConn:
    	
    	    conn.setblocking(0)
    
    	    if debug: print 'FrontEnd.Connected by', addr
    	
	    putToMainQueue(['SET_STATUS','D'])
    	
    	    #time.sleep(0.5)
    	
    	    while self.isRun and self.isConn:
    	    	
    	    	time.sleep(0.2)
    	
    	    	data = ''
    	    	try:
    	    	    data = conn.recv(512)
    	    	    if debug: print 'Got from backend ', data
    	    	    
		    putToMainQueue(['GET_DATA',data])
     	    	
    	    	    if not data: 
    	    		if debug: print 'FrontEnd anyRemote die?'
    	    	    
 			putToMainQueue(['SET_STATUS','S'])
    	    		self.isConn = False
    	    		break

    	    	except socket.error,msg:
    	    	    pass
    	    	
    	    	try:
    	    	    #print 'Send to backend ???'
    	    	    gtk.gdk.threads_enter()
    	    	    if cmdToSend:
    	    		# need to syncronize with GUI thread
    	    		if debug: print 'Send to backend '+cmdToSend + "\n"
    	    		conn.sendall(cmdToSend)
    	    		cmdToSend = '';
    	    	    gtk.gdk.threads_leave()
    	    		
    	    	except socket.error, NameError:
    	    	    if debug: print 'EXCEPTION 1'
    	    	    pass
    	
    	    if debug: print 'Close connection'  
    	    conn.close()
	    
	    gtk.gdk.threads_enter()
	    ti  = liststore.get_iter_first()
	    while ti != None:
	        stts = liststore.get_value(ti, 5)
	        if stts == AR_MANAGED:

		    aRun = liststore.get_value(ti, 3)
	            if aRun != '':
	    	        isRun  = getResult(aRun,'frontend')
                    
			status = AR_AVAIL
			if isRun == 'OK':
			    status = AR_RUNNING
			
			strIter = liststore.get_string_from_iter(ti)
			putToMainQueue(['UPDATE_LIST',strIter,status])
			
		    else:
		        isInst = isInstalled(liststore.get_value(ti, 2))
			
			status = ''
			if isInst == 'OK':
			    status = AR_AVAIL
			    
			strIter = liststore.get_string_from_iter(ti)
			putToMainQueue(['UPDATE_LIST',strIter,status])
		    
	        ti = liststore.iter_next(ti)
	    gtk.gdk.threads_leave()
		
		
##################################################################################
#
# Device browser
#
##################################################################################

class DeviceBrowser (gtk.Window):

    def __init__(self):
        global gui, debug, bt_devices
	
	gtk.Window.__init__(self)
    
        self.set_title("gAnyRemote device browser")
        self.connect("destroy", self.close)

        vbox = gtk.VBox(False, 0)
        self.add(vbox)
	
	self.createMenus(vbox)

        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 1, 1, 0, gtk.PACK_START)
	
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        hbox.add(scrolledwin)
	hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PACK_START)

        self.treeview  = gtk.TreeView(bt_devices)
       
        self.column_name = gtk.TreeViewColumn(_('Name'))
        self.column_dnam = gtk.TreeViewColumn(_('Device Name'))
        self.column_addr = gtk.TreeViewColumn(_('Address'))
        self.column_stts = gtk.TreeViewColumn(AR_STATUS)
        
	self.column_name.set_resizable(True)
	self.column_dnam.set_resizable(True)
	self.column_addr.set_resizable(True)
	self.column_stts.set_resizable(True) 

	self.column_name.set_expand(True)
	
	self.column_name.set_spacing(5)
	self.column_dnam.set_spacing(5)
	self.column_addr.set_spacing(5)
	self.column_stts.set_spacing(5)
  
	self.treeview.append_column(self.column_name)
	self.treeview.append_column(self.column_dnam)
        self.treeview.append_column(self.column_addr)
        self.treeview.append_column(self.column_stts)

        self.cell1 = gtk.CellRendererText()
        self.cell2 = gtk.CellRendererText()
        self.cell3 = gtk.CellRendererText()
        self.cell4 = gtk.CellRendererText()

        self.column_name.pack_start(self.cell1, True)
        self.column_dnam.pack_start(self.cell2, False)
        self.column_addr.pack_start(self.cell3, False)
        self.column_stts.pack_start(self.cell4, False)
	
        self.column_name.set_attributes(self.cell1, text=2)
        self.column_dnam.set_attributes(self.cell2, text=1)
        self.column_addr.set_attributes(self.cell3, text=0)
        self.column_stts.set_attributes(self.cell4, text=4)

        self.treeview.set_search_column(0)

        self.column_name.set_sort_column_id(0)
	
	bt_devices.set_sort_column_id(0,gtk.SORT_ASCENDING)
 	
        scrolledwin.add(self.treeview)
	self.treeview.connect("row_activated",  self.rowActivateAction)
	
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	
	self.set_size_request(420, 200)
	self.show_all()
	
	self.isShown = True

	if gui.browseTmout_ > 0:
	    browseDevices('F')
	    self.timer = gobject.timeout_add (int(1000)*gui.browseTmout_, browseDevices)

    def createMenus(self, vbox):
    
        self.menubar = gtk.MenuBar()
        vbox.pack_start(self.menubar, expand=False)

        topmenuitem = gtk.MenuItem(AR_FILE)
        self.menubar.add(topmenuitem)
	
        menu = gtk.Menu()
	topmenuitem.set_submenu(menu)
 
        menuitem = iconMenuItem(_('Scan for devices'), gtk.STOCK_FIND)
        menu.add(menuitem)
	menuitem.connect('activate', self.scan)

	menuitem = iconMenuItem(_('Details'),gtk.STOCK_PROPERTIES)
        menu.add(menuitem)
	menuitem.connect('activate', self.details)

        menuitem = gtk.ImageMenuItem(gtk.STOCK_REMOVE)
        menu.add(menuitem)
	menuitem.connect('activate', self.delete)

        menuitem = gtk.ImageMenuItem(gtk.STOCK_CLOSE)
        menu.add(menuitem)
	menuitem.connect('activate', self.close)

    def showDetails(self,ti):
        global dwin
	v1 = bt_devices.get_value(ti, 0)
	v2 = bt_devices.get_value(ti, 1)
	v3 = bt_devices.get_value(ti, 2)
	v4 = bt_devices.get_value(ti, 3)
	
        showDetailsWin(v1, v2, v3, v4, False)

    def scan(self,w):
	stopPBar () 
	startPBar(_('Scanning'),30)
        browseDevices('T')

    def delete(self,w):
        global bt_devices
	
	(model, titer) = self.treeview.get_selection().get_selected()
	if titer:
            treeiter = bt_devices.remove(titer)

    def details(self,w):
	(model, titer) = self.treeview.get_selection().get_selected()
	if titer:
	    self.showDetails(titer)

    def rowActivateAction(self, treeview, path, view_column):
        global bt_devices
	self.showDetails(bt_devices.get_iter(path))
		    
    def close(self,w):
        global debug
	if debug: print "DeviceBrowser.close"
	
	saveDevices()
	
        self.destroy()
	self.isShown = False
	    
##################################################################################
#
# Configuration checker 
#
##################################################################################

class CfgChecker (gtk.Window):

    def __init__(self, jDir):
        global debug
    
	gtk.Window.__init__(self)

	self.javaDir = jDir
       
        self.set_title(_('Configuration Check'))
        self.connect("destroy", self.close)
    
	if debug: print 'CfgChecker: initWindow'
     
    	pbs = AR_NOTINSTALLED
	if pybluez: pbs = _('Installed')
	
        ars = isInstalled('anyremote')
        if ars == 'NOK':
	    ars = AR_NOTINSTALLED
        else:
            ars = _('Installed')

        bus = isInstalled('sdptool')
        if bus == 'NOK':
	    bus = AR_NOTINSTALLED
        else:
            bus = _('Installed')

        jDir = getJ2MEPath()
        jVer = ''
	ajs = _('Installed')
        if jDir == '':
	    ajs = AR_NOTINSTALLED
        else:
            jVer = getJavaClientVersion(jDir+os.sep+'anyRemote-16.jad')
            
        if jDir == os.environ.get("HOME")+os.sep+'.anyRemote':
	    ajs = _('Downloaded')

        ajs = ajs+' v.'+jVer

        ahs = isInstalled('anyremote2html')
        if ahs == 'NOK':
	    ahs = AR_NOTINSTALLED
        else:
            ahs = _('Installed')
        
	bts = btVerify(False)
        if bts == 'NOK':
	    bts = _('Not active')
        else:
            bts = _('Active')
    
        pkg_list = gtk.TreeStore(str,str)
	pkg_list.append(None,["anyRemote",ars])
	pkg_list.append(None,["Bluez utilities",bus])
	pkg_list.append(None,["PyBluez",pbs])
	ti = pkg_list.append(None,["anyremote-J2ME-client",ajs])
       
	if jDir != self.javaDir and jDir != '':
	    pkg_list.append(ti,[_('Warning:'),_('Installation directory of anyremote-J2ME-client not specified in current setup configuration !')])
        
	# it needs to run it in separated thread
        #jnewver = checkJavaClientUpdate()
        #if ajs != AR_NOTINSTALLED and jnewver != "":
	#    pkg_list.append(ti,[_('Info:'),_('New version of anyremote-J2ME-client is available for download')+' v.'+jnewver])

	pkg_list.append(None,["anyremote2html",ahs])
	pkg_list.append(None,["Bluetooth service",bts])

        vbox = gtk.VBox(False, 0)
        self.add(vbox)
	
	self.createMenus(vbox)

        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 1, 1, 0, gtk.PACK_START)
	
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        hbox.add(scrolledwin)
	hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PACK_START)

        self.treeview  = gtk.TreeView(pkg_list)
        self.treeview.expand_all()
       
        self.column_pkg  = gtk.TreeViewColumn(_('Package'))
        self.column_stat = gtk.TreeViewColumn(AR_STATUS)
        
	self.column_pkg.set_resizable(True)
	self.column_stat.set_resizable(True)

	self.column_pkg.set_expand(True)
	
	self.column_pkg.set_spacing(5)
	self.column_stat.set_spacing(5)
  
	self.treeview.append_column(self.column_pkg)
	self.treeview.append_column(self.column_stat)

        self.cell1 = gtk.CellRendererText()
        self.cell2 = gtk.CellRendererText()

        self.column_pkg.pack_start(self.cell1, True)
        self.column_stat.pack_start(self.cell2, False)
	
        self.column_pkg.set_attributes(self.cell1, text=0)
        self.column_stat.set_attributes(self.cell2, text=1)

        self.treeview.set_search_column(0)

        self.column_pkg.set_sort_column_id(0)
	
	pkg_list.set_sort_column_id(0,gtk.SORT_ASCENDING)
 	
        scrolledwin.add(self.treeview)
	
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	
	self.set_size_request(320, 220)
	self.show_all()
	
	self.isShown = True

    def createMenus(self, vbox):
    
        self.menubar = gtk.MenuBar()
        vbox.pack_start(self.menubar, expand=False)

        topmenuitem = gtk.MenuItem(AR_FILE)
        self.menubar.add(topmenuitem)
	
        menu = gtk.Menu()
	topmenuitem.set_submenu(menu)

        menuitem = gtk.ImageMenuItem(gtk.STOCK_CLOSE)
        menu.add(menuitem)
	menuitem.connect('activate', self.close)

    def close(self,w):
        self.destroy()
	self.isShown = False
	    
##################################################################################
#
# Editor 
#
##################################################################################

class cfgEditor (gtk.Window):

    def __init__(self, f):
	
	gtk.Window.__init__(self)
	
	self.editedFile = f
	
	self.set_size_request(600, 700)
        self.set_resizable(True)  
        self.connect("destroy", self.closeEditWindow)
        self.set_title(_('Edit configuration file'))
        self.set_border_width(0)

        box1 = gtk.VBox(False, 0)
        self.add(box1)
       
        self.menubar = gtk.MenuBar()
        box1.pack_start(self.menubar, expand=False)
       
        topmenuitem = gtk.MenuItem(AR_FILE)
        self.menubar.add(topmenuitem)

        menu = gtk.Menu()
	topmenuitem.set_submenu(menu)
	
	menuitem = iconMenuItem(_('Save'), gtk.STOCK_SAVE)
	menu.add(menuitem)
	menuitem.connect('activate', self.saveFile)
	
	menuitem = iconMenuItem(_('Save As'), gtk.STOCK_SAVE_AS)
	menu.add(menuitem)
	menuitem.connect('activate', self.saveAs)
	
	menuitem = iconMenuItem(AR_CLOSE, gtk.STOCK_CLOSE)
	menu.add(menuitem)
	menuitem.connect('activate', self.closeEditWindow)
 
        box2 = gtk.VBox(False, 10)
        box2.set_border_width(10)
        box1.pack_start(box2, True, True, 0)

        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        textview = gtk.TextView()
	textview.set_editable(False);
        self.textbuffer = textview.get_buffer()
        sw.add(textview)

        box2.pack_start(sw)
	
        infile = None
        try:
            infile = open(self.editedFile, "r")
        except IOError:
            pass
            
        if infile:
            string = infile.read()
            infile.close()
            self.textbuffer.set_text(string)
	    
	    textview.set_editable(os.access(self.editedFile, os.W_OK))

	else:
	    errorMessage(_('Can not read the file ')+self.editedFile)
	    self.editedFile = ""
		
        self.show_all()

    def closeEditWindow(self, widget):
        self.destroy()

    def saveFile(self, widget):
	try:
	    f=open(self.editedFile, 'w')
	
	    if f:
    	        i1 = self.textbuffer.get_iter_at_offset(0)
    	        i2 = self.textbuffer.get_iter_at_offset(self.textbuffer.get_char_count())
                txt = self.textbuffer.get_text(i1, i2)
	        f.write(txt)
	        f.close()
		self.destroy()
        except IOError:
	    errorMessage(_('Can not save the file !'))
	    self.saveAs(None)

    def saveAs(self, widget):
	self.fdialog = gtk.FileChooserDialog(_('Save File As'),None,gtk.FILE_CHOOSER_ACTION_SAVE,
	                        (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK))
 	
	self.fdialog.set_default_response(gtk.RESPONSE_OK)
        response = self.fdialog.run()
	
        if response == gtk.RESPONSE_OK:
            f = self.fdialog.get_filename()
            if f:
                self.editedFile = f
                self.saveFile(None)
	self.fdialog.destroy()

##################################################################################
#
# Main window
#
##################################################################################

class gAnyRemote(gtk.Window):

    def __init__(self, openW):
        global debug, guiMode, liststore
    
	gtk.Window.__init__(self)
	
    	initVerify()
	
    	self.notInTray = openW
	self.useType   = ''
    
        try:
	    self.tray = gtk.StatusIcon()
            self.tray.connect('popup-menu', self.rightClickAction)
	    self.tray.connect('activate',   self.trayPressAction)
        except AttributeError:
    	    self.tray = None
            self.notInTray = True
    
        self.set_title("gAnyRemote")
        
	if self.tray:
	    self.connect("delete_event", self.hideWindow2)
	else:
	    self.connect("destroy", self.quitAction)
	
	self.connect("size-allocate", self.resizeEvent)
	
        vbox = gtk.VBox(False, 0)
        self.add(vbox)
        vbox.show()
	
	self.createMenus(vbox)

        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 1, 1, 0, gtk.PACK_START)
        hbox.show()
	
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        hbox.add(scrolledwin)
	hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PACK_START)
	scrolledwin.show()

        self.treeview  = gtk.TreeView() 
       
        self.column_app    = gtk.TreeViewColumn(AR_APP)
        self.column_status = gtk.TreeViewColumn(AR_STATUS)
        self.column_mode   = gtk.TreeViewColumn(AR_MODE)
        self.column_type   = gtk.TreeViewColumn(_('Type'))
        
	self.column_app.set_resizable(True)
	self.column_status.set_resizable(True)
	self.column_mode.set_resizable(True) 
	self.column_type.set_resizable(True)  

	self.column_app.set_expand(True)
	
	self.column_app.set_spacing(5)
	self.column_status.set_spacing(5)
	self.column_mode.set_spacing(5)
	self.column_app.set_spacing(5)
	
	#self.column_app.set_min_width(200)
  
	self.treeview.append_column(self.column_app)
        self.treeview.append_column(self.column_status)
        self.treeview.append_column(self.column_mode)
        self.treeview.append_column(self.column_type)

        self.cell0 = gtk.CellRendererPixbuf()
        self.cell1 = gtk.CellRendererText()
        self.cell2 = gtk.CellRendererText()
        self.cell3 = gtk.CellRendererText()
        self.cell4 = gtk.CellRendererText()

        self.column_app.pack_start   (self.cell0, False)
        self.column_app.pack_start   (self.cell1, True)
        self.column_status.pack_start(self.cell2, False)
        self.column_mode.pack_start  (self.cell3, False)
        self.column_type.pack_end    (self.cell4, False)
	
        self.column_app.set_attributes   (self.cell0, pixbuf=1)
        self.column_app.set_attributes   (self.cell1, text=0)
        self.column_status.set_attributes(self.cell2, text=5)
        self.column_mode.set_attributes  (self.cell3, text=6)
        self.column_type.set_attributes  (self.cell4, text=7)

        self.treeview.set_search_column(0)
        #self.treeview.set_fixed_height_mode(1)

        self.column_app.set_sort_column_id(0)
	
	liststore.set_sort_column_id(0,gtk.SORT_ASCENDING)
 	
        scrolledwin.add(self.treeview)
	self.treeview.connect("row_activated",  self.rowActivateAction)
	self.treeview.connect("cursor_changed", self.rowSelectAction)
	
	self.treeview.show()
	
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()

	################
        hbox = gtk.HBox(False, 0)
	if guiMode == 'expert':
            vbox.add(hbox)
	    vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
            hbox.show()
	    
        self.entry = gtk.Entry()
        self.entry.set_max_length(512)
	
	if guiMode == 'expert':
            hbox.pack_start(self.entry, True, True, 0)
            self.entry.show()

	if guiMode == 'expert':
            b = gtk.Button(label=AR_CHOOSE)
            b.connect("clicked", self.openFDialog, self.entry)
            hbox.pack_end(b, False, False, 0)
		
	################
	if debug:
            hbox = gtk.HBox(False, 0)
            vbox.add(hbox)
	    vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
	
            self.cmd = gtk.Entry()
            self.cmd.connect('key-press-event', self.commandRun)
            self.cmd.set_max_length(512)
            hbox.pack_start(self.cmd, True, True, 0)
 
            bExec = gtk.Button(label=_('Execute Command'))
            bExec.connect("clicked", self.execCmd)
            hbox.pack_end(bExec, False, False, 0)
  
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        self.detailsStore = gtk.TreeStore(str)
	self.detailsHead = self.detailsStore.append(None,[_('Details')])
	self.detailsData = self.detailsStore.append(self.detailsHead,[''])
         
        self.detailsTreeview  = gtk.TreeView(self.detailsStore)
        
        self.detailsRenderer = gtk.CellRendererText()
        self.detailsRenderer.set_property('cell-background-gdk', self.get_style().bg[gtk.STATE_NORMAL])
        try:
	    self.detailsRenderer.set_property('wrap-mode', pango.WRAP_WORD) #gtk.WRAP_WORD ?
	except TypeError, AttributeError:
	    pass
	        
        self.detailsColumn = gtk.TreeViewColumn('')
        self.detailsColumn.pack_start(self.detailsRenderer, True)
        self.detailsColumn.set_attributes(self.detailsRenderer, text=0)
        self.detailsColumn.set_sort_column_id(0)
        
	self.detailsTreeview.append_column(self.detailsColumn) 
        self.detailsTreeview.set_headers_visible(False)
        self.detailsTreeview.set_enable_search(False)
        self.detailsTreeview.get_selection().set_mode(gtk.SELECTION_NONE)

        hbox.pack_start(self.detailsTreeview, True, True, 0)

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)

        btn = gtk.Button(label=_('Update Status'))
        addIconToButton(btn,gtk.STOCK_REFRESH)
        btn.connect("clicked", self.rescanPressed)
        hbox.pack_start(btn, True, True, 0)

        self.runBtn = gtk.Button(label=_('Start'))
        addIconToButton(self.runBtn,gtk.STOCK_EXECUTE)
        self.runBtn.connect("clicked", self.runPressed)
        hbox.pack_start(self.runBtn, True, True, 0)

        self.stopBtn = gtk.Button(label=_('Stop'))
        addIconToButton(self.stopBtn,gtk.STOCK_STOP)
        self.stopBtn.connect("clicked", self.stopPressed)
        hbox.pack_start(self.stopBtn, True, True, 0)
                                                             	
	self.sBar = gtk.Statusbar()
	vbox.add(self.sBar)
	vbox.set_child_packing(self.sBar, 0, 1, 0, gtk.PACK_END)
	self.cid = self.sBar.get_context_id('a')

	if debug:
	    h = 420
	else:
	    h = 390
	    
	self.set_size_request(500, h)
        
	try:
	    self.detailsRenderer.set_property('wrap-width', 450)
	except TypeError, AttributeError:
	    pass
	    
	self.set_icon(findIcon('ganyremote.png'))
	
	if self.notInTray:
	     self.show_all()
        
	self.pixbufOn    = findIcon('ganyremote.png')
	self.pixbufOff   = findIcon('ganyremote_off.png')
	self.pixbufFlash = findIcon('ganyremote_flash.png')
	self.pixbufRun   = findIcon('ganyremote_light.png')

	self.curPixbuf = self.pixbufOff
        if self.tray != None: self.tray.set_from_pixbuf(self.curPixbuf)
		
	gtk.window_set_default_icon(self.pixbufOn)
		
	self.setStatusStopped()
	
	self.setDefaultConfig()
	
	if os.path.exists(os.environ.get("HOME")+os.sep+'.anyRemote'+os.sep+'anyremote-fe.conf'):
	    self.readConfig()
	else:
	    set = 0
	    if os.path.exists('/usr/share/anyremote/cfg-data'):
	        set = 1
		self.cfgDirs.append('/usr/share/anyremote/cfg-data')
		
	    elif os.path.exists('/usr/local/share/anyremote/cfg-data'):
	        set = 1
		self.cfgDirs.append('/usr/local/share/anyremote/cfg-data/')
		
	    # quick fix for ubuntu
	    elif os.path.exists('/etc/anyremote/cfg-data'):
	        set = 1
		self.cfgDirs.append('/etc/anyremote/cfg-data')

            self.javaDir_ = getJ2MEPath() 
		
	    if set == 0 or self.javaDir_ == '':
		self.showWizard()
	    
	if self.checkJavaUpdate_:
	    if debug: print 'Check java client updates at web'

    
	    jv = JCVerifier(False)
	    jv.start()
	
	self.frontEnd = None

	self.inQueueTimer = gobject.timeout_add(300, self.checkInputQueue)
    
	    
    ##################################################################################
    #
    # Configuration related part
    #
    ##################################################################################

    def saveConfigAction(self, action):
        self.saveConfig()

    def saveConfig(self):
        global bt_devices
	
 	# anyRemote related part
   	cfg = os.environ.get("HOME")+os.sep+'.anyRemote'
    	if os.path.exists(cfg):
	    pass
	else:
	    os.mkdir(cfg)
	    
	f=open(cfg + os.sep + 'anyremote-fe.conf', 'w')
	if f:
 	    f.write('LastCfgFile='+self.entry.get_text()+'\n')
	    
	    if self.showAll_:
	        f.write('Show=All\n')
	    else:
	    	what = 'Show='
		if self.showApps_:
		    what = what + 'Apps,'
		if self.showCustom_:
		    what = what + 'Custom,'
		if self.showExamples_:
		    what = what + 'Examples,'
		if self.showAt_:
		    what = what + 'AT,'
		if self.showSrv_:
		    what = what + 'Server,'
		if self.showBm_:
		    what = what + 'Bemused,'
	    	
		f.write(what+'\n')

	    ac = '0'
            if self.autoReconn_:
	        ac = '1'
 	    f.write('AutoReconnectAT='+ac+'\n')
	    
	    if self.runWeb_:
	        f.write('WebInterface='+self.webParams_+'\n')

	    if self.device_ != '':
	        f.write('OverrideDevice='+self.device_+'\n')

	    #if self.updateTmout_ != -1:
	    tm = "%s" % (self.updateTmout_)
	    f.write('UpdateTimeout='+tm+'\n')
		
	    dirs = 'CfgDirs='
	    for d in self.cfgDirs:
	    	if d != '':
	            dirs = dirs +d + ';'
 	    f.write(dirs+'\n')
	    
	    if self.browseTmout_ > 0:
	        tm = "%s" % (self.browseTmout_)
	        f.write('DeviceBrowserTimeout='+tm+'\n')
            else:
	        f.write('DeviceBrowserTimeout=-1\n')
	   
	    f.write('JavaDir='+self.javaDir_+'\n')
	    if self.checkJavaUpdate_:
	        f.write('CheckJavaUpdate=true\n')

	    f.close()
	
	saveDevices()

    def setDefaultConfig(self):
    
	self.lastCfgFile   = ''
	self.cfgDirs       = []
	self.javaDir_      = ''
	self.checkJavaUpdate_ = False
	self.showApps_     = True
	self.showCustom_   = False
	self.showExamples_ = False
	self.showAt_       = False
	self.showSrv_      = True
	self.showBm_       = False
	self.showAll_      = False
	self.autoReconn_   = False
	self.device_       = ''
	self.runWeb_       = False
	self.webParams_    = ''
	self.updateTmout_  = 60
	self.browseTmout_  = -1
	
    def readConfig(self):
        global bt_devices

	# anyRemote related part
       	cfg  = os.environ.get("HOME")+os.sep+'.anyRemote' + os.sep + 'anyremote-fe.conf'
	
    	if os.path.exists(cfg):
	    f=open(cfg, 'r')
	    if f:
	        for line in f:
		    line = line.replace('\n','')
		    os.path.exists(cfg) 
		    if line.startswith('LastCfgFile='):
		        self.lastCfgFile=line[12:]
		    elif line.startswith('Show='):
		    	#Show=Apps,Custom,Examples|All
			what = line[5:].split(',')
			
			# override defaults
	                self.showApps_ = False
			self.showSrv_  = False
			
			for item in what:
			   if item == 'All':
			      self.showAll_ = True
			   elif item == 'Apps':
			      self.showApps_ = True
			   elif item == 'Custom':
			      self.showCustom_ = True
			   elif item == 'Examples':
			      self.showExamples_ = True
			   elif item == 'AT':
			      self.showAt_ = True
			   elif item == 'Server':
			      self.showSrv_ = True
			   elif item == 'Bemused':
			      self.showBm_ = True
			      
		    elif line.startswith('AutoReconnectAT='):
		        self.autoReconn_ = (line == 'AutoReconnectAT=1')
		    elif line.startswith('OverrideDevice='):
		        self.device_ = line[15:]
		    elif line.startswith('WebInterface='):
		        self.runWeb_    = True
		        self.webParams_ = line[13:]
                    elif line.startswith('CfgDirs='):
		        self.cfgDirs=line[8:].split(';')
                    elif line.startswith('UpdateTimeout='):
		        self.updateTmout_=int(line[14:])
                    elif line.startswith('DeviceBrowserTimeout='):
		        tmt=line[21:]
    	    	        try:
    	    		    self.browseTmout_=int(tmt)
    	    	        except ValueError:
			    self.browseTmout_=-1

			if self.browseTmout_ <= 0:
			    self.browseTmout_=-1
                    elif line.startswith('JavaDir='):
		        self.javaDir_=line[8:]
                    elif line.startswith('CheckJavaUpdate=true'):
		        self.checkJavaUpdate_=True
		    
	    	f.close()
		self.entry.set_text(self.lastCfgFile)
		
		# Try to search again
		if self.javaDir_ == '':
		    self.javaDir_ = getJ2MEPath()
		
	# device browser related part
       	cfg  = os.environ.get("HOME")+os.sep+'.anyRemote' + os.sep + 'anyremote-peers.conf'
	
    	if os.path.exists(cfg) :
	    f=open(cfg, 'r')
	    if f:
	        for line in f:
		    line = line.replace('\n','')
		    os.path.exists(cfg)
		    
		    if line.startswith('Device='):
		        deviceData=line[7:].split(',')
			
			v1 = deviceData[0]
			v2 = deviceData[1]
			v3 = deviceData[2]
			v4 = deviceData[3]
			
			bt_devices.append([v1,v2,v3,v4,''])
	    	f.close()
	    
    def setAutoStartup(self, wm, isAuto):
        if wm == 'KDE':
	    autopath = os.environ.get("HOME")+os.sep+'.kde'+os.sep+'Autostart'+os.sep+'ganyremote'
	    if isAuto:
	    	if not os.path.exists(autopath):
		    os.system('ln -s `which ganyremote` '+autopath)
	    else:
	    	os.system('rm -f '+autopath)
	
        elif wm == 'Gnome':		# will work for gnome > 2.14 ?
	    cfgpath  = os.environ.get("HOME")+os.sep+'.config'
	    autopath = cfgpath+os.sep+'autostart'
	    autorun  = autopath+os.sep+'ganyremote.desktop'

    	    if not os.path.isdir(cfgpath):
        	os.mkdir(cfgpath)
    	    if not os.path.isdir(autopath):
        	os.mkdir(autopath)
	    if isAuto:
    	        if not os.path.isfile(autorun):
	            f=open(autorun, 'w')
	            if f:
 	                f.write('[Desktop Entry]\n')
 	                f.write('Encoding=UTF-8\n')
 	                f.write('Name=gAnyRemote\n')
 	                f.write('Exec=ganyremote\n')
 	                f.write('Icon=ganyremote\n')
 	                f.write('Type=Application\n')
 	                f.write('Comment=Remote control through bluetooth or IR connection\n')
 	                f.write('GenericName=Remote control through bluetoth or IR connection\n')
 	                f.write('Categories=Utility;\n')
		        f.close()
            else:
	        os.system('rm -f '+autorun)
		

    def populateCfgFiles(self):
        global cfgFileReaderFlag
	try:
	    if cfgFileReaderFlag:
	        return
	except NameError:
	    pass
	    
	cfgFileReader = CfgFileReader(self.cfgDirs, self.showAll_,self.showApps_,self.showCustom_,self.showExamples_,self.showAt_,self.showSrv_,self.showBm_)
	cfgFileReader.start()

    ##################################################################################
    #
    # Config Window related part
    #
    ##################################################################################
    
    def showBrowser(self, action):
	showBrowserWin()

    def showChkCfg(self, action):
	showChkCfgWin(self.javaDir_)

    def showConfAction(self, action):
	    self.showConfDialog()

    def showConfDialog(self):
	self.dirsChanged = False
	
        self.config = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.config.set_title(_('Properties'))
 	self.config.set_size_request(700, 400)
	self.config.connect("destroy", self.closeCfg)
       
	vbox = gtk.VBox(False, 0)
        self.config.add(vbox)
        vbox.show()

        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        hbox.show()

        label = gtk.Label(_('Choose directories with configuration files and add them to the list'))
        hbox.pack_start(label, True, True, 0)
        label.show()
	
	hsep = gtk.HSeparator()
        vbox.add(hsep)
	vbox.set_child_packing(hsep, 0, 1, 0, gtk.PACK_START)
        hsep.show()
	
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 1, 1, 0, gtk.PACK_START)
        hbox.show()
	
        scrolledwin = gtk.ScrolledWindow()
        scrolledwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        hbox.add(scrolledwin)
	hbox.set_child_packing(scrolledwin, 1, 1, 0, gtk.PACK_START)
	scrolledwin.show()
	
        self.cfg_liststore = gtk.ListStore(str)
        self.cfg_treeview  = gtk.TreeView(self.cfg_liststore)
       
        self.column_dir = gtk.TreeViewColumn(_('Directories'))
	self.cfg_treeview.append_column(self.column_dir)
        self.cfg_cell = gtk.CellRendererText()
        self.column_dir.pack_start(self.cfg_cell, True)
        self.column_dir.set_attributes(self.cfg_cell, text=0)
        self.column_dir.set_sort_column_id(0)
        scrolledwin.add(self.cfg_treeview)
	self.cfg_treeview.show()
	
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        hbox.show()
	
        self.btnAdd = gtk.Button(label=AR_ADD)
        self.btnAdd.connect("clicked", self.addToCfgDirList)
        hbox.pack_start(self.btnAdd, False, False, 0)
	self.btnAdd.show()

        btn = gtk.Button(label=AR_DELETE)
        btn.connect("clicked", self.deleteFromCfgDirList)
        hbox.pack_start(btn, False, False, 0)
	btn.show()

        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        hbox.show()

	vbox1 = gtk.VBox(False, 0)
        hbox.add(vbox1)
        vbox1.show()

        label = gtk.Label(_('Show in list : '))
        vbox1.pack_start(label, False, False, 0)
	#label.set_justify(gtk.JUSTIFY_LEFT)
	label.set_alignment(0,0)
        label.show()

	self.showAll = gtk.CheckButton(AR_ALL)
        vbox1.pack_end(self.showAll, True, True, 0)
        self.showAll.show()
	
	vbox1 = gtk.VBox(False, 0)
        hbox.add(vbox1)
        vbox1.show()
	
	self.showApps = gtk.CheckButton(_('Applications'))
        vbox1.pack_start(self.showApps, True, True, 0)
        self.showApps.show()

	self.showAt = gtk.CheckButton(_('AT-mode'))
        vbox1.pack_end(self.showAt, True, True, 0)
        self.showAt.show()
	
	vbox1 = gtk.VBox(False, 0)
        hbox.add(vbox1)
        vbox1.show()

	self.showCustom = gtk.CheckButton(_('Custom Made'))
        vbox1.pack_start(self.showCustom, True, True, 0)
        self.showCustom.show()

	self.showSrv = gtk.CheckButton(_('Server-mode'))
        vbox1.pack_end(self.showSrv, True, True, 0)
        self.showSrv.show()
	
	vbox1 = gtk.VBox(False, 0)
        hbox.add(vbox1)
        vbox1.show()

	self.showExamples = gtk.CheckButton(_('Examples'))
        vbox1.pack_start(self.showExamples, True, True, 0)
        self.showExamples.show()
	
	self.showBm = gtk.CheckButton(_('Bemused-emulation'))
        vbox1.pack_end(self.showBm, True, True, 0)
        self.showBm.show()
	
	self.showAll.set_active(self.showAll_)
	self.setFilters()
	
	if not self.showAll_:
	    self.showApps.set_active(self.showApps_)
	    self.showCustom.set_active(self.showCustom_)
	    self.showExamples.set_active(self.showExamples_)
	    self.showAt.set_active(self.showAt_)
	    self.showSrv.set_active(self.showSrv_)
	    self.showBm.set_active(self.showBm_)
	
	self.showAll.connect     ('toggled', self.showAllAction)
	self.showApps.connect    ('toggled', self.filterChangedAction)
	self.showCustom.connect  ('toggled', self.filterChangedAction)
	self.showExamples.connect('toggled', self.filterChangedAction)
	self.showAt.connect      ('toggled', self.filterChangedAction)
	self.showSrv.connect     ('toggled', self.filterChangedAction)
	self.showBm.connect      ('toggled', self.filterChangedAction)
    
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        hbox.show()
	
        self.updLabel = gtk.Label(_('Update application list every'))
        hbox.pack_start(self.updLabel, True, True, 0)	
        self.updLabel.show()

        self.updateTmout = gtk.Entry()
        self.updateTmout.set_max_length(6)
	self.updateTmout.set_width_chars(2)
        hbox.pack_start(self.updateTmout, True, True, 0)
	self.updateTmout.connect('changed', self.tmoutChangedAction)
        self.updateTmout.show()
	tt = gtk.Tooltips()
	tt.set_tip(self.updateTmout,_('Empty field means no update'))
	
	tm = ''
	if self.updateTmout_ > 0:
	    tm = "%s" % (self.updateTmout_)
	self.updateTmout.set_text(tm)
	
        label = gtk.Label(_('sec.'))
        hbox.pack_start(label, True, True, 0)
        label.show()
	
        separator = gtk.VSeparator()
        hbox.pack_start(separator, False, True, 0)
        separator.show()

        label = gtk.Label(_('Auto startup with'))
        hbox.pack_start(label, True, True, 0)
        label.show()
	
	self.autorunGnome = gtk.CheckButton(_('Gnome session'))
        hbox.pack_start(self.autorunGnome, True, True, 0)
	self.autorunGnome.set_active(os.path.exists(os.environ.get("HOME")+os.sep+'.config'+os.sep+'autostart'+os.sep+'ganyremote.desktop'))
        self.autorunGnome.show()
	
	self.autorunKDE = gtk.CheckButton(_('KDE session'))
        hbox.pack_start(self.autorunKDE, True, True, 0)
	self.autorunKDE.set_active(os.path.exists(os.environ.get("HOME")+os.sep+'.kde'+os.sep+'Autostart'+os.sep+'ganyremote'))
        self.autorunKDE.show()

        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
        hbox.show()
	
        label = gtk.Label(_('Override \"Device=\" parameter with')+'  ')
        hbox.pack_start(label, 0, True, 0)
        label.show()
	
        self.device = gtk.Entry()
        self.device.set_max_length(512)
        hbox.pack_start(self.device, True, True, 0)
	self.device.connect('changed', self.deviceChangedAction)
        self.device.show()
	
        separator = gtk.VSeparator()
        hbox.pack_start(separator, False, True, 0)
        separator.show()
 
	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
        hbox.show()

 	self.autoReconn = gtk.CheckButton(_('Auto reconnect in AT mode'))
        hbox.pack_start(self.autoReconn, True, True, 0)
	self.autoReconn.set_active(self.autoReconn_)
        self.autoReconn.show()

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
        hbox.show()

	self.runWeb = gtk.CheckButton(_('Run web interface with parameters'))
        hbox.pack_start(self.runWeb, 0, True, 0)
	self.runWeb.set_active(self.runWeb_)
        self.runWeb.connect('toggled', self.webToggledAction)
        self.runWeb.show()

        self.webParams1 = gtk.Entry()
        self.webParams1.set_max_length(64)
        hbox.pack_start(self.webParams1, True, True, 0)
        self.webParams1.set_editable(False)
        self.webParams1.show()

        self.webParams = gtk.Entry()
        self.webParams.set_max_length(256)
        hbox.pack_start(self.webParams, True, True, 0)
        self.webParams.show()
	
	self.webParams.set_text(self.webParams_)
	self.device.set_text(self.device_)
	
	self.setWebParamsActive(self.runWeb_)
	
	self.runWeb.set_active(self.runWeb_ and self.device_.startswith('socket:'))

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        hbox.show()

        self.jLabel = gtk.Label(_('Upload java client from '))
        hbox.pack_start(self.jLabel, False, False, 0)	
        self.jLabel.show()
	
        self.javaDir = gtk.Entry()
        hbox.pack_start(self.javaDir, True, True, 0)
        self.javaDir.show()

        self.chooseJava = gtk.Button(label=AR_CHOOSE)
        self.chooseJava.connect("clicked", self.chooseJavaDir)
        hbox.pack_start(self.chooseJava, False, False, 0)
	self.chooseJava.show()

	################
        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        hbox.show()
	
 	self.checkJava = gtk.CheckButton(_('Check java client updates at start'))
        hbox.pack_start(self.checkJava, True, True, 0)
	self.checkJava.set_active(self.checkJavaUpdate_)
        self.checkJava.show()

        self.checkJavaNow = gtk.Button(label=_('Check java client updates'))
        self.checkJavaNow.connect("clicked", self.checkJavaWeb)
        hbox.pack_start(self.checkJavaNow, False, False, 0)
	self.checkJavaNow.show()

	
	################
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()

        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, False, True, 0, gtk.PACK_START)
        hbox.show()

        self.brLabel = gtk.Label(' '+_('Run device browser with timeout')+'  ')
        hbox.pack_start(self.brLabel, False, True, 0)
        self.brLabel.show()
	self.brLabel.set_sensitive((self.browseTmout_ > 0))
	
        self.browseTmout = gtk.Entry()
        self.browseTmout.set_max_length(5)
        self.browseTmout.set_width_chars(3)
        hbox.pack_start(self.browseTmout, False, True, 0)
	self.browseTmout.connect('changed', self.dbrowseChangedAction)
        self.browseTmout.show()
	tt = gtk.Tooltips()
	tt.set_tip(self.browseTmout,_('Empty field means no update. Beware: Java client could fail to connect to anyRemote when browsing is in process'))
	
	tm = ''
	if self.browseTmout_ > 0:
	    tm = "%s" % (self.browseTmout_)
	self.browseTmout.set_text(tm)

        label = gtk.Label('  ')
        hbox.pack_start(label, True, True, 0)
        label.show()

        self.downloadJavaNow = gtk.Button(label=_('Download java client from Web'))
        self.downloadJavaNow.connect("clicked", self.uploadJavaWeb)
        hbox.pack_start(self.downloadJavaNow, False, False, 0)
	self.downloadJavaNow.show()
	tt = gtk.Tooltips()
	tt.set_tip(self.downloadJavaNow,_('Files will be saved to $HOME/.anyRemote'))

	################
        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        separator.show()

        hbox = gtk.HBox(False, 0)
        vbox.add(hbox)
	vbox.set_child_packing(hbox, 0, 1, 0, gtk.PACK_START)
        hbox.show()
	
        btn = gtk.Button(label=AR_OK)
	addIconToButton(btn,gtk.STOCK_OK)
        btn.connect("clicked", self.okCloseCfg)
        hbox.pack_end(btn, False, False, 0)
	btn.show()
 
        btn = gtk.Button(label=AR_CANCEL)
	addIconToButton(btn,gtk.STOCK_CANCEL)
        btn.connect("clicked", self.closeCfg)
        hbox.pack_end(btn, False, False, 0)
	btn.show()
	
	for d in self.cfgDirs:
	    if d != '':
	        self.cfg_liststore.append([d])
	
	self.javaDir.set_text(self.javaDir_)  
	 
	self.config.show()
	
	self.showConfItem.set_sensitive(False)
		
    def addToCfgDirList(self, w):
	self.btnAdd.set_sensitive(False)
	
	dialog = gtk.FileChooserDialog(AR_SEL_DIR,None,gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
	         	(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
 	dialog.set_default_response(gtk.RESPONSE_OK)
        response = dialog.run()
	
        if response == gtk.RESPONSE_OK:
            self.dirsChanged = True
    	
	    newPath = dialog.get_filename()

	    add = True
        
	    treeiter = self.cfg_liststore.get_iter_first()
	    while treeiter != None:
	        value = self.cfg_liststore.get_value(treeiter, 0)
	        if value == newPath:
	            add = False
		    break
	        treeiter = self.cfg_liststore.iter_next(treeiter)
	
	    if add:
	        self.cfg_liststore.append([newPath])
	    
	dialog.destroy()
	self.btnAdd.set_sensitive(True)

    def deleteFromCfgDirList(self, w):
	(model, titer) = self.cfg_treeview.get_selection().get_selected()
	if titer:
           treeiter = self.cfg_liststore.remove(titer)
	self.dirsChanged = True

    def chooseJavaDir(self, w):
	self.chooseJava.set_sensitive(False)
		
	dialog = gtk.FileChooserDialog(AR_SEL_DIR,None,gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
	                        (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
 	dialog.set_default_response(gtk.RESPONSE_OK)
        response = dialog.run()
	
        if response == gtk.RESPONSE_OK:
            self.javaDir.set_text(dialog.get_filename())
	    
	dialog.destroy()
	
	self.chooseJava.set_sensitive(True)

    def closeCfg(self, w):
	self.config.destroy()
	self.showConfItem.set_sensitive(True)

    def okCloseCfg(self, w):

	self.setAutoStartup("KDE",     self.autorunKDE.get_active())
	self.setAutoStartup("Gnome", self.autorunGnome.get_active())
	
	self.showApps_     = self.showApps.get_active()
	self.showCustom_   = self.showCustom.get_active()
	self.showExamples_ = self.showExamples.get_active()
	self.showAll_      = self.showAll.get_active()
	self.showAt_       = self.showAt.get_active()
	self.showSrv_      = self.showSrv.get_active()
	self.showBm_       = self.showBm.get_active()

	self.autoReconn_   = self.autoReconn.get_active()
	self.runWeb_       = self.runWeb.get_active()
	self.webParams_    = self.webParams.get_text().strip()
	self.device_       = self.device.get_text().strip()
	self.javaDir_      = self.javaDir.get_text().strip()
	self.checkJavaUpdate_ = self.checkJava.get_active()
	
	tm = self.updateTmout.get_text().strip()
	if tm == '':
	    tm = '-1'
	if self.updateTmout_ != int(tm):
	    self.updateTmout_ = int(tm)
	    if self.updateTmout_ < 0:
	        self.updateTmout_ = -1
	    stopUpdater()
	    startUpdater(self.updateTmout_)
	
	tm = self.browseTmout.get_text().strip()
	if tm == '':
	    tm = '-1'
	if self.browseTmout_ != int(tm):
	    self.browseTmout_ = int(tm)
	    if self.browseTmout_ <= 0:
	        self.browseTmout_ = -1
	    stopBtComm()
	    startBtComm(self.browseTmout_, self.javaDir_)

        self.cfgDirs = []
        
	treeiter     = self.cfg_liststore.get_iter_first()
	while treeiter != None:
	    value = self.cfg_liststore.get_value(treeiter, 0)
	    self.cfgDirs.append(value)
	    treeiter = self.cfg_liststore.iter_next(treeiter)
	       
	proceed = True
	if self.cfgDirs == []:
	    
	    dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK_CANCEL,
	                              _('There is no item in the list !\ngAnyRemote will not be able to manage any software !'))
	    ret = dialog.run()
	    if ret == gtk.RESPONSE_CANCEL:
	        proceed = False
		
	    dialog.destroy()

	if proceed:
	    self.saveConfig() 
	    self.config.destroy()
	
	    self.showConfItem.set_sensitive(True)
	
	    if self.dirsChanged == True:
	        self.populateCfgFiles()
	        self.dirsChanged = False
	    
    def dbrowseChangedAction(self, editable):  
	self.browseTmout_ = self.browseTmout.get_text().strip()
	if self.browseTmout_ == '':
	     self.brLabel.set_sensitive(False)
	else:     
	     self.brLabel.set_sensitive((self.browseTmout_ > 0))

    def tmoutChangedAction(self, editable):  
	self.updateTmout_ = self.updateTmout.get_text().strip()
	if self.updateTmout_ == '':
	     self.updLabel.set_sensitive(False)
	else:     
	     self.updLabel.set_sensitive((self.updateTmout_ > 0))
	    
    def deviceChangedAction(self, editable):
	self.device_ = self.device.get_text().strip()
	self.setWebParamsActiveReset()
	
    def webToggledAction(self, w):
        active = self.runWeb.get_active()
	if active:
	    isInst = isInstalled('anyremote2html')
	    if isInst == 'NOK':
	    	dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK,
                     _('anyremote2html is not installed !'))
	        dialog.run()
	        dialog.destroy()
	    else:
		if self.device.get_text().startswith('socket:'):
		    self.webParams1.set_text(' -a '+self.device.get_text()[7:])
		else:
	            self.device.set_text('socket:5000')
	            self.webParams1.set_text(' -a 5000')
	            self.webParams.set_text(' -w 5550')
		    
	self.webParams1.set_sensitive(active)
	self.webParams.set_sensitive(active)

    def filterChangedAction(self, w):
    	self.dirsChanged = True

    def showAllAction(self, w):
    	self.dirsChanged = True
	self.setFilters()
	
    def setFilters(self):
	if self.showAll.get_active():
    	    self.showApps.set_active(False)
    	    self.showCustom.set_active(False)
    	    self.showExamples.set_active(False)
    	    self.showAt.set_active(False)
    	    self.showSrv.set_active(False)
    	    self.showBm.set_active(False)
	    
    	    self.showApps.set_sensitive(False)
    	    self.showCustom.set_sensitive(False)
    	    self.showExamples.set_sensitive(False)
    	    self.showAt.set_sensitive(False)
    	    self.showSrv.set_sensitive(False)
    	    self.showBm.set_sensitive(False)
        else:
    	    self.showApps.set_sensitive(True)
    	    self.showCustom.set_sensitive(True)
    	    self.showExamples.set_sensitive(True)
    	    self.showAt.set_sensitive(True)
    	    self.showSrv.set_sensitive(True)
    	    self.showBm.set_sensitive(True)
	
    def setWebParamsActiveReset(self):
	
	active = (self.runWeb.get_active() and self.device.get_text().startswith('socket:'))
	self.setWebParamsActive(active)
	
    def setWebParamsActive(self, active):
    
	self.webParams.set_sensitive(active)

	if active:
	    self.webParams1.set_text(' -a '+self.device.get_text()[7:])
	else:
            self.webParams1.set_text('')

    def uploadJavaWeb(self,w):
        global debug,jup

        try:
            if jup != None:
	       if debug: print 'Uploading already active. Skip request.'
	       return
        except NameError:
            pass
	    
        jup = JCUploader()
        jup.start()
	
	jdir = os.environ.get("HOME")+os.sep+'.anyRemote'
	if self.javaDir_ != jdir:
	    ret = yesno(self,_('Would You like to change upload java client path ?'))
	    if ret == gtk.RESPONSE_YES:
	        self.javaDir_ = os.environ.get("HOME")+os.sep+'.anyRemote'
		try:
		    self.javaDir.set_text(self.javaDir_)
		except AttributeError:
		    # OK. config window was not yet shown
		    pass

    def checkJavaWeb(self,w):
	jv = JCVerifier(True)
	jv.start()

    def updateAvail(self):
        ret = yesno(self,_("New version of java client is available. Would You like to download it ?"))
	if ret == gtk.RESPONSE_YES:
	    self.uploadJavaWeb(self) 
	    
    ##################################################################################
    #
    # Status related function
    #
    ##################################################################################

    def setStatustext(self,text):
	self.sBar.pop(self.cid)
	self.sBar.push(self.cid,'  ' + text)
	
    def setStatusStopped(self):
    
        global debug
	if debug: print 'setStatusStopped'

    	self.runBtn.set_sensitive(True)
	self.runItem.set_sensitive(True)
	self.stopBtn.set_sensitive(False)
	self.stopItem.set_sensitive(False)

        self.setIcon(self.pixbufOff)
	self.setStatustext(AR_STOPPED)
	if self.tray != None: self.tray.set_tooltip(AR_STOPPED)

    def setStatusDisconnected(self):
    
        global debug
	if debug: print 'setStatusDisconnected'

    	self.runBtn.set_sensitive(False)
	self.runItem.set_sensitive(False)
	self.stopBtn.set_sensitive(True)
	self.stopItem.set_sensitive(True)

        self.setIcon(self.pixbufRun)
	self.setStatustext(AR_DISCONN)
	if self.tray != None: self.tray.set_tooltip(AR_DISCONN)

    def setStatusConnected(self):
    
        global debug
	if debug: print 'setStatusConnected'
	
        self.setIcon(self.pixbufOn)
	
	msg = AR_CONNECT
	if self.runWeb_:
	    msg = AR_CONNECT2
	
	self.setStatustext(msg)
	
	if self.tray != None: self.tray.set_tooltip(msg)
	
    def translateMsg(self, data):
    
    	global debug
	if debug: print 'translateMsg  ' + data

	if data == '':

	   return
	   
	elif data == 'Exiting':
	
	   self.setStatusStopped()
	   return

	elif data == 'Connected':

	   self.setStatusConnected()
	   return

	elif data == 'Disconnected':

	   self.setStatusDisconnected()
	   return
	
	if data == '(Init)':

	   msg = 'anyRemote initialized'

	else:
	
	   # Just key press 
	   self.setIcon(gui.pixbufFlash)
	   self.blinkTimer = gobject.timeout_add(200, self.resetTrayIcon)	   
	   
	   if debug:
	       msg = data
	   else:
	       return
	
	self.setStatustext(msg)
	
    def resetTrayIcon(self):
    
        self.setIcon(gui.pixbufOn)
	return False
   		
    def checkInputQueue(self):
        global guiQueue
	
	while True:
	    try:
	        data = guiQueue.get(False)
	    
	        if data[0] == 'MSG_INF':
	            message(data[1],gtk.MESSAGE_INFO)
                elif data[0] == 'MSG_ERR':
	            message(data[1],gtk.MESSAGE_INFO)
                elif data[0] == 'UPDATE_AVAIL':
	            self.updateAvail()
                elif data[0] == 'PBAR_START':
	            self.startProgressBar(data[1],data[2])
                elif data[0] == 'PBAR_STOP':
	            self.stopProgressBar()
                elif data[0] == 'PBAR_WRITE':
	            self.writeProgressBar(data[1])
                elif data[0] == 'SET_STATUS':
	            if data[1] == 'S':
		        self.setStatusStopped()
	            elif data[1] == 'D':
		        self.setStatusDisconnected()
	            elif data[1] == 'C':
		        self.setStatusConnected()
                elif data[0] == 'LOADED':
	            self.setStatustext(str(data[1]))
                elif data[0] == 'UPDATE_LIST':
		    treeiter = liststore.get_iter_from_string(data[1])
		    liststore.set_value(treeiter, 5, data[2])    
                elif data[0] == 'GET_DATA':
    	            self.translateMsg(data[1])
 	    
	    except Queue.Empty:
                break
	    
	return True

    def startProgressBar(self,m,t):
        global pbar
        pbar = PBar(m,t)
	
    def stopProgressBar(self):
        global pbar
        try:
            pbar.stop()
        except AttributeError, NameError:
            pass

    def writeProgressBar(self,m):
        global pbar
        try:
            pbar.set_text(m)
        except AttributeError, NameError:
            pass
	
    ##################################################################################
    #
    # Button and menu handlers
    #
    ##################################################################################

    def aboutAction(self, action):
    
        try:
            dialog = gtk.AboutDialog()
            dialog.set_name("gAnyRemote")
            dialog.set_copyright('Copyright 2007,2008,2009 Mikhail Fedotov')
            dialog.set_website("http://anyremote.sf.net/")
            dialog.connect ("response", lambda d, r: d.destroy())
            dialog.show()
        except AttributeError:
    	    infoMessage("gAnyRemote\nCopyright 2007,2008,2009 Mikhail Fedotov\nhttp://anyremote.sf.net/")


    def helpAction(self, action):

	# open web browser on docs page if found ?
	app = 'firefox'
	isInst = isInstalled(app)
	if isInst == 'NOK':
	    app = 'konqueror'
	    isInst = isInstalled(app)
	    
	    if isInst == 'NOK':
	        errorMessage(_('Can not find browser to show help !'))
		return
		
	docpath = ''
	if os.path.isdir('/usr/share/doc/anyremote/doc-html'):
	    docpath = '/usr/share/doc/anyremote/doc-html'
	elif os.path.isdir('/usr/local/share/doc/anyremote/doc-html'):
	    docpath = '/usr/local/share/doc/anyremote/doc-html'
	elif os.path.isdir('/usr/share/anyremote/doc-html'):
	    docpath = '/usr/share/anyremote/doc-html'
	elif os.path.isdir('/usr/local/share/anyremote/doc-html'):
	    docpath = '/usr/local/share/anyremote/doc-html'
	# quick fix for ubuntu
	elif os.path.isdir('/usr/share/doc/anyremote/html'):
	    docpath = '/usr/share/doc/anyremote/html'
	else:    
	    errorMessage(_('Can not find documentation !'))
	    return
	
	cmd = app + ' ' + docpath + os.sep + 'g-shots.html &'
	os.system(cmd)
	    	
    def trayPressAction(self, *args):
        if self.get_property('visible'):
            self.hide()
        else:
	    self.show_all()

    def showWindowAction(self, *args):
        self.trayPressAction(*args)

    def quitAction(self, *args):
        try:
            gobject.source_remove(self.inQueueTimer)
        except AttributeError, NameError:
            print 'Exception: gobject.source_remove(gui.inQueueTimer)'
 
        self.quit()

    def resizeEvent(self, *args):
        (w,h)=self.get_size()
	try:
	    self.detailsRenderer.set_property('wrap-width', w-50)
	except TypeError, AttributeError:
	    pass

    def rightClickAction(self, icon, event_button, event_time):
        menu = gtk.Menu()

        item = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
	item.connect('activate', self.aboutAction)
        menu.append(item)
	
	item = gtk.ImageMenuItem(gtk.STOCK_EXECUTE)
	item.connect('activate', self.runPressed)
        menu.append(item)

        item = gtk.ImageMenuItem(gtk.STOCK_STOP)
	item.connect('activate', self.stopPressed)
        menu.append(item)
	
	title = _('Restore')
        if self.get_property('visible'):
            title = _('Minimize')
        self.mainWinItem = gtk.MenuItem(title)
	self.mainWinItem.connect('activate', self.showWindowAction)
        menu.append(self.mainWinItem)

        item = gtk.ImageMenuItem(gtk.STOCK_QUIT)
	item.connect('activate', self.quitAction)
        menu.append(item)
	menu.show_all()

        menu.popup(None, None,
            gtk.status_icon_position_menu, event_button,
            event_time, icon)
	
    def runPressed(self, widget):
	global port, debug
	
	# to store last used cfg.file
        entry_text = self.entry.get_text()
	self.saveConfig()
	
	self.setStatusDisconnected()
	
	startAnyRemote(self.entry.get_text(),self.runWeb_)	

    def stopPressed(self, widget):
	global debug
	
	if debug: print 'Stop anyRemote'
	
	# To avoid socket.error: (98, 'Address already in use') 
	# it needs to close client socket first
    	killAnyRemote()
			
	self.setStatusStopped()

    def rescanPressed(self, widget):
	self.populateCfgFiles()

    def openEditor(self, widget):
        if self.lastCfgFile:
	    e = cfgEditor(self.lastCfgFile)
	
    def execCmd(self, w):
    	global cmdToSend
        print 'Add to queue ' + self.cmd.get_text()
        cmdToSend = self.cmd.get_text() 
	
	
    ##################################################################################
    #
    # Wizard window
    #
    ##################################################################################
    
    def showWizard(self):
	dialog = gtk.MessageDialog(None,
		     gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK,
                     _('This is the first time gAnyRemote runs.\nPlease specify directories with anyRemote configuration files.'))

	dialog.run()
	dialog.destroy()
	
	self.showConfDialog()
	
	if getJ2MEPath() == '': 
	    ret  = yesno(self,_('Would You like to download java client from Web ?'))
	    if ret == gtk.RESPONSE_YES:
	        self.uploadJavaWeb(self)
	
   
    ##################################################################################
    #
    # Main window creation
    #
    ##################################################################################

    def createMenus(self, vbox):
        global usepybluez
	
        self.menubar = gtk.MenuBar()
        vbox.pack_start(self.menubar, expand=False)

        topmenuitem = gtk.MenuItem(AR_FILE)
        self.menubar.add(topmenuitem)
	
        menu = gtk.Menu()
	topmenuitem.set_submenu(menu)

        try:
	    stock_edit = gtk.STOCK_EDIT
            menuitem = gtk.ImageMenuItem(stock_edit)
        except AttributeError:
    	    menuitem = iconMenuItem(_('Edit'), gtk.STOCK_JUSTIFY_LEFT)

        menu.add(menuitem)
	menuitem.connect('activate', self.openEditor)
        
        self.runItem = iconMenuItem(_('Start'), gtk.STOCK_EXECUTE)
	
	menu.add(self.runItem)
	self.runItem.connect('activate', self.runPressed)

        self.stopItem = gtk.ImageMenuItem(gtk.STOCK_STOP)
        menu.add(self.stopItem)
	self.stopItem.connect('activate', self.stopPressed)

        if self.tray != None:
	    menuitem = iconMenuItem(_('Close Window'), gtk.STOCK_CLOSE)
	    menu.add(menuitem)
	    menuitem.connect('activate', self.hideWindow)

        menuitem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
        menu.add(menuitem)
	menuitem.connect('activate', self.quitAction)

        topmenuitem = gtk.MenuItem(_('Setup'))
        self.menubar.add(topmenuitem)
	
        menu = gtk.Menu()
	topmenuitem.set_submenu(menu)

        self.dbrowserItem = iconMenuItem(_('Device Browser'), gtk.STOCK_FIND)
        menu.add(self.dbrowserItem)
	self.dbrowserItem.connect('activate', self.showBrowser)
	if not usepybluez:
	    self.dbrowserItem.set_sensitive(False)
        self.dbrowserItem.show()
       
       
        self.showConfItem = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
        menu.add(self.showConfItem)
	self.showConfItem.connect('activate', self.showConfAction)
	
        self.chkCfg = iconMenuItem(_('Check Configuration'),gtk.STOCK_PROPERTIES)
        menu.add(self.chkCfg)
	self.chkCfg.connect('activate', self.showChkCfg)
        self.chkCfg.show()
	
        menuitem = gtk.ImageMenuItem(gtk.STOCK_SAVE)
        menu.add(menuitem)
	menuitem.connect('activate', self.saveConfigAction)
	
        topmenuitem = gtk.MenuItem(_('Help'))
        self.menubar.add(topmenuitem)
	
        menu = gtk.Menu()
	topmenuitem.set_submenu(menu)

        try:
	    stock_about = gtk.STOCK_ABOUT
            menuitem = gtk.ImageMenuItem(stock_about)
        except AttributeError:
   	    menuitem = iconMenuItem(_('About'),gtk.STOCK_DIALOG_INFO)
            
        menu.add(menuitem)
	menuitem.connect('activate', self.aboutAction)

        menuitem = gtk.ImageMenuItem(gtk.STOCK_HELP)
        menu.add(menuitem)
	menuitem.connect('activate', self.helpAction)

    def commandRun(self, w, event):
        keyname = gtk.gdk.keyval_name(event.keyval)
        if keyname == 'KP_Enter' or keyname == 'Return':
            self.execCmd(self.cmd)
            return True
        return False

    def rowActivateAction(self, treeview, path, view_column):
	treeiter = liststore.get_iter(path)
	self.lastCfgFile = liststore.get_value(treeiter, 4)
	self.entry.set_text(self.lastCfgFile)
	self.useType = liststore.get_value(treeiter, 6)
	self.runPressed(self.runBtn)

    def rowSelectAction(self, treeview):
	selection = treeview.get_selection()
	(model, treeiter) = selection.get_selected()
	self.lastCfgFile = liststore.get_value(treeiter, 4)
	self.entry.set_text(self.lastCfgFile)
	self.useType = liststore.get_value(treeiter, 6)
        
        desc = liststore.get_value(treeiter, 8)
        self.detailsStore.set_value(self.detailsData, 0, desc.replace('\\n','\n'))

    ##################################################################################
    #
    # 
    #
    ##################################################################################

    def openFDialog(self, w, entry):
	self.fdialog = gtk.FileChooserDialog(_('File selection'),None,gtk.FILE_CHOOSER_ACTION_OPEN,
	                        (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
	self.fdialog.set_filename(entry.get_text())
 	self.fdialog.set_default_response(gtk.RESPONSE_OK)
        response = self.fdialog.run()
	
        if response == gtk.RESPONSE_OK:
            self.entry.set_text(self.fdialog.get_filename())
	self.fdialog.destroy()
 
    def hideWindow2(self,w,p):
        self.hideWindow(w)
	return True
	
    def hideWindow(self,w):
    	self.hide()
		    
    def quit(self):
        print 'Exiting...'
	
	stopBtComm()
	stopJCUploader()
	stopPBar()
	stopUpdater()
	stopFrontend();
	self.saveConfig()
	gtk.main_quit()

    def setIcon(self, pixbuf):
	self.curPixbuf = pixbuf
	if self.tray != None: self.tray.set_from_pixbuf(self.curPixbuf)

##################################################################################
#
# Utilities functions
#
##################################################################################

def getHttp(hname,fname,tmp):
    global debug

    try:
        conn = httplib.HTTPConnection(hname,80,timeout=10)
    # old pythons (<2.6)
    except TypeError:
        conn = httplib.HTTPConnection(hname)

    try:
        conn.request("GET", fname)
    except Exception: 
        errorMessage(_('Can not establish the connection !'))
        return False
    
    r = conn.getresponse()
    
    if debug: print fname, r.status, r.reason,r.getheader('content-length')
    
    ret = True
    
    if r.status == httplib.OK:
        if debug: print 'download',fname
	
	try:
            data = r.read()
	except Exception:
	    errorMessage(_('Download failed !'))
	    return False

	f=open(os.environ.get("HOME")+os.sep+'.anyRemote'+fname+tmp, 'w')
	if f:
 	    f.write(data)
	    f.close()
    else:
        if tmp == "":
            errorMessage(_('Can not download ')+hname+fname)
	    ret = False
	    
	
    conn.close()
    
    return ret
    
def uploadJavaWebGui(fname, strip=False):
 
    writePBar(_('Downloading')+' '+fname)
    
    if not getHttp("anyremote.sourceforge.net",os.sep+fname,""):
        stopPBar()
	return False
    
    if strip:
        f1 = os.environ.get("HOME")+os.sep+'.anyRemote'+os.sep+fname
        os.system('rm -f '+f1+'.tmp; cat '+f1+'|sed \'s/MIDlet-Jar-URL: http:\/\/anyremote.sourceforge.net\//MIDlet-Jar-URL: /\' > '+f1+'.tmp;mv '+f1+'.tmp '+f1);
    
    return True

def getJavaClientVersion(fname):
    global debug
    if debug: print 'Check version of Java Client from file',fname
    return getResult('cat '+fname+'|grep MIDlet-Version|tr -d \" \"|cut -f 2 -d \":\"','main')

def checkJavaClientUpdate():
    global debug
    
    if not getHttp("anyremote.sourceforge.net",os.sep+"anyRemote-16.jad",".check"):
        return ""
	
    newver = getJavaClientVersion(os.environ.get("HOME")+os.sep+'.anyRemote'+os.sep+'anyRemote-16.jad.check')
    oldver = getJavaClientVersion(getJ2MEPath()+os.sep+'anyRemote-16.jad')
    
    if debug: print 'compare new=',newver,' and old=',oldver
    
    nvers = newver.split('.')
    overs = oldver.split('.')
    
    l = len(nvers)
    if len(overs) > l: 
        l = len(overs)
    
    foundnew = False
    for i in range(l):
        
	if len(overs) < i:
	    oi = 0
	else:
	    oi = overs[i]
	    
	if len(nvers) < i:
	    ni = 0
	else:
	    ni = nvers[i]
	
	#if debug: print '(',i,') compare new=',ni,' and old=',oi
	if ni > oi:
	    foundnew = True
	    break

    if (foundnew):
        return  newver
	
    return ""

def iconMenuItem(title, stock):
    mItem = gtk.ImageMenuItem(title)
    im = gtk.Image()
    try:
	im.set_from_stock(stock, gtk.ICON_SIZE_MENU)
	mItem.set_image(im)
    except AttributeError:
	pass
    return mItem

def addIconToButton(button, stock):
 
    # on Mandriva 2008.1 it is disabled by default
    button.get_settings().set_long_property('gtk-button-images',1,'');
    try:
	im = gtk.Image()
	im.set_from_stock(stock, gtk.ICON_SIZE_BUTTON)
	button.set_image(im)
    except AttributeError:
	pass

def yesno(p,m):
    dialog = gtk.MessageDialog(p,gtk.DIALOG_MODAL,gtk.MESSAGE_INFO,gtk.BUTTONS_YES_NO, m)
    # force it to show to avoid some warnings
    dialog.show()
    dialog.set_keep_above(True)
    rid = dialog.run()
    dialog.destroy()
    return rid

def message(m,t):
    stopPBar()
    flag = 0
    if t == gtk.MESSAGE_ERROR:
        flag = gtk.DIALOG_MODAL
    dialog = gtk.MessageDialog(None,flag,t,gtk.BUTTONS_OK, m)
    dialog.show() 
    dialog.set_keep_above(True)
    dialog.run()
    dialog.destroy()

def putToDevWQueue(data):
    global ddQueue
    try:
    	ddQueue.put(data)
    except Queue.Full:
    	pass

def putToMainQueue(data):
    global guiQueue
    try:
    	guiQueue.put(data)
    except Queue.Full:
    	pass

def errorMessage(m):
    putToMainQueue(['MSG_ERR',m])

def infoMessage(m):
    putToMainQueue(['MSG_INF',m])

def getJ2MEPath():
    path = ''
    if os.path.exists('/usr/share/anyremote-J2ME-client/anyRemote-16.jar'):
        path = '/usr/share/anyremote-J2ME-client'
    elif os.path.exists('/usr/local/share/anyremote-J2ME-client/anyRemote-16.jar'):
        path = '/usr/local/share/anyremote-J2ME-client'
    elif os.path.exists(os.environ.get("HOME") + os.sep + '.anyRemote' + os.sep + 'anyRemote-16.jar'):
        path = os.environ.get("HOME") + os.sep + '.anyRemote'
    return path

def isInstalled(app):
    dirs = os.getenv('PATH').split(':')
    for d in dirs:
        if os.path.exists(d+'/'+app):
            return 'OK'
    return 'NOK'

def reqVersion(cmd):
    res = getResult(cmd,'main')
    if res == 'OK':
         return 'OK'
    return 'NOK'
	
def getResult(cmd, suffix):
    toFile = os.environ.get("HOME") + os.sep + '.anyRemote' + os.sep + 'ganyremote-' + suffix + '.tmp'
    os.system(cmd + '> ' + toFile)
    line = getLineTmpFile(toFile)
    return line.replace('\n','')

def getLineTmpFile(toFile):
    fd = open(toFile,'r')
    ln = ''
    if fd:
    	ln=fd.readline()
    	fd.close()
    return ln
    
#####################################################################################    

def saveDevices():
    global bt_devices

    # anyRemote related part
    cfg = os.environ.get("HOME")+os.sep+'.anyRemote'
    if os.path.exists(cfg):
    	pass
    else:
    	os.mkdir(cfg)

    f=open(cfg + os.sep + 'anyremote-peers.conf', 'w')
    if f:
    	treeiter     = bt_devices.get_iter_first()
    	while treeiter != None:
    	    v1 = bt_devices.get_value(treeiter, 0)
    	    v2 = bt_devices.get_value(treeiter, 1)
    	    v3 = bt_devices.get_value(treeiter, 2)
    	    v4 = bt_devices.get_value(treeiter, 3)
    	    
    	    f.write('Device='+v1+','+v2+','+v3+','+v4+'\n')

    	    treeiter = bt_devices.iter_next(treeiter)
    	f.close()

#####################################################################################    

def startUpdater(tmout):
    global statusUpdater
    if statusUpdater == None and tmout != -1:
    	statusUpdater = StatusUpdater(tmout)
    	statusUpdater.start()

def stopUpdater():
    global statusUpdater
    try:
    	statusUpdater.stop()
    	statusUpdater.join(2)
    except AttributeError, NameError:
        print 'Exception: statusUpdater.stop()'
    	pass
    statusUpdater = None
    
#####################################################################################    

def killAnyRemote():
    os.system('pkill -f "python .*anyremote2html"')
    os.system('killall -2 anyremote 2> /dev/null')


def startAnyRemote(cfg_file, webIface):
    global debug, gui
    
    killAnyRemote()
    
    time.sleep(0.5)

    web = ''
    if webIface:
    	web = ' -http'

    dev = ''
    if gui.device_ != '':
    	dev = ' -s '+gui.device_

    log = ''
    if debug:
    	log = ' -log'

    # TODO: add '-a' only for AT mode cfg.files
    rconn = ''
    if gui.autoReconn_ != '' and (gui.useType == 'AT' or gui.useType == ''):
        rcomm = ' -a '
    	    
    to_path = os.environ.get("HOME") + os.sep + '.anyRemote' + os.sep

    cmd = 'anyremote -fe ' + port + log + web + ' -f ' + cfg_file + dev + rconn + ' > '+ to_path + 'anyremote.stdout &'
    if debug: print cmd
    os.system(cmd)
    
    if webIface:
    	dd = ''
    	if debug: dd = '-d '

    	cmd = 'anyremote2html ' + dd + ' -a '+ gui.device_[7:] + ' ' + gui.webParams_ + ' > '+ to_path + 'anyremote2html.stdout &'
    	if debug: print cmd
    	os.system(cmd)

def timerBrowseDevices():
    browseDevices('F')
    
def browseDevices(force):
    global debug, cmd_array
    
    if force == 'F' and ['scan','F'] in cmd_array:
        if debug: print 'Skip device scan'
    else:
        gtk.gdk.threads_enter()
        queueBT('scan',force)
        gtk.gdk.threads_leave()
    
    return True
    
def startBtComm(tmout, jDir):
    global bt, gui, usepybluez
    if usepybluez == True and bt == None: 
	bt = BtComm(jDir)
	bt.start()
	
	if tmout != '' and tmout > 0: 
            gui.timer = gobject.timeout_add (int(1000*tmout), timerBrowseDevices)

def stopBtComm():
    global debug, bt, gui
    
    try:
        gobject.source_remove(gui.timer)
    except AttributeError, NameError:
        if debug: print 'Exception: BtComm gobject.source_remove(gui.timer)'
        pass
	
    try:
    	bt.stop()
    	bt.join(2)
    except AttributeError, NameError:
        if debug: print 'Exception: bt.stop()'
    	pass
    bt = None

def startFrontend():
    global frontEnd

    frontEnd = FrontEnd()
    frontEnd.start()

def stopFrontend():
    global frontEnd, debug

    # To avoid socket.error: (98, 'Address already in use') 
    # it needs to close client socket first
    
    killAnyRemote()

    time.sleep(0.5)

    try:
    	frontEnd.stop()
    except AttributeError, NameError:
        if debug: print 'Exception: frontEnd.stop()'
    	pass
    frontEnd = None

def showBrowserWin():
    global browserWin, debug
    try:
        if debug: print 'browserWin',browserWin.isShown
	if browserWin.isShown:
	    return
    except AttributeError, NameError:
	pass
    browserWin = DeviceBrowser()

def showChkCfgWin(javaDir):
    global chkCfgWin, debug
    try:
        if debug: print 'chkCfgWin',chkCfgWin.isShown
	if chkCfgWin.isShown:
	    return
    except AttributeError, NameError:
	pass
    chkCfgWin = CfgChecker(javaDir)

def showDetailsWin(v1,v2,v3,v4,v5):
    global dwin, gui 
    
    try:
	if dwin.isShown: 
	    return
    except AttributeError, NameError:
	pass
    dwin = DeviceDetail(v1, v2, v3, v4, v5, gui.javaDir_)

def getAvailableSet():

    global bt_devices

    gtk.gdk.threads_enter()
    treeiter = bt_devices.get_iter_first()
    gtk.gdk.threads_leave()

    s = []
    while treeiter != None:
    	gtk.gdk.threads_enter()
    	addr = bt_devices.get_value(treeiter, 0)
    	st   = bt_devices.get_value(treeiter, 4)
    	gtk.gdk.threads_leave()
    	
    	if st == AR_AVAIL:
	    s.append(addr)
    	
    	gtk.gdk.threads_enter()
    	treeiter = bt_devices.iter_next(treeiter)
    	gtk.gdk.threads_leave()
    
    return s

def getDevSet():

    global bt_devices

    gtk.gdk.threads_enter()
    treeiter = bt_devices.get_iter_first()
    gtk.gdk.threads_leave()

    s = []
    while treeiter != None:
    	gtk.gdk.threads_enter()
    	addr = bt_devices.get_value(treeiter, 0)
    	s.append(addr)
    	treeiter = bt_devices.iter_next(treeiter)
    	gtk.gdk.threads_leave()
    
    return s

def queueBT(tag,address):
    global debug

    if debug: print 'queueBT',cmd_array
    i = len(cmd_array)-1
    if i > 0 and cmd_array[i] == ['scan','']:
        cmd_array.insert(i,[tag,address])
    else:
        cmd_array.append([tag,address]) 
   
#####################################################################################    

def findIcon(name):
    global icon_theme, debug
    
    iName = name.split('.',1)
    
    try:
	a = icon_theme
    except NameError:    
        icon_theme = gtk.icon_theme_get_default()
	icon_theme.append_search_path('/opt/kde3/share/icons') 
	icon_theme.append_search_path('/opt/gnome/share/pixmaps') 
	icon_theme.append_search_path('/opt/gnome/share/icons') 
	if debug:
	    icon_theme.append_search_path('./data') 
	
	if debug:
            print 'findIcon path',icon_theme.get_search_path()
		
    try:
        pixbuf = icon_theme.load_icon(iName[0], 16, 0)
    except gobject.GError, exc:
        try:
	   if debug: print 'Can not find',iName,'Use default.'
	       
           pixbuf = icon_theme.load_icon("fileopen", 16, 0)
        except gobject.GError, exc:
	   # Try it hard
	   if debug: print 'Can not find default icon.'
	   icon_file = getResult('find /usr/share/icons /usr/share/pixmaps /usr/share/app-install/icons/ /usr/local/share/pixmaps /opt/kde3/share/icons /opt/gnome/share/pixmaps /opt/gnome/share/icons . -name fileopen.png 2>/dev/null','main')
	   
	   if icon_file != '':
	      icon_theme.append_search_path(os.path.dirname(icon_file))
	      try:
	          pixbuf = icon_theme.load_icon(iName[0], 16, 0)
              except gobject.GError, exc:
	          pixbuf = None
	   else:
	       pixbuf = None
    
    return pixbuf


def btVerify(showmsg):
    hcid = getResult('echo \'A=`ps -ef|grep hcid|grep -v grep|grep -v defunct`; if [ "x$A" == "x" ]; then echo NOK; else echo OK; fi\' | bash -f -s','main')
    if hcid == 'NOK':
        hcid = getResult('echo \'A=`ps -ef|grep bluetoothd|grep -v grep|grep -v defunct`; if [ "x$A" == "x" ]; then echo NOK; else echo OK; fi\' | bash -f -s','main')
    if showmsg and hcid == 'NOK':
        infoMessage(_('Bluetooth service is not active'))
    return hcid

def initVerify():

    tool = isInstalled('anyremote')
    if tool == 'NOK':
        errorMessage(_('anyRemote not found !\nPlease install it or correct $PATH'))

    tool = isInstalled('sdptool')
    if tool == 'NOK':
        errorMessage(_('sdptool not found !\nPlease install bluez-util'))

    # no needs to warn user
    #z = btVerify(True)

def usage():
    print 'ganyremote [-h|--help] [-p|--port <port>] [-d|--debug] [-o|--open] [-e] [-n|--npybluez]'
    
##################################################################################
#
# Main function
#
##################################################################################

def main():

    global gui, debug, guiMode, guiQueue, ddQueue, port, cmdToSend, icons, runUpdater, liststore, bt_devices, bt, pbar, cmd_array, dwin, browserWin, chkCfgWin, statusUpdater, frontEnd, usepybluez
    
    try:
        opts, args = getopt.getopt(sys.argv[1:], "dnehop:", ["debug", "expert", "help", "open", "npybluez", "port="])
    except getopt.GetoptError:
    	usage()
        sys.exit(2)
	
    browserWin = None
    chkCfgWin  = None
    bt         = None
    cmd_array  = []
    cmdToSend  = ''
    debug      = False
    dwin       = None
    guiMode    = 'simple'
    frontEnd   = None
    icons      = dict()
    openWin    = False
    pbar       = None
    port       = '5050'
    runUpdater = False
    statusUpdater = None
    usepybluez = True
    
    for o, a in opts:
        if o in ("-d", "--debug"):
            debug   = True
            guiMode = 'expert'
        if o in ("-e", "--expert"):
            guiMode = 'expert'
        if o in ("-h", "--help"):
            usage()
            sys.exit()
        if o in ("-p", "--port"):
            port = a
        if o in ("-o", "--open"):
            openWin = True
        if o in ("-n", "--npybluez"):
            usepybluez = False

    if pybluez == False and usepybluez == True:
        print _('Install PyBluez first !\nOr run with --npybluez option')
	return

    confdir = os.environ.get("HOME")+os.sep+'.anyRemote'
    if not os.path.isdir(confdir):
        os.mkdir(confdir)
    
    liststore  = gtk.ListStore(str, gtk.gdk.Pixbuf, str, str, str, str, str, str, str)
    bt_devices = gtk.ListStore(str,str,str,str,str)

    gobject.threads_init()
    
    guiQueue = Queue.Queue(0)
    ddQueue  = Queue.Queue(0)
    
    gui = gAnyRemote(openWin)
    gui.populateCfgFiles()
    
    if debug: 
        print 'Use translation from ',local_path
        print 'Starting backgroung threads'
	
    startUpdater(gui.updateTmout_)
    startBtComm(gui.browseTmout_, gui.javaDir_)
    startFrontend()

    gtk.main()
    
    return 0

if __name__ == "__main__":
    main()
