LizardByte / PyStream

WIP: Experimental project to test various capture and streaming protocols.
GNU Affero General Public License v3.0
3 stars 0 forks source link

Replace `pygame` with `kivy` in `client.py` #1

Open ReenigneArcher opened 2 years ago

ReenigneArcher commented 2 years ago

Using kivy would make it easier to create a multi platform client application.

Not quite sure how to get started though for this type of application.

ReenigneArcher commented 2 years ago

Outdated, but similar example: https://github.com/atuldo/videoStream/blob/master/videoStream.py

ReenigneArcher commented 2 years ago

This is probably close but not working quite yet... just putting here for now.

Been trying to save the image to memory and use that but not having much luck.

client.py

# reference
# https://github.com/atuldo/videoStream/blob/master/videoStream.py

from kivy.config import Config
from kivy.core.window import Window

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.clock import Clock
from socket import socket
from threading import *
from kivy.uix.image import Image
from kivy.cache import Cache
import pygame
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button

from lz4.frame import decompress
from kivy.core.image import Image as CoreImage
from io import BytesIO

from io import StringIO
buff = StringIO()

Config.set('graphics', 'resizable', 0)
Window.size = (600, 500)

kv = '''
Main:
    BoxLayout:
        orientation: 'vertical'
        padding: root.width * 0.05, root.height * .05
        spacing: '5dp'
        BoxLayout:
            size_hint: [1,.85]
            Image:
                id: image
                source: root.image
        BoxLayout:
            size_hint: [1,.15]
            GridLayout:
                cols: 2
                spacing: '10dp'
                Button:
                    id: status
                    text:'Play'
                    bold: True
                    on_press: root.play_pause()
                Button:
                    text: 'Close'
                    bold: True
                    on_press: root.close()
'''

def recv_all(conn, length):
    """Retrieve all pixels."""

    buf = b''
    while len(buf) < length:
        data = conn.recv(length - len(buf))
        if not data:
            return data
        buf += data
    return buf

sock = socket()

class Main(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.ipAddress = '127.0.0.1'
        self.port = 5000
        self.image = ''
        self.popup = None

    def play_pause(self):
        if not self.ipAddress or not self.port:
            box = GridLayout(cols=1)
            box.add_widget(Label(text="Ip or Port Not Set"))
            btn = Button(text="OK")
            btn.bind(on_press=self.close_popup)
            box.add_widget(btn)
            self.popup = Popup(title='Error', content=box, size_hint=(.8, .3))
            self.popup.open()
        else:
            self.ids.status.text = "Playing"
            sock.connect((self.ipAddress, self.port))
            self.image = BytesIO(b"")
            Clock.schedule_interval(self.recv, 0.1)

    def close_popup(self, btn):
        self.popup.dismiss()

    def stop(self):
        self.ids.status.text = "Play"
        Clock.unschedule(self.recv)

    def recv(self, dt):
        size_len = int.from_bytes(sock.recv(1), byteorder='big')
        size = int.from_bytes(sock.recv(size_len), byteorder='big')
        pixels = decompress(recv_all(sock, size))

        image = pygame.image.fromstring(pixels, (1920, 1080), "RGB")  # convert received image from string

        pygame.image.save(image, buff)
        buff.seek(0)

        self.ids.image_source.reload()

    def close(self):
        App.get_running_app().stop()

class VideoStreamApp(App):
    def build(self):
        return Builder.load_string(kv)

VideoStreamApp().run()
LizardByte-bot commented 1 year ago

This issue is stale because it has been open for 90 days with no activity. Comment or remove the stale label, otherwise this will be closed in 10 days.