mirror of
https://github.com/xfgryujk/blivechat.git
synced 2025-01-13 22:00:15 +08:00
GUI插件网络消息移到线程处理
This commit is contained in:
parent
644e36b4eb
commit
0b39380f70
@ -6,6 +6,7 @@ import logging
|
|||||||
from typing import *
|
from typing import *
|
||||||
|
|
||||||
import pubsub.pub as pub
|
import pubsub.pub as pub
|
||||||
|
import wx
|
||||||
|
|
||||||
import blcsdk
|
import blcsdk
|
||||||
import blcsdk.models as sdk_models
|
import blcsdk.models as sdk_models
|
||||||
@ -26,7 +27,7 @@ async def init():
|
|||||||
blc_rooms = await blcsdk.get_rooms()
|
blc_rooms = await blcsdk.get_rooms()
|
||||||
for blc_room in blc_rooms:
|
for blc_room in blc_rooms:
|
||||||
if blc_room.room_id is not None:
|
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:
|
except blcsdk.SdkError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -38,7 +39,10 @@ def shut_down():
|
|||||||
class MsgHandler(blcsdk.BaseHandler):
|
class MsgHandler(blcsdk.BaseHandler):
|
||||||
def on_client_stopped(self, client: blcsdk.BlcPluginClient, exception: Optional[Exception]):
|
def on_client_stopped(self, client: blcsdk.BlcPluginClient, exception: Optional[Exception]):
|
||||||
logger.info('blivechat disconnected')
|
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(
|
def _on_open_plugin_admin_ui(
|
||||||
self, client: blcsdk.BlcPluginClient, message: sdk_models.OpenPluginAdminUiMsg, extra: sdk_models.ExtraData
|
self, client: blcsdk.BlcPluginClient, message: sdk_models.OpenPluginAdminUiMsg, extra: sdk_models.ExtraData
|
||||||
|
@ -1,62 +1,53 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import concurrent.futures
|
||||||
|
import logging
|
||||||
import logging.handlers
|
import logging.handlers
|
||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
import sys
|
import threading
|
||||||
|
from typing import *
|
||||||
|
|
||||||
|
import pubsub.pub as pub
|
||||||
import wx
|
import wx
|
||||||
|
|
||||||
import blcsdk
|
import blcsdk
|
||||||
|
import blcsdk.models as sdk_models
|
||||||
import config
|
import config
|
||||||
import listener
|
import listener
|
||||||
import ui.app
|
import ui.room_config_dialog
|
||||||
|
import ui.room_frame
|
||||||
|
import ui.task_bar_icon
|
||||||
|
|
||||||
logger = logging.getLogger('native-ui')
|
logger = logging.getLogger('native-ui')
|
||||||
|
|
||||||
|
app: Optional['App'] = None
|
||||||
async def main():
|
|
||||||
try:
|
|
||||||
await init()
|
|
||||||
await run()
|
|
||||||
finally:
|
|
||||||
await shut_down()
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
async def init():
|
def main():
|
||||||
init_signal_handlers()
|
init_signal_handlers()
|
||||||
|
|
||||||
init_logging()
|
init_logging()
|
||||||
config.init()
|
config.init()
|
||||||
|
|
||||||
await blcsdk.init()
|
global app
|
||||||
if not blcsdk.is_sdk_version_compatible():
|
app = App()
|
||||||
raise RuntimeError('SDK version is not compatible')
|
|
||||||
|
|
||||||
ui.app.init()
|
logger.info('Running event loop')
|
||||||
await listener.init()
|
app.MainLoop()
|
||||||
|
|
||||||
|
|
||||||
def init_signal_handlers():
|
def init_signal_handlers():
|
||||||
signums = (signal.SIGINT, signal.SIGTERM)
|
def signal_handler(*_args):
|
||||||
try:
|
wx.CallAfter(start_shut_down)
|
||||||
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)
|
|
||||||
|
|
||||||
# 不太安全,但Windows只能用这个
|
for signum in (signal.SIGINT, signal.SIGTERM):
|
||||||
for signum in signums:
|
signal.signal(signum, signal_handler)
|
||||||
signal.signal(signum, signal_handler)
|
|
||||||
|
|
||||||
|
|
||||||
def start_shut_down(*_args):
|
def start_shut_down():
|
||||||
app = wx.GetApp()
|
if app is not None and app.IsMainLoopRunning():
|
||||||
if app is not None:
|
|
||||||
app.ExitMainLoop()
|
app.ExitMainLoop()
|
||||||
else:
|
else:
|
||||||
wx.Exit()
|
wx.Exit()
|
||||||
@ -77,16 +68,120 @@ def init_logging():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def run():
|
class App(wx.App):
|
||||||
logger.info('Running event loop')
|
def __init__(self, *args, **kwargs):
|
||||||
await wx.GetApp().MainLoop()
|
self._network_worker = NetworkWorker()
|
||||||
logger.info('Start to shut down')
|
|
||||||
|
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():
|
class NetworkWorker:
|
||||||
listener.shut_down()
|
def __init__(self):
|
||||||
await blcsdk.shut_down()
|
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__':
|
if __name__ == '__main__':
|
||||||
sys.exit(asyncio.run(main()))
|
main()
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
PyPubSub==4.0.3
|
PyPubSub==4.0.3
|
||||||
wxasync==0.49
|
|
||||||
wxPython==4.2.1
|
wxPython==4.2.1
|
||||||
XlsxWriter==3.2.0
|
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