Source code for webcface.client_impl

import threading
import logging
from typing import List
import webcface.client_data
import webcface.message
import webcface.client
import webcface.canvas2d_base
import webcface.image_frame
import webcface


[docs] def on_recv( wcli: "webcface.client.Client", data: webcface.client_data.ClientData, message: bytes, ) -> None: sync_members: List[str] = [] if len(message) > 0: for m in webcface.message.unpack(message): if isinstance(m, webcface.message.SyncInitEnd): data.svr_name = m.svr_name data.svr_version = m.ver data.svr_hostname = m.hostname data.self_member_id = m.member_id data.sync_init_end = True if isinstance(m, webcface.message.Ping): data.queue_msg_always([webcface.message.Ping.new()]) if isinstance(m, webcface.message.PingStatus): data.ping_status = m.status for member2 in wcli.members(): on_ping = data.on_ping.get(member2.name) if on_ping is not None: on_ping(member2) if isinstance(m, webcface.message.Sync): member = data.get_member_name_from_id(m.member_id) data.sync_time_store.set_recv(member, m.time) sync_members.append(member) if isinstance(m, webcface.message.SyncInit): data.value_store.init_member(m.member_name) data.text_store.init_member(m.member_name) data.func_store.init_member(m.member_name) data.view_store.init_member(m.member_name) data.canvas2d_store.init_member(m.member_name) data.canvas3d_store.init_member(m.member_name) data.log_store.init_member(m.member_name) data.member_ids[m.member_name] = m.member_id data.member_lib_name[m.member_id] = m.lib_name data.member_lib_ver[m.member_id] = m.lib_ver data.member_remote_addr[m.member_id] = m.addr if data.on_member_entry is not None: data.on_member_entry(wcli.member(m.member_name)) if isinstance(m, webcface.message.ValueRes): member, field = data.value_store.get_req(m.req_id, m.sub_field) data.value_store.set_recv(member, field, m.data) on_change = data.on_value_change.get(member, {}).get(field) if on_change is not None: on_change(wcli.member(member).value(field)) if isinstance(m, webcface.message.ValueEntry): member = data.get_member_name_from_id(m.member_id) data.value_store.set_entry(member, m.field) on_entry = data.on_value_entry.get(member) if on_entry is not None: on_entry(wcli.member(member).value(m.field)) if isinstance(m, webcface.message.TextRes): member, field = data.text_store.get_req(m.req_id, m.sub_field) data.text_store.set_recv(member, field, m.data) on_change = data.on_text_change.get(member, {}).get(field) if on_change is not None: on_change(wcli.member(member).variant(field)) if isinstance(m, webcface.message.TextEntry): member = data.get_member_name_from_id(m.member_id) data.text_store.set_entry(member, m.field) on_entry = data.on_text_entry.get(member) if on_entry is not None: on_entry(wcli.member(member).text(m.field)) if isinstance(m, webcface.message.ImageRes): member, field = data.image_store.get_req(m.req_id, m.sub_field) data.image_store.set_recv( member, field, webcface.image_frame.ImageFrame( m.width, m.height, m.data, m.color_mode, m.cmp_mode ), ) on_change = data.on_image_change.get(member, {}).get(field) if on_change is not None: on_change(wcli.member(member).image(field)) if isinstance(m, webcface.message.ImageEntry): member = data.get_member_name_from_id(m.member_id) data.image_store.set_entry(member, m.field) on_entry = data.on_image_entry.get(member) if on_entry is not None: on_entry(wcli.member(member).image(m.field)) if isinstance(m, webcface.message.ViewRes): member, field = data.view_store.get_req(m.req_id, m.sub_field) v_prev = data.view_store.get_recv(member, field) if v_prev is None: v_prev = webcface.view.ViewData() data.view_store.set_recv(member, field, v_prev) if m.ids is not None: v_prev.ids = m.ids for i, c in m.data_diff.items(): v_prev.components[i] = c on_change = data.on_view_change.get(member, {}).get(field) if on_change is not None: on_change(wcli.member(member).view(field)) if isinstance(m, webcface.message.ViewEntry): member = data.get_member_name_from_id(m.member_id) data.view_store.set_entry(member, m.field) on_entry = data.on_view_entry.get(member) if on_entry is not None: on_entry(wcli.member(member).view(m.field)) if isinstance(m, webcface.message.Canvas2DRes): member, field = data.canvas2d_store.get_req(m.req_id, m.sub_field) c2_prev = data.canvas2d_store.get_recv(member, field) if c2_prev is None: c2_prev = webcface.canvas2d.Canvas2DData(1.0, 1.0) data.canvas2d_store.set_recv(member, field, c2_prev) c2_prev.width = m.width c2_prev.height = m.height if m.ids is not None: c2_prev.ids = m.ids for i, c2 in m.data_diff.items(): c2_prev.components[i] = c2 on_change = data.on_canvas2d_change.get(member, {}).get(field) if on_change is not None: on_change(wcli.member(member).canvas2d(field)) if isinstance(m, webcface.message.Canvas2DEntry): member = data.get_member_name_from_id(m.member_id) data.canvas2d_store.set_entry(member, m.field) on_entry = data.on_canvas2d_entry.get(member) if on_entry is not None: on_entry(wcli.member(member).canvas2d(m.field)) if isinstance(m, webcface.message.Canvas3DRes): member, field = data.canvas3d_store.get_req(m.req_id, m.sub_field) c3_prev = data.canvas3d_store.get_recv(member, field) if c3_prev is None: c3_prev = webcface.canvas3d.Canvas3DData() data.canvas3d_store.set_recv(member, field, c3_prev) if m.ids is not None: c3_prev.ids = m.ids for i, c3 in m.data_diff.items(): c3_prev.components[i] = c3 on_change = data.on_canvas3d_change.get(member, {}).get(field) if on_change is not None: on_change(wcli.member(member).canvas3d(field)) if isinstance(m, webcface.message.Canvas3DEntry): member = data.get_member_name_from_id(m.member_id) data.canvas3d_store.set_entry(member, m.field) on_entry = data.on_canvas3d_entry.get(member) if on_entry is not None: on_entry(wcli.member(member).canvas3d(m.field)) if isinstance(m, webcface.message.LogRes): member, field = data.log_store.get_req(m.req_id, m.sub_field) log_data = data.log_store.get_recv(member, field) if log_data is None: log_data = webcface.log_handler.LogData() data.log_store.set_recv(member, field, log_data) log_data.data.extend(m.log) if ( webcface.Log.keep_lines >= 0 and len(log_data.data) > webcface.Log.keep_lines ): del log_data.data[: -webcface.Log.keep_lines] on_change = data.on_log_change.get(member) if on_change is not None: on_change(wcli.member(member).log()) if isinstance(m, webcface.message.LogEntry): member = data.get_member_name_from_id(m.member_id) data.log_store.set_entry(member, m.field) on_entry = data.on_log_entry.get(member) if on_entry is not None: on_entry(wcli.member(member).log(m.field)) if isinstance(m, webcface.message.FuncInfo): member = data.get_member_name_from_id(m.member_id) data.func_store.set_entry(member, m.field) data.func_store.set_recv(member, m.field, m.func_info) on_entry = data.on_func_entry.get(member) if on_entry is not None: on_entry(wcli.member(member).func(m.field)) if isinstance(m, webcface.message.Call): func_info = data.func_store.get_recv(data.self_member_name, m.field) if func_info is not None: data.queue_msg_always( [ webcface.message.CallResponse.new( m.caller_id, m.caller_member_id, True ) ] ) r = webcface.func_info.PromiseData( webcface.field.Field(data, data.self_member_name, m.field) ) func_info.run(r, m.args) p = webcface.func_info.Promise(r) @p.on_finish def on_finish(p: webcface.func_info.Promise): data.queue_msg_always( [ webcface.message.CallResult.new( m.caller_id, m.caller_member_id, p.is_error, p.rejection if p.is_error else p.response, ) ] ) else: data.queue_msg_always( [ webcface.message.CallResponse.new( m.caller_id, m.caller_member_id, False ) ] ) if isinstance(m, webcface.message.CallResponse): try: r = data.func_result_store.get_result(m.caller_id) r._set_reach(m.started) if not m.started: data.func_result_store.del_result(m.caller_id) except IndexError: data.logger_internal.error( f"error receiving call response id={m.caller_id}" ) if isinstance(m, webcface.message.CallResult): try: r = data.func_result_store.get_result(m.caller_id) r._set_finish(m.result, m.is_error) data.func_result_store.del_result(m.caller_id) except IndexError: data.logger_internal.error( f"error receiving call result id={m.caller_id}" ) for member in sync_members: on_sync = data.on_sync.get(member) if on_sync is not None: on_sync(wcli.member(member))
[docs] def sync_data_first( data: webcface.client_data.ClientData, ) -> List[webcface.message.MessageBase]: msgs: List[webcface.message.MessageBase] = [] msgs.append( webcface.message.SyncInit.new( data.self_member_name, "python", webcface.__version__ ) ) with data.value_store.lock: for m, r in data.value_store.transfer_req().items(): for k, i in r.items(): msgs.append(webcface.message.ValueReq.new(m, k, i)) with data.text_store.lock: for m, r in data.text_store.transfer_req().items(): for k, i in r.items(): msgs.append(webcface.message.TextReq.new(m, k, i)) with data.image_store.lock: for m, r in data.image_store.transfer_req().items(): for k, i in r.items(): info = data.image_store.get_req_info(m, k) if info is None: info = webcface.image_frame.ImageReq( None, None, None, None, None, None ) msgs.append(webcface.message.ImageReq.new(m, k, i, info)) with data.view_store.lock: for m, r in data.view_store.transfer_req().items(): for k, i in r.items(): msgs.append(webcface.message.ViewReq.new(m, k, i)) with data.canvas2d_store.lock: for m, r in data.canvas2d_store.transfer_req().items(): for k, i in r.items(): msgs.append(webcface.message.Canvas2DReq.new(m, k, i)) with data.canvas3d_store.lock: for m, r in data.canvas3d_store.transfer_req().items(): for k, i in r.items(): msgs.append(webcface.message.Canvas3DReq.new(m, k, i)) with data.log_store.lock: for m, r2 in data.log_store.transfer_req().items(): for k, i in r.items(): msgs.append(webcface.message.LogReq.new(m, k, i)) msgs.extend(sync_data(data, True)) return msgs
[docs] def sync_data( data: webcface.client_data.ClientData, is_first: bool, ) -> List[webcface.message.MessageBase]: msgs: List[webcface.message.MessageBase] = [] msgs.append(webcface.message.Sync.new()) with data.value_store.lock: for k, v in data.value_store.transfer_send(is_first).items(): msgs.append(webcface.message.Value.new(k, v)) with data.text_store.lock: for k, v2 in data.text_store.transfer_send(is_first).items(): msgs.append(webcface.message.Text.new(k, v2)) with data.image_store.lock: for k, v8 in data.image_store.transfer_send(is_first).items(): msgs.append( webcface.message.Image.new( k, v8.data, v8.width, v8.height, v8.color_mode, v8.compress_mode ) ) with data.view_store.lock: view_send_prev = data.view_store.get_send_prev(is_first) view_send = data.view_store.transfer_send(is_first) for k, v4 in view_send.items(): v_prev = view_send_prev.get(k) v_diff = {} for i in v4.ids: if ( v_prev is None or i not in v_prev.components or v_prev.components[i] != v4.components[i] ): v_diff[i] = v4.components[i] ids_changed = v_prev is None or v_prev.ids != v4.ids msgs.append( webcface.message.View.new(k, v_diff, (v4.ids if ids_changed else None)) ) with data.canvas2d_store.lock: canvas2d_send_prev = data.canvas2d_store.get_send_prev(is_first) canvas2d_send = data.canvas2d_store.transfer_send(is_first) for k, v5 in canvas2d_send.items(): c2_prev = canvas2d_send_prev.get(k) c2_diff = {} for i in v5.ids: if ( c2_prev is None or i not in c2_prev.components or c2_prev.components[i] != v5.components[i] ): c2_diff[i] = v5.components[i] ids_changed = c2_prev is None or c2_prev.ids != v5.ids msgs.append( webcface.message.Canvas2D.new( k, v5.width, v5.height, c2_diff, (v5.ids if ids_changed else None) ) ) with data.canvas3d_store.lock: canvas3d_send_prev = data.canvas3d_store.get_send_prev(is_first) canvas3d_send = data.canvas3d_store.transfer_send(is_first) for k, v6 in canvas3d_send.items(): c3_prev = canvas3d_send_prev.get(k) c3_diff = {} for i in v6.ids: if ( c3_prev is None or i not in c3_prev.components or c3_prev.components[i] != v6.components[i] ): c3_diff[i] = v6.components[i] ids_changed = c3_prev is None or c3_prev.ids != v6.ids msgs.append( webcface.message.Canvas3D.new( k, c3_diff, (v6.ids if ids_changed else None) ) ) with data.log_store.lock: log_send = data.log_store.transfer_send(is_first) for k, v7 in log_send.items(): if is_first: log_send_data = v7.data else: log_send_data = v7.data[v7.sent_lines :] v7.sent_lines = len(v7.data) if len(log_send_data) > 0: msgs.append(webcface.message.Log.new(k, log_send_data)) with data.func_store.lock: for k, v3 in data.func_store.transfer_send(is_first).items(): if not k.startswith("."): msgs.append(webcface.message.FuncInfo.new(k, v3)) return msgs