autoglm-gui 0.4.11__py3-none-any.whl → 0.4.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. AutoGLM_GUI/__init__.py +8 -0
  2. AutoGLM_GUI/__main__.py +29 -34
  3. AutoGLM_GUI/adb_plus/__init__.py +6 -0
  4. AutoGLM_GUI/adb_plus/device.py +50 -0
  5. AutoGLM_GUI/adb_plus/ip.py +78 -0
  6. AutoGLM_GUI/adb_plus/serial.py +35 -0
  7. AutoGLM_GUI/api/__init__.py +8 -0
  8. AutoGLM_GUI/api/agents.py +76 -67
  9. AutoGLM_GUI/api/devices.py +96 -6
  10. AutoGLM_GUI/api/media.py +12 -235
  11. AutoGLM_GUI/config_manager.py +538 -97
  12. AutoGLM_GUI/exceptions.py +7 -0
  13. AutoGLM_GUI/platform_utils.py +19 -0
  14. AutoGLM_GUI/schemas.py +35 -2
  15. AutoGLM_GUI/scrcpy_protocol.py +46 -0
  16. AutoGLM_GUI/scrcpy_stream.py +192 -307
  17. AutoGLM_GUI/server.py +7 -2
  18. AutoGLM_GUI/socketio_server.py +125 -0
  19. AutoGLM_GUI/static/assets/{about-wSo3UgQ-.js → about-kgOkkOWe.js} +1 -1
  20. AutoGLM_GUI/static/assets/chat-CZV3RByK.js +149 -0
  21. AutoGLM_GUI/static/assets/{index-B5u1xtK1.js → index-BPYHsweG.js} +1 -1
  22. AutoGLM_GUI/static/assets/index-Beu9cbSy.css +1 -0
  23. AutoGLM_GUI/static/assets/index-DfI_Z1Cx.js +10 -0
  24. AutoGLM_GUI/static/assets/worker-D6BRitjy.js +1 -0
  25. AutoGLM_GUI/static/index.html +2 -2
  26. {autoglm_gui-0.4.11.dist-info → autoglm_gui-0.4.12.dist-info}/METADATA +2 -1
  27. autoglm_gui-0.4.12.dist-info/RECORD +56 -0
  28. AutoGLM_GUI/resources/apks/ADBKeyBoard.LICENSE.txt +0 -339
  29. AutoGLM_GUI/resources/apks/ADBKeyBoard.README.txt +0 -1
  30. AutoGLM_GUI/resources/apks/ADBKeyboard.apk +0 -0
  31. AutoGLM_GUI/static/assets/chat-BcY2K0yj.js +0 -25
  32. AutoGLM_GUI/static/assets/index-CHrYo3Qj.css +0 -1
  33. AutoGLM_GUI/static/assets/index-D5BALRbT.js +0 -10
  34. autoglm_gui-0.4.11.dist-info/RECORD +0 -52
  35. {autoglm_gui-0.4.11.dist-info → autoglm_gui-0.4.12.dist-info}/WHEEL +0 -0
  36. {autoglm_gui-0.4.11.dist-info → autoglm_gui-0.4.12.dist-info}/entry_points.txt +0 -0
  37. {autoglm_gui-0.4.11.dist-info → autoglm_gui-0.4.12.dist-info}/licenses/LICENSE +0 -0
AutoGLM_GUI/server.py CHANGED
@@ -1,5 +1,10 @@
1
- """AutoGLM-GUI Backend API Server."""
1
+ """AutoGLM-GUI Backend API Server (FastAPI + Socket.IO)."""
2
2
 
3
- from AutoGLM_GUI.api import app
3
+ from socketio import ASGIApp
4
+
5
+ from AutoGLM_GUI.api import app as fastapi_app
6
+ from AutoGLM_GUI.socketio_server import sio
7
+
8
+ app = ASGIApp(sio, other_asgi_app=fastapi_app)
4
9
 
5
10
  __all__ = ["app"]
@@ -0,0 +1,125 @@
1
+ """Socket.IO server for Scrcpy video streaming."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import time
7
+ from typing import Any
8
+
9
+ import socketio
10
+
11
+ from AutoGLM_GUI.logger import logger
12
+ from AutoGLM_GUI.scrcpy_protocol import ScrcpyMediaStreamPacket
13
+ from AutoGLM_GUI.scrcpy_stream import ScrcpyStreamer
14
+
15
+ sio = socketio.AsyncServer(
16
+ async_mode="asgi",
17
+ cors_allowed_origins="*",
18
+ )
19
+
20
+ _socket_streamers: dict[str, ScrcpyStreamer] = {}
21
+ _stream_tasks: dict[str, asyncio.Task] = {}
22
+
23
+
24
+ async def _stop_stream_for_sid(sid: str) -> None:
25
+ task = _stream_tasks.pop(sid, None)
26
+ if task:
27
+ task.cancel()
28
+
29
+ streamer = _socket_streamers.pop(sid, None)
30
+ if streamer:
31
+ streamer.stop()
32
+
33
+
34
+ def stop_streamers(device_id: str | None = None) -> None:
35
+ """Stop active scrcpy streamers (all or by device)."""
36
+ sids = list(_socket_streamers.keys())
37
+ for sid in sids:
38
+ streamer = _socket_streamers.get(sid)
39
+ if not streamer:
40
+ continue
41
+ if device_id and streamer.device_id != device_id:
42
+ continue
43
+ task = _stream_tasks.pop(sid, None)
44
+ if task:
45
+ task.cancel()
46
+ streamer.stop()
47
+ _socket_streamers.pop(sid, None)
48
+
49
+
50
+ async def _stream_packets(sid: str, streamer: ScrcpyStreamer) -> None:
51
+ try:
52
+ async for packet in streamer.iter_packets():
53
+ payload = _packet_to_payload(packet)
54
+ await sio.emit("video-data", payload, to=sid)
55
+ except asyncio.CancelledError:
56
+ raise
57
+ except Exception as exc:
58
+ logger.exception("Video streaming failed: %s", exc)
59
+ try:
60
+ await sio.emit("error", {"message": str(exc)}, to=sid)
61
+ except Exception:
62
+ pass
63
+ finally:
64
+ await _stop_stream_for_sid(sid)
65
+
66
+
67
+ def _packet_to_payload(packet: ScrcpyMediaStreamPacket) -> dict[str, Any]:
68
+ payload: dict[str, Any] = {
69
+ "type": packet.type,
70
+ "data": packet.data,
71
+ "timestamp": int(time.time() * 1000),
72
+ }
73
+ if packet.type == "data":
74
+ payload["keyframe"] = packet.keyframe
75
+ payload["pts"] = packet.pts
76
+ return payload
77
+
78
+
79
+ @sio.event
80
+ async def connect(sid: str, environ: dict) -> None:
81
+ logger.info("Socket.IO client connected: %s", sid)
82
+
83
+
84
+ @sio.event
85
+ async def disconnect(sid: str) -> None:
86
+ logger.info("Socket.IO client disconnected: %s", sid)
87
+ await _stop_stream_for_sid(sid)
88
+
89
+
90
+ @sio.on("connect-device")
91
+ async def connect_device(sid: str, data: dict | None) -> None:
92
+ payload = data or {}
93
+ device_id = payload.get("device_id") or payload.get("deviceId")
94
+ max_size = int(payload.get("maxSize") or 1280)
95
+ bit_rate = int(payload.get("bitRate") or 4_000_000)
96
+
97
+ await _stop_stream_for_sid(sid)
98
+
99
+ streamer = ScrcpyStreamer(
100
+ device_id=device_id,
101
+ max_size=max_size,
102
+ bit_rate=bit_rate,
103
+ )
104
+
105
+ try:
106
+ await streamer.start()
107
+ metadata = await streamer.read_video_metadata()
108
+ await sio.emit(
109
+ "video-metadata",
110
+ {
111
+ "deviceName": metadata.device_name,
112
+ "width": metadata.width,
113
+ "height": metadata.height,
114
+ "codec": metadata.codec,
115
+ },
116
+ to=sid,
117
+ )
118
+ except Exception as exc:
119
+ streamer.stop()
120
+ logger.exception("Failed to start scrcpy stream: %s", exc)
121
+ await sio.emit("error", {"message": str(exc)}, to=sid)
122
+ return
123
+
124
+ _socket_streamers[sid] = streamer
125
+ _stream_tasks[sid] = asyncio.create_task(_stream_packets(sid, streamer))
@@ -1 +1 @@
1
- import{j as o}from"./index-D5BALRbT.js";function t(){return o.jsx("div",{className:"p-2",children:o.jsx("h3",{children:"About"})})}export{t as component};
1
+ import{j as o}from"./index-DfI_Z1Cx.js";function t(){return o.jsx("div",{className:"p-2",children:o.jsx("h3",{children:"About"})})}export{t as component};