mirror of
https://github.com/xfgryujk/blivechat.git
synced 2025-02-23 18:20:41 +08:00
GUI插件网络消息移到线程处理
This commit is contained in:
parent
644e36b4eb
commit
0b39380f70
@ -6,6 +6,7 @@ import logging
|
||||
from typing import *
|
||||
|
||||
import pubsub.pub as pub
|
||||
import wx
|
||||
|
||||
import blcsdk
|
||||
import blcsdk.models as sdk_models
|
||||
@ -26,7 +27,7 @@ async def init():
|
||||
blc_rooms = await blcsdk.get_rooms()
|
||||
for blc_room in blc_rooms:
|
||||
if blc_room.room_id is not None:
|
||||
_get_or_add_room(blc_room.room_key, blc_room.room_id)
|
||||
wx.CallAfter(_get_or_add_room, blc_room.room_key, blc_room.room_id)
|
||||
except blcsdk.SdkError:
|
||||
pass
|
||||
|
||||
@ -38,7 +39,10 @@ def shut_down():
|
||||
class MsgHandler(blcsdk.BaseHandler):
|
||||
def on_client_stopped(self, client: blcsdk.BlcPluginClient, exception: Optional[Exception]):
|
||||
logger.info('blivechat disconnected')
|
||||
__main__.start_shut_down()
|
||||
wx.CallAfter(__main__.start_shut_down)
|
||||
|
||||
def handle(self, client: blcsdk.BlcPluginClient, command: dict):
|
||||
wx.CallAfter(super().handle, client, command)
|
||||
|
||||
def _on_open_plugin_admin_ui(
|
||||
self, client: blcsdk.BlcPluginClient, message: sdk_models.OpenPluginAdminUiMsg, extra: sdk_models.ExtraData
|
||||
|
@ -1,62 +1,53 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import asyncio
|
||||
import concurrent.futures
|
||||
import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
import threading
|
||||
from typing import *
|
||||
|
||||
import pubsub.pub as pub
|
||||
import wx
|
||||
|
||||
import blcsdk
|
||||
import blcsdk.models as sdk_models
|
||||
import config
|
||||
import listener
|
||||
import ui.app
|
||||
import ui.room_config_dialog
|
||||
import ui.room_frame
|
||||
import ui.task_bar_icon
|
||||
|
||||
logger = logging.getLogger('native-ui')
|
||||
|
||||
|
||||
async def main():
|
||||
try:
|
||||
await init()
|
||||
await run()
|
||||
finally:
|
||||
await shut_down()
|
||||
return 0
|
||||
app: Optional['App'] = None
|
||||
|
||||
|
||||
async def init():
|
||||
def main():
|
||||
init_signal_handlers()
|
||||
|
||||
init_logging()
|
||||
config.init()
|
||||
|
||||
await blcsdk.init()
|
||||
if not blcsdk.is_sdk_version_compatible():
|
||||
raise RuntimeError('SDK version is not compatible')
|
||||
global app
|
||||
app = App()
|
||||
|
||||
ui.app.init()
|
||||
await listener.init()
|
||||
logger.info('Running event loop')
|
||||
app.MainLoop()
|
||||
|
||||
|
||||
def init_signal_handlers():
|
||||
signums = (signal.SIGINT, signal.SIGTERM)
|
||||
try:
|
||||
loop = asyncio.get_running_loop()
|
||||
for signum in signums:
|
||||
loop.add_signal_handler(signum, start_shut_down)
|
||||
except NotImplementedError:
|
||||
def signal_handler(*args):
|
||||
asyncio.get_running_loop().call_soon(start_shut_down, *args)
|
||||
def signal_handler(*_args):
|
||||
wx.CallAfter(start_shut_down)
|
||||
|
||||
# 不太安全,但Windows只能用这个
|
||||
for signum in signums:
|
||||
signal.signal(signum, signal_handler)
|
||||
for signum in (signal.SIGINT, signal.SIGTERM):
|
||||
signal.signal(signum, signal_handler)
|
||||
|
||||
|
||||
def start_shut_down(*_args):
|
||||
app = wx.GetApp()
|
||||
if app is not None:
|
||||
def start_shut_down():
|
||||
if app is not None and app.IsMainLoopRunning():
|
||||
app.ExitMainLoop()
|
||||
else:
|
||||
wx.Exit()
|
||||
@ -77,16 +68,120 @@ def init_logging():
|
||||
)
|
||||
|
||||
|
||||
async def run():
|
||||
logger.info('Running event loop')
|
||||
await wx.GetApp().MainLoop()
|
||||
logger.info('Start to shut down')
|
||||
class App(wx.App):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._network_worker = NetworkWorker()
|
||||
|
||||
self._dummy_timer: Optional[wx.Timer] = None
|
||||
self._task_bar_icon: Optional[ui.task_bar_icon.TaskBarIcon] = None
|
||||
|
||||
self._key_room_frame_dict: Dict[sdk_models.RoomKey, ui.room_frame.RoomFrame] = {}
|
||||
self._room_config_dialog: Optional[ui.room_config_dialog.RoomConfigDialog] = None
|
||||
|
||||
super().__init__(*args, clearSigInt=False, **kwargs)
|
||||
self.SetExitOnFrameDelete(False)
|
||||
|
||||
def OnInit(self):
|
||||
# 这个定时器只是为了及时响应信号,因为只有处理UI事件时才会唤醒主线程
|
||||
self._dummy_timer = wx.Timer(self)
|
||||
self._dummy_timer.Start(1000)
|
||||
self.Bind(wx.EVT_TIMER, lambda _event: None, self._dummy_timer)
|
||||
|
||||
self._task_bar_icon = ui.task_bar_icon.TaskBarIcon()
|
||||
|
||||
pub.subscribe(self._on_add_room, 'add_room')
|
||||
pub.subscribe(self._on_del_room, 'del_room')
|
||||
pub.subscribe(self._on_room_frame_close, 'room_frame_close')
|
||||
pub.subscribe(self._on_add_room, 'open_room')
|
||||
pub.subscribe(self._on_open_room_config_dialog, 'open_room_config_dialog')
|
||||
|
||||
self._network_worker.init()
|
||||
return True
|
||||
|
||||
def OnExit(self):
|
||||
logger.info('Start to shut down')
|
||||
|
||||
self._network_worker.start_shut_down()
|
||||
self._network_worker.join(10)
|
||||
|
||||
return super().OnExit()
|
||||
|
||||
def _on_add_room(self, room_key: sdk_models.RoomKey):
|
||||
if room_key in self._key_room_frame_dict:
|
||||
return
|
||||
|
||||
room_frame = self._key_room_frame_dict[room_key] = ui.room_frame.RoomFrame(None, room_key)
|
||||
room_frame.Show()
|
||||
|
||||
def _on_del_room(self, room_key: sdk_models.RoomKey):
|
||||
room_frame = self._key_room_frame_dict.pop(room_key, None)
|
||||
if room_frame is not None:
|
||||
room_frame.Close(True)
|
||||
|
||||
def _on_room_frame_close(self, room_key: sdk_models.RoomKey):
|
||||
self._key_room_frame_dict.pop(room_key, None)
|
||||
|
||||
def _on_open_room_config_dialog(self):
|
||||
if self._room_config_dialog is None or self._room_config_dialog.IsBeingDeleted():
|
||||
self._room_config_dialog = ui.room_config_dialog.RoomConfigDialog(None)
|
||||
self._room_config_dialog.Show()
|
||||
|
||||
|
||||
async def shut_down():
|
||||
listener.shut_down()
|
||||
await blcsdk.shut_down()
|
||||
class NetworkWorker:
|
||||
def __init__(self):
|
||||
self._worker_thread = threading.Thread(
|
||||
target=asyncio.run, args=(self._worker_thread_func(),), daemon=True
|
||||
)
|
||||
self._thread_init_future = concurrent.futures.Future()
|
||||
|
||||
self._loop: Optional[asyncio.AbstractEventLoop] = None
|
||||
self._shut_down_event: Optional[asyncio.Event] = None
|
||||
|
||||
def init(self):
|
||||
self._worker_thread.start()
|
||||
self._thread_init_future.result(10)
|
||||
|
||||
def start_shut_down(self):
|
||||
if self._shut_down_event is not None:
|
||||
self._loop.call_soon_threadsafe(self._shut_down_event.set)
|
||||
|
||||
def join(self, timeout=None):
|
||||
self._worker_thread.join(timeout)
|
||||
return not self._worker_thread.is_alive()
|
||||
|
||||
async def _worker_thread_func(self):
|
||||
self._loop = asyncio.get_running_loop()
|
||||
try:
|
||||
try:
|
||||
await self._init_in_worker_thread()
|
||||
self._thread_init_future.set_result(None)
|
||||
except BaseException as e:
|
||||
self._thread_init_future.set_exception(e)
|
||||
return
|
||||
|
||||
await self._run()
|
||||
finally:
|
||||
await self._shut_down()
|
||||
|
||||
async def _init_in_worker_thread(self):
|
||||
await blcsdk.init()
|
||||
if not blcsdk.is_sdk_version_compatible():
|
||||
raise RuntimeError('SDK version is not compatible')
|
||||
|
||||
await listener.init()
|
||||
|
||||
self._shut_down_event = asyncio.Event()
|
||||
|
||||
async def _run(self):
|
||||
logger.info('Running network thread event loop')
|
||||
await self._shut_down_event.wait()
|
||||
logger.info('Network thread start to shut down')
|
||||
|
||||
@staticmethod
|
||||
async def _shut_down():
|
||||
listener.shut_down()
|
||||
await blcsdk.shut_down()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(asyncio.run(main()))
|
||||
main()
|
||||
|
@ -1,4 +1,3 @@
|
||||
PyPubSub==4.0.3
|
||||
wxasync==0.49
|
||||
wxPython==4.2.1
|
||||
XlsxWriter==3.2.0
|
||||
|
@ -1,61 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
from typing import *
|
||||
|
||||
import pubsub.pub as pub
|
||||
import wxasync
|
||||
|
||||
import blcsdk.models as sdk_models
|
||||
import ui.room_config_dialog
|
||||
import ui.room_frame
|
||||
import ui.task_bar_icon
|
||||
|
||||
logger = logging.getLogger('native-ui.' + __name__)
|
||||
|
||||
_app: Optional['App'] = None
|
||||
|
||||
|
||||
def init():
|
||||
global _app
|
||||
_app = App()
|
||||
|
||||
|
||||
class App(wxasync.WxAsyncApp):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._task_bar_icon: Optional[ui.task_bar_icon.TaskBarIcon] = None
|
||||
|
||||
super().__init__(*args, clearSigInt=False, **kwargs)
|
||||
self.SetExitOnFrameDelete(False)
|
||||
|
||||
self._key_room_frame_dict: Dict[sdk_models.RoomKey, ui.room_frame.RoomFrame] = {}
|
||||
self._room_config_dialog: Optional[ui.room_config_dialog.RoomConfigDialog] = None
|
||||
|
||||
def OnInit(self):
|
||||
self._task_bar_icon = ui.task_bar_icon.TaskBarIcon()
|
||||
|
||||
pub.subscribe(self._on_add_room, 'add_room')
|
||||
pub.subscribe(self._on_del_room, 'del_room')
|
||||
pub.subscribe(self._on_room_frame_close, 'room_frame_close')
|
||||
pub.subscribe(self._on_add_room, 'open_room')
|
||||
pub.subscribe(self._on_open_room_config_dialog, 'open_room_config_dialog')
|
||||
return True
|
||||
|
||||
def _on_add_room(self, room_key: sdk_models.RoomKey):
|
||||
if room_key in self._key_room_frame_dict:
|
||||
return
|
||||
|
||||
room_frame = self._key_room_frame_dict[room_key] = ui.room_frame.RoomFrame(None, room_key)
|
||||
room_frame.Show()
|
||||
|
||||
def _on_del_room(self, room_key: sdk_models.RoomKey):
|
||||
room_frame = self._key_room_frame_dict.pop(room_key, None)
|
||||
if room_frame is not None:
|
||||
room_frame.Close(True)
|
||||
|
||||
def _on_room_frame_close(self, room_key: sdk_models.RoomKey):
|
||||
self._key_room_frame_dict.pop(room_key, None)
|
||||
|
||||
def _on_open_room_config_dialog(self):
|
||||
if self._room_config_dialog is None or self._room_config_dialog.IsBeingDeleted():
|
||||
self._room_config_dialog = ui.room_config_dialog.RoomConfigDialog(None)
|
||||
self._room_config_dialog.Show()
|
Loading…
Reference in New Issue
Block a user