<commit_before>#!/usr/bin/env python
#
# (C) 2005 British Broadcasting Corporation and Kamaelia Contributors(1)
#     All Rights Reserved.
#
# You may only modify and redistribute this under the terms of any of the
# following licenses(2): Mozilla Public License, V1.1, GNU General
# Public License, V2.0, GNU Lesser General Public License, V2.1
#
# (1) Kamaelia Contributors are listed in the AUTHORS file and at
#     http://kamaelia.sourceforge.net/AUTHORS - please extend this file,
#     not this notice.
# (2) Reproduced in the COPYING file, and at:
#     http://kamaelia.sourceforge.net/COPYING
# Under section 3.5 of the MPL, we are using this text since we deem the MPL
# notice inappropriate for this file. As per MPL/GPL/LGPL removal of this
# notice is prohibited.
#
# Please contact us via: <EMAIL>
# to discuss alternative licensing.
# -------------------------------------------------------------------------

"""\
=====================
GUI for Ryans Bittorrent Package
=====================
TODO
"""

import sys
sys.path.append("../../Kamaelia/UI/OpenGL/")


import Axon
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *

from Util3D import *
from OpenGLComponent import *

from Button import Button
from ArrowButton import ArrowButton
from SimpleButton import SimpleButton
from ProgressBar import ProgressBar
from Container import Container
from SkyGrassBackground import SkyGrassBackground
from Movement import WheelMover
from Label import Label

import random
import os


class TorrentOpenGLGUI(Axon.Component.component):
    Inboxes = {
        "inbox":"not used",
        "control":"not used",
        "button":"To receive commands from buttons",
        "torrent_delivery": "for reception of torrent files",
    }
    
    Outboxes = {
        "outbox":"",
        "signal" : "",
        "fetcher" : "",
        "fetchersignal" : "",
        "mover_signal": "",
        "mover_switch": "",
    }
    
    
    def __init__(self, **argd):
        super(TorrentOpenGLGUI, self).__init__()
        
        
    def main(self):
        self.mover = WheelMover(radius=15, center=(0,0,-25), steps=500, slots=40).activate()
        self.link( (self, "mover_signal"), (self.mover, "notify") )
        self.link( (self, "mover_switch"), (self.mover, "switch") )

        self.background = SkyGrassBackground(size=(5000,5000,0), position=(0,0,-90)).activate()
        
        self.up_button = ArrowButton(size=(1,1,0.3), position=(7,5,-15), msg="UP").activate()
        self.down_button = ArrowButton(size=(1,1,0.3), position=(7,-5,-15), rotation=(0,0,180), msg="DOWN").activate()
        
        self.link( (self.up_button, "outbox"), (self, "button") )
        self.link( (self.down_button, "outbox"), (self, "button") )
        
        self.loadLocalTorrentFiles()
        
        while 1:
            
            if self.dataReady("button"):
                msg = self.recv("button")
                if msg == "UP":
                    self.send("NEXT", "mover_switch")
                if msg == "DOWN":
                    self.send("PREVIOUS", "mover_switch")
                if msg == "ADD":
                    self.addTorrent("Test")
                    
            if self.dataReady("torrent_delivery"):
                torrent = self.recv("torrent_delivery")
                
                    
            yield 1


    def loadLocalTorrentFiles(self):
        print "Loading local torrent files..."
        cwd = os.getcwd()
        files = os.listdir(cwd)
        for f in files:
            if f.endswith(".torrent"):
                print "- ",f
                fobj = open(f)
                torrent = fobj.read() 
                fobj.close()
                self.addTorrent(f, torrent)
                

    def addTorrent(self, title, torrent):
        start = Button(size=(0.9,0.5,0.3), caption="Start", msg=torrent).activate()
        info  = Button(size=(0.9,0.5,0.3), caption="Info", msg="Info").activate()
        progress = ProgressBar(size=(3,0.5,0.3)).activate()
        colour = [int(random.randint(100,255)) for i in range(3) ]
        label = Label( size=(5.4, 0.3, 0.3), caption=title, fontsize=26, bgcolour=colour).activate()
        
        container_elements = {
            progress : { "position":(-1.2,-0.3,0) },
            start : { "position":(1.1,-0.3,0) },
            info : { "position":(2.3,-0.3,0) },
            label : { "position":(0, 0.3, 0) },
        }
    
        container = Container(contents=container_elements, position=(0,0,-10)).activate()
        
        req = { "APPEND_CONTROL":True,
                "objectid": id(container),
                "control": (container,"position")
        }
        self.send(req, "mover_signal")
        
        
    def getTorrentName(self, torrent):
        if torrent.find("name") != -1:
            pass
        else:
            return "Unknown Name"
        
        
if __name__ == "__main__":
    from Kamaelia.Chassis.Graphline import Graphline
    import sys
    sys.path.append("../HTTP")

    from Kamaelia.Community.RJL.Kamaelia.Protocol.HTTP.HTTPClient import SimpleHTTPClient
    from Kamaelia.Util.Console import ConsoleReader
    from Kamaelia.Community.RJL.Kamaelia.Protocol.Torrent.TorrentPatron import TorrentPatron
    from Kamaelia.Community.RJL.Kamaelia.Protocol.Torrent.TorrentIPC import TIPCNewTorrentCreated, TIPCTorrentStartFail, TIPCTorrentAlreadyDownloading, TIPCTorrentStatusUpdate
    
    Graphline(
        reader = ConsoleReader(prompt="Enter torrent location:"),
        gui = TorrentOpenGLGUI(),
        httpclient = SimpleHTTPClient(),
        backend = TorrentPatron(),
        linkages = {
            ("gui", "outbox") : ("backend", "inbox"),
            ("gui", "fetchersignal") : ("httpclient", "control"),
            ("gui", "signal") : ("backend", "control"),
            ("reader", "outbox") : ("httpclient", "inbox"),
            ("httpclient", "outbox") : ("gui", "torrent_delivery"),
            ("backend", "outbox"): ("gui", "inbox")
        }
    ).run()
        
    
    Axon.Scheduler.scheduler.run.runThreads()  
<commit_msg>+ Torrent downloading works. + Added stop buttons. + Torrent info can be shown. + lots of minor changes<commit_after>#!/usr/bin/env python
#
# (C) 2005 British Broadcasting Corporation and Kamaelia Contributors(1)
#     All Rights Reserved.
#
# You may only modify and redistribute this under the terms of any of the
# following licenses(2): Mozilla Public License, V1.1, GNU General
# Public License, V2.0, GNU Lesser General Public License, V2.1
#
# (1) Kamaelia Contributors are listed in the AUTHORS file and at
#     http://kamaelia.sourceforge.net/AUTHORS - please extend this file,
#     not this notice.
# (2) Reproduced in the COPYING file, and at:
#     http://kamaelia.sourceforge.net/COPYING
# Under section 3.5 of the MPL, we are using this text since we deem the MPL
# notice inappropriate for this file. As per MPL/GPL/LGPL removal of this
# notice is prohibited.
#
# Please contact us via: <EMAIL>
# to discuss alternative licensing.
# -------------------------------------------------------------------------

"""\
=====================
GUI for Ryans Bittorrent Package
=====================
TODO
"""

import sys
sys.path.append("../../Kamaelia/UI/OpenGL/")


import Axon
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *

from Util3D import *
from OpenGLComponent import *

from Button import Button
from ArrowButton import ArrowButton
from SimpleButton import SimpleButton
from ProgressBar import ProgressBar
from Container import Container
from SkyGrassBackground import SkyGrassBackground
from Movement import WheelMover, PathMover, LinearPath
from Label import Label
from PygameWrapperPlane import PygameWrapperPlane
from Kamaelia.UI.Pygame.Ticker import Ticker

from Kamaelia.Community.RJL.Kamaelia.Protocol.Torrent.TorrentIPC import *

from BitTorrent.bencode import bdecode

import random
import os
import time

class TorrentOpenGLGUI(Axon.AdaptiveCommsComponent.AdaptiveCommsComponent):
    Inboxes = {
        "inbox":"Receive messages from TorrentPatron",
        "control":"not used",
        
        "nav":"To receive commands from navigation buttons",

        "start": "Start commands from buttons",
        "stop": "Stop commands from buttons",

        "show_info": "Info commands from buttons",
        "hide_info": "Hide torrent info",

        "torrent_url": "For reception of torrent file URLs",
        "torrent_file": "For reception of torrent files",
    }
    
    Outboxes = {
        "outbox":"Send Messages to TorrentPatron",
        "signal" : "",

        "fetcher" : "Send URLs to SimpleHttpClient",

        "mover_signal": "Send command to WheelMover",
        "mover_switch": "Control WheelMover",
        
        "infomover_commands": "Send commands to info container mover",
        "torrent_info": "For sending info about a torrent"
    }
    
    
    def __init__(self, **argd):
        super(TorrentOpenGLGUI, self).__init__()
        
        self.torrents = []
        self.torrent_from_id = {}
        self.torrent_to_id = {}
        self.torrent_containers = {}
        self.torrent_info = {}
        self.torrent_progress_comms = {}
        self.torrent_filename = {}
        
        self.requested_files = []
        self.started_torrents = []
        
        
    def main(self):
        self.initUIComponents()        
        self.loadLocalTorrentFiles()
        
        while 1:
            yield 1
            
            while self.dataReady("inbox"):
                msg = self.recv("inbox")
                print str(msg)
                
                if isinstance(msg, TIPCNewTorrentCreated):
                    torrent = self.started_torrents.pop(0)
                    self.torrent_from_id[msg.torrentid] = torrent
                    self.torrent_to_id[torrent] = msg.torrentid
                                        
                elif isinstance(msg, TIPCTorrentStartFail) or isinstance(msg, TIPCTorrentAlreadyDownloading):
                    self.started_torrents.pop()
                
                elif isinstance(msg, TIPCTorrentStatusUpdate):
                    self.send(msg.statsdictionary.get("fractionDone","0"), self.torrent_progress_comms[ self.torrent_from_id[msg.torrentid]] )

            while self.dataReady("nav"):
                msg = self.recv("nav")
                if msg == "UP":
                    self.send("NEXT", "mover_switch")
                if msg == "DOWN":
                    self.send("PREVIOUS", "mover_switch")

            while self.dataReady("torrent_url"):
                url = self.recv("torrent_url")
                filename = os.path.basename(url)
                self.requested_files.append(filename)
                self.send(url, "fetcher")

            while self.dataReady("torrent_file"):
                torrentfile = self.recv("torrent_file")
                # save received file
                filename = self.requested_files.pop()
                fobj = open(getcwd()+filename, 'w')
                fobj.write(torrentfile)
                fobj.close()
                print "RECEIVED TORRENT", filename
                # add torrent
                self.addTorrent(filename, torrentfile)                
                
            while self.dataReady("start"):
                torrent = self.recv("start")
                print "START TORRENT", self.torrent_filename[torrent]
                self.send(torrent)
                self.started_torrents.append(torrent)
                
            while self.dataReady("stop"):
                torrent = self.recv("stop")
                try:
                    self.send( TIPCCloseTorrent(torrentid=self.torrent_to_id[torrent]) )
                except KeyError:
                    pass
                
            while self.dataReady("show_info"):
                torrent = self.recv("show_info")
                self.showInfo(torrent)

            while self.dataReady("hide_info"):
                msg = self.recv("hide_info")
                self.hideInfo()


    def initUIComponents(self):
        self.mover = WheelMover(radius=15, center=(0,0,-25), steps=500, slots=40).activate()
        self.link( (self, "mover_signal"), (self.mover, "notify") )
        self.link( (self, "mover_switch"), (self.mover, "switch") )

        self.background = SkyGrassBackground(size=(5000,5000,0), position=(0,0,-90)).activate()
        
        # create & link nav buttons
        self.up_button = ArrowButton(size=(1,1,0.3), position=(7,5,-15), msg="UP").activate()
        self.down_button = ArrowButton(size=(1,1,0.3), position=(7,-5,-15), rotation=(0,0,180), msg="DOWN").activate()
        self.link( (self.up_button, "outbox"), (self, "nav") )
        self.link( (self.down_button, "outbox"), (self, "nav") )
        
        # init info display
        self.infoticker = Ticker(text_height=20).activate()
        self.tickerwrapper = PygameWrapperPlane(wrap=self.infoticker, size=(2.5,2.5,0.3)).activate()
        self.hideinfo_button = Button(caption="Hide", fontsize=30).activate()
        
        infocontents = {
            self.tickerwrapper : { "position":(0,.5,0) },
            self.hideinfo_button : { "position":(0,-2.3,0) },
        }
        
        self.infocontainer = Container(contents=infocontents, position=(0,8,-8)).activate()
        infopath = LinearPath([(0, 8, -8), (0,0,-8)], 200)
        
        self.infomover = PathMover(infopath, False).activate()
        
        self.link( (self.infomover, "outbox"), (self.infocontainer, "position") )
        self.link( (self, "infomover_commands"), (self.infomover, "inbox") )
        self.link( (self, "torrent_info"), (self.infoticker, "inbox") )
        self.link( (self.hideinfo_button, "outbox"), (self, "hide_info") )
        
        self.send("Stop", "infomover_commands")


    def loadLocalTorrentFiles(self):
        print "Loading local torrent files..."
        cwd = os.getcwd()
        files = os.listdir(cwd)
        for f in files:
            if f.endswith(".torrent"):
                print "- ",f
                fobj = open(f)
                torrent = fobj.read() 
                fobj.close()
                self.addTorrent(f, torrent)
                

    def addTorrent(self, title, torrent):
        self.torrents.append(torrent)
        self.torrent_filename[torrent] = title
    
        start = Button(size=(0.8,0.5,0.3), caption="Start", fontsize=35, msg=torrent).activate()
        info  = Button(size=(0.8,0.5,0.3), caption="Info", fontsize=35, msg=torrent).activate()
        stop = Button(size=(0.8,0.5,0.3), caption="Stop", fontsize=35, msg=torrent).activate()
        progress = ProgressBar(size=(3.2,0.5,0.3), barcolour=(100,255,100)).activate()
        colour = [ int(random.randint(100,255)) for i in range(3) ]
        label = Label( size=(6.0, 0.3, 0.3), caption=title, fontsize=26, bgcolour=colour).activate()

        self.link( (start, "outbox"), (self, "start") )
        self.link( (stop, "outbox"), (self, "stop") )
        self.link( (info, "outbox"), (self, "show_info") )
        
        container_elements = {
            progress : { "position":(-1.4,-0.3,0) },
            start : { "position":(0.8,-0.3,0) },
            stop : { "position":(1.7,-0.3,0) },
            info : { "position":(2.6,-0.3,0) },
            label : { "position":(0, 0.3, 0) },
        }
    
        container = Container(contents=container_elements, position=(0,0,-10)).activate()
        self.torrent_containers[torrent] = id(container)
        
        req = { "APPEND_CONTROL":True,
                "objectid": id(container),
                "control": (container,"position")
        }
        self.send(req, "mover_signal")
        
        # create & link box for progress update
        progbox = self.addOutbox("progress")
        self.torrent_progress_comms[torrent] = progbox
        self.link( (self, progbox), (progress, "progress") )


    def showInfo(self, torrent):
        try:
            decoded = self.torrent_info[torrent]
        except KeyError:
            self.torrent_info[torrent] = bdecode(torrent)
            decoded = self.torrent_info[torrent]
        
        info = decoded.get("info", None)
        if info is not None:
            name = info.get("name", "?")
            length = info.get("length", "?")

        date = decoded.get("creation date", "?")
        creator = decoded.get("created by", "?")
        announce = decoded.get("announce", "?")
        comment = decoded.get("comment", "")
            
        infotuple = (name, comment, length, date, creator, announce)
        
        infostring = "Name:%s\nComment:%s\nLength:%s\nCreation Date:%s\nCreated by:%s\nAnnounce:%s\n" % infotuple
        print "INFO\n", infostring
        
        # move info container in front of everthig
        self.send("Forward", "infomover_commands")
        self.send("Play", "infomover_commands")
        self.send(infostring, "torrent_info")
        
        
    def hideInfo(self):
        self.send("Backward", "infomover_commands")
        self.send("Play", "infomover_commands")
        
        
if __name__ == "__main__":
    from Kamaelia.Chassis.Graphline import Graphline
    import sys

    from Kamaelia.Community.RJL.Kamaelia.Protocol.HTTP.HTTPClient import SimpleHTTPClient
    from Kamaelia.Util.Console import *
    from Kamaelia.Community.RJL.Kamaelia.Protocol.Torrent.TorrentPatron import TorrentPatron
    from Kamaelia.UI.PygameDisplay import PygameDisplay
    
    # override pygame display service
    ogl_display = OpenGLDisplay.getDisplayService()
    PygameDisplay.setDisplayService(ogl_display[0])
    
    print "TEST"
    Graphline(
        reader = ConsoleReader(),#(prompt="Enter torrent location:"),
        httpclient = SimpleHTTPClient(),
        echo = ConsoleEchoer(),
        gui = TorrentOpenGLGUI(),
        backend = TorrentPatron(),
        linkages = {
            ("gui", "outbox") : ("backend", "inbox"),
#            ("gui", "fetchersignal") : ("httpclient", "control"),
#            ("gui", "signal") : ("backend", "control"),
            ("reader", "outbox") : ("gui", "torrent_url"),
            ("gui", "fetcher") : ("httpclient", "inbox"),
            ("httpclient", "outbox") : ("gui", "torrent_file"),
            ("httpclient", "debug") : ("echo", "inbox"),
            ("backend", "outbox"): ("gui", "inbox")
        }
    ).run()

{'fraction_non_alphanumeric': 0.14325068870523416, 'fraction_numerical': 0.01609679684545995, 'mean_word_length': 2.205887445887446, 'pattern_counts': {'":': 45, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3231833', 'n_tokens_mistral': 5729, 'n_tokens_neox': 5448, 'n_words': 1201}