#!/usr/bin/env python # -*- coding: utf-8 -*- # gtk_JAMtank_Ventana.py por: # Flavio Danesse # CeibalJAM! - Uruguay - Plan Ceibal # # 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import pygame from pygame.locals import * import gc gc.enable() import socket import SocketServer import gobject import threading import gtk import pygtk pygtk.require("2.0") from sugar.activity import activity import time import string import sys import dbus import os import commands import threading from JAMtank import JAMtank from TCP_Server_thread_Stream import ThreadedTCPServer, ThreadedTCPRequestHandler DIRECTORIODEIMAGENES = os.getcwd()+"/Imagenes/" DIRECTORIODESONIDOS = os.getcwd()+"/Sonidos/" PUERTO = 5000 # ------ Inicio de Funciones de Presencia ---------- OLPC_SESSION_BUS = "/tmp/olpc-session-bus" PRESENCE_SERVICE = "org.laptop.Sugar.Presence" PRESENCE_PATH = "/org/laptop/Sugar/Presence" PRESENCE_IFACE = "org.laptop.Sugar.Presence" BUDDY_IFACE = "org.laptop.Sugar.Presence.Buddy" def get_bus(): # sugar presence if os.path.exists(OLPC_SESSION_BUS): address = "unix:path=%s" % OLPC_SESSION_BUS return dbus.bus.BusConnection(address_or_type=address) else: if len(sys.argv) != 2: sys.exit(1) if 'DBUS_SESSION_BUS_ADDRESS' in os.environ: del os.environ['DBUS_SESSION_BUS_ADDRESS'] display = sys.argv[1] os.environ['DISPLAY'] = display return dbus.bus.BusConnection() def get_Xos(): # devuelve la ip y el nombre de todas las xo en la red # En realidad devuelve el nick de todas las xo, la ip local y las ip en la mesh de las demás xo bus = get_bus() ps = bus.get_object(PRESENCE_SERVICE, PRESENCE_PATH) ps_iface = dbus.Interface(ps, PRESENCE_IFACE) buddies = map(lambda b: bus.get_object(PRESENCE_SERVICE, b), ps_iface.GetBuddies()) xos = [] for buddy in buddies: buddy_iface = dbus.Interface(buddy, BUDDY_IFACE) try: props = buddy_iface.GetProperties() ip = "%s" % (props['ip4-address'].encode('utf-8')) nick = "%s" % (props['nick'].encode('utf-8')) xo = (ip, nick) xos.append(xo) except dbus.DBusException: pass return xos # ------ Fin de Funciones de Presencia ---------- class GTK_JAMtank(activity.Activity): # Interface gtk def __init__(self, handle): activity.Activity.__init__(self, handle, False) self.set_title("-.JAMtank (versión 1).- -. CeibalJAM! 2010.-") pygame.mixer.init(44100, -16, 2, 2048) pygame.mixer.music.set_volume(1.0) self.sonido = pygame.mixer.Sound(DIRECTORIODESONIDOS+"Menu.ogg") self.jamtank = None self.servidor = None self.modo = None self.estado = "Presentacion" self.nick = None self.lista_servidores = None self.ip = None # ip local self.ip_server = None # ip servidor # Canvas self.contenedor_principal = gtk.VBox() # imagen Creditos imagen = gtk.Image() imagen.set_from_file(DIRECTORIODEIMAGENES + "JAMtank.png") self.contenedor_principal.pack_start(imagen, False, False, 0) # Lista de Servidores Activos # self.contenedor_principal.pack_start(gtk.Label("Servidores JAMtank Actualmente Activos en la Red"), False, False, 0) # Lista de Servidores Activos self.caja_servers = gtk.VBox() viewport = gtk.ScrolledWindow() viewport.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) viewport.add_with_viewport(self.caja_servers) frame = gtk.Frame() frame.add(viewport) # busca servidores JAMtank en la red self.actualiza_servers(None) # Botones servidor local, actualizar lista de servidores y salir caja_botones = gtk.VBox() boton_servidor = gtk.Button("Crear Nuevo Juego en Red") boton_servidor.connect("clicked", self.set_Estado, "servidor", self.ip) boton_servidor.connect_object("clicked", gtk.Widget.destroy, self) boton_scan = gtk.Button("Actualizar Lista de Juegos en la Red") boton_scan.connect("clicked", self.actualiza_servers) boton_salir = gtk.Button("Salir de JAMtank") boton_salir.connect_object("clicked", self.salir, None) caja_botones.pack_start(boton_servidor, True, True, 5) caja_botones.pack_start(boton_scan, True, True, 5) caja_botones.pack_end(boton_salir, True, True, 5) # imagen Teclado imagen1 = gtk.Image() imagen1.set_from_file(DIRECTORIODEIMAGENES + "Teclado.png") caja_secundaria = gtk.HBox() caja_secundaria.pack_start(imagen1, False, False, 0) caja_secundaria.pack_start(frame, True, True, 5) caja_secundaria.pack_end(caja_botones, False, False, 5) self.contenedor_principal.pack_start(caja_secundaria, True, True, 0) # para introducir una IP conocida #caja = gtk.HBox() #etiqueta = gtk.Label("IP: ") self.entrada = None #conectar = gtk.Button("Conectarse a Esta IP") #conectar.connect("clicked", self.get_connect_ip_conocida) #caja.pack_start (etiqueta, False, False, 5) #caja.pack_start (self.entrada, False, False, 5) #caja.pack_start (conectar, False, False, 5) #self.contenedor_principal.pack_start(caja, False, False, 5) self.set_canvas(self.contenedor_principal) self.show_all() self.sonido.play(loops=-1) # switch gtk pygame reloj = gobject.timeout_add(500, self.get_Juego) def set_entrada_ip_conocida(self): # objetos para agregar ip de servidor conocido caja = gtk.HBox() etiqueta = gtk.Label("Conectarse a (IP): ") self.entrada = gtk.Entry() conectar = gtk.Button("Jugar") conectar.connect("clicked", self.get_connect_ip_conocida) caja.pack_start (etiqueta, True, True, 5) caja.pack_start (self.entrada, True, True, 5) caja.pack_end (conectar, True, True, 5) caja.show_all() self.caja_servers.pack_start(caja, False, False, 5) def get_connect_ip_conocida(self, widget): # Conecta a la ip ingresada ip = self.entrada.get_text() if ip: self.set_Estado(None, "cliente", ip) gtk.Widget.destroy(self) def actualiza_servers(self, widget): # Verifica tener conexión a una red self.lista_servidores = [] # obtiene el nombre de la xo XOs = get_Xos() self.ip, self.nick = XOs[0] while not self.ip or self.ip == "localhost": # obtiene el nombre de la xo XOs = get_Xos() self.ip, self.nick = XOs[0] self.get_avisar_no_hay_ip() red = self.ip.split(".") for x in range(2, 254): ip = "%s.%s.%s.%s" % (red[0],red[1],red[2],x) thread = threading.Thread( target=self.scan_red, args=( ip, PUERTO) ) thread.start() time.sleep(0.02) self.get_lista_xos() def scan_red (self, ip, puerto): # escanea la red en busca del puerto abierto para JAMtant conexion = socket.socket() try: conexion.connect( (ip, puerto) ) self.lista_servidores.append(ip) except: pass conexion.close() def get_lista_xos(self): # arma la lista de xo en la red con server JAMtank corriendo for child in self.caja_servers: self.caja_servers.remove(child) self.set_entrada_ip_conocida() for ip in self.lista_servidores: caja = gtk.HBox() lab_ip = gtk.Label(ip) conectar = gtk.Button("Jugar") conectar.connect("clicked", self.set_Estado, "cliente", ip) conectar.connect_object("clicked", gtk.Widget.destroy, self) caja.pack_start(lab_ip, True, True, 5) caja.pack_end(conectar, True, True, 5) caja.show_all() self.caja_servers.pack_start(caja, False, False, 5) def get_avisar_no_hay_ip(self): # Crea un cuadro de dialogo para avisar que no está conectado a ninguna red. dialog = gtk.Dialog("Atención !!!", None, gtk.DIALOG_MODAL, None) etiqueta0 = gtk.Label("No estás conectado a ninguna Red.") dialog.vbox.pack_start(etiqueta0, True, True, 5) etiqueta1 = gtk.Label("JAMtank es un juego en red, debes conectarte a una Red") dialog.vbox.pack_start(etiqueta1, True, True, 5) dialog.add_button("OK", 1) dialog.add_button("Cancelar", 2) dialog.show_all() if dialog.run() == 1: pass elif dialog.run() == 2: # sale automaticamente sys.exit() dialog.destroy() def delete_event(self, widget, event, data=None): # Cierra la ventana gtk return gtk.FALSE def salir(self, widget): sys.exit() def set_Estado(self, widget, modo, ip): # para poder llamar al juego luego de que se cierre la ventana gtk self.sonido.stop() pygame.quit() self.ip_server = ip self.modo = modo # Servidor o Cliente self.estado = "Juego" #----------------------Juego pygame------------------------------------------------------------- def get_Juego(self): # Se llama al juego pygame if self.estado == "Juego": if self.modo == "servidor": server = ThreadedTCPServer((self.ip, PUERTO), ThreadedTCPRequestHandler) server.allow_reuse_address = True server.socket.setblocking(0) server_thread = threading.Thread(target=server.serve_forever) server_thread.setDaemon(True) server_thread.start() self.jamtank = JAMtank(ip=self.ip, PUERTO=PUERTO) elif self.modo == "cliente": self.jamtank = JAMtank(ip=self.ip_server, PUERTO=PUERTO) return False # no volver por acá else: pass return True # seguir viniendo por acá #----------------------Juego pygame------------------------------------------------------------- if __name__ == "__main__": GTK_JAMtank()