Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# -*- coding: utf-8 -*- 

2# This file is part of Xpra. 

3# Copyright (C) 2010-2020 Antoine Martin <antoine@xpra.org> 

4# Xpra is released under the terms of the GNU GPL v2, or, at your option, any 

5# later version. See the file COPYING for details. 

6#pylint: disable-msg=E1101 

7 

8import os.path 

9 

10from xpra.os_util import OSX, POSIX 

11from xpra.util import engs 

12from xpra.scripts.config import FALSE_OPTIONS 

13from xpra.server.mixins.stub_server_mixin import StubServerMixin 

14from xpra.log import Logger 

15 

16log = Logger("webcam") 

17 

18 

19""" 

20Mixin for servers that handle webcam forwarding, 

21it just delegates to the webcam source mixin, 

22so each user can have its own webcam device(s). 

23""" 

24class WebcamServer(StubServerMixin): 

25 

26 def __init__(self): 

27 self.webcam_device = "" 

28 self.webcam_encodings = [] 

29 self.webcam_enabled = False 

30 self.webcam_virtual_video_devices = 0 

31 

32 def init(self, opts): 

33 self.webcam_enabled = opts.webcam.lower() not in FALSE_OPTIONS 

34 if os.path.isabs(opts.webcam): 

35 self.webcam_device = opts.webcam 

36 

37 def init_state(self): 

38 #duplicated 

39 self.readonly = False 

40 

41 def threaded_setup(self): 

42 self.init_webcam() 

43 

44 

45 def get_server_features(self, _source) -> dict: 

46 return { 

47 "webcam" : self.webcam_enabled, 

48 "webcam.encodings" : self.webcam_encodings, 

49 "virtual-video-devices" : self.webcam_virtual_video_devices, 

50 } 

51 

52 

53 def get_info(self, _proto) -> dict: 

54 info = { 

55 "" : self.webcam_enabled, 

56 } 

57 if self.webcam_enabled: 

58 info.update({ 

59 "encodings" : self.webcam_encodings, 

60 "virtual-video-devices" : self.webcam_virtual_video_devices, 

61 }) 

62 if self.webcam_device: 

63 info["device"] = self.webcam_device 

64 return {"webcam" : info} 

65 

66 

67 def init_webcam(self): 

68 if not self.webcam_enabled: 

69 return 

70 try: 

71 from xpra.codecs.pillow.decoder import get_encodings 

72 self.webcam_encodings = tuple(x for x in ("png", "jpeg", "webp") if x in get_encodings()) 

73 except Exception as e: 

74 log.error("Error: webcam forwarding disabled:") 

75 log.error(" %s", e) 

76 self.webcam_enabled = False 

77 if self.webcam_device: 

78 self.webcam_virtual_video_devices = 1 

79 else: 

80 self.webcam_virtual_video_devices = self.init_virtual_video_devices() 

81 if self.webcam_virtual_video_devices==0: 

82 self.webcam_enabled = False 

83 

84 def init_virtual_video_devices(self): 

85 log("init_virtual_video_devices") 

86 if not POSIX or OSX: 

87 return 0 

88 try: 

89 from xpra.codecs.v4l2.pusher import Pusher 

90 assert Pusher 

91 except ImportError as e: 

92 log.error("Error: failed to import the virtual video module:") 

93 log.error(" %s", e) 

94 return 0 

95 try: 

96 from xpra.platform.xposix.webcam import get_virtual_video_devices, check_virtual_dir 

97 except ImportError as e: 

98 log.warn("Warning: cannot load webcam components") 

99 log.warn(" %s", e) 

100 log.warn(" webcam forwarding disabled") 

101 return 0 

102 check_virtual_dir() 

103 devices = get_virtual_video_devices() 

104 log.info("found %i virtual video device%s for webcam forwarding", len(devices), engs(devices)) 

105 return len(devices) 

106 

107 def _process_webcam_start(self, proto, packet): 

108 if self.readonly: 

109 return 

110 assert self.webcam_enabled 

111 ss = self.get_server_source(proto) 

112 if not ss: 

113 log.warn("Warning: invalid client source for webcam start") 

114 return 

115 device_id, w, h = packet[1:4] 

116 ss.start_virtual_webcam(device_id, w, h) 

117 

118 def _process_webcam_stop(self, proto, packet): 

119 if self.readonly: 

120 return 

121 ss = self.get_server_source(proto) 

122 if not ss: 

123 log.warn("Warning: invalid client source for webcam start") 

124 return 

125 device_id, message = (list(packet)+[""])[1:3] 

126 ss.stop_virtual_webcam(device_id, message) 

127 

128 def _process_webcam_frame(self, proto, packet): 

129 if self.readonly: 

130 return 

131 ss = self.get_server_source(proto) 

132 if not ss: 

133 log.warn("Warning: invalid client source for webcam frame") 

134 return 

135 device_id, frame_no, encoding, w, h, data = packet[1:7] 

136 ss.process_webcam_frame(device_id, frame_no, encoding, w, h, data) 

137 

138 def init_packet_handlers(self): 

139 if self.webcam_enabled: 

140 self.add_packet_handlers({ 

141 "webcam-start" : self._process_webcam_start, 

142 "webcam-stop" : self._process_webcam_stop, 

143 "webcam-frame" : self._process_webcam_frame, 

144 }, False)