예제 #1
0
class Client:
    def __init__(self):
        self.socket = socket.socket()
        self.socket.settimeout(5)
        self.buffer_size = 2048
        self.vsock = videosocket.VideoSocket(self.socket)
        self.is_video_call = False
        self.videofeed = None
        self.connected = True

    def receive(self):
        while self.connected:
            if self.is_video_call:
                if not self.videofeed:
                    self.videofeed = VideoFeed("client_cam", 1)

                frame = self.videofeed.get_frame()
                self.vsock.vsend(frame)
                rcvd_frame = self.vsock.vreceive()

                try:
                    if rcvd_frame == 2:
                        self.is_video_call = False
                        self.vsock.vsend(bytes("-2", ENCODING))
                        self.videofeed.destroy()
                        continue
                except:
                    pass

                quit = self.videofeed.set_frame(rcvd_frame)
                if quit:
                    # inform other party that user wants to quit
                    self.vsock.vsend(bytes("-1", ENCODING))
                    self.is_video_call = False

            else:
                # free up webcam in case not in use
                if self.videofeed:
                    self.videofeed = None

                msg = self.socket.recv(self.buffer_size)
                try:
                    decoded_msg = msg.decode(ENCODING)
                except:
                    continue
                if decoded_msg == "VIDEO_CALL_START":
                    self.send(bytes("READY_FOR_VIDEO_CALL", ENCODING))
                    self.is_video_call = True

                elif decoded_msg == "READY_FOR_VIDEO_CALL":
                    self.is_video_call = True

                elif decoded_msg == "VIDEO_CALL_INITIATE":
                    self.initiate_video_call()

                elif decoded_msg == "VIDEO_CALL_ACCEPT" or decoded_msg == "VIDEO_CALL_REJECTED":
                    self.send(msg)

                elif "VIDEO_CALL_REQUEST" in decoded_msg:
                    # someone wants to videochat with you
                    from_uname = decoded_msg.split('$')[-1]
                    self.receive_vcall(from_uname)

                else:
                    self.update_gui(msg, False)

    def send(self, msg=None):
        if msg is None:
            msg = msg_box.get()
            msg_box.delete(0, tk.END)
            self.socket.send(bytes(msg, ENCODING))
        else:
            self.socket.send(msg)

    def initiate_video_call(self):
        self.send(bytes("VIDEO_CALL_START", ENCODING))
        usernames = self.socket.recv(self.buffer_size).decode(ENCODING)
        names = usernames.split("$")[:-1]

        num_online = len(names)
        root = tk.Tk()
        root.geometry("300x%s" % (str((2 + num_online) * 100)))
        if num_online == 0:
            l = tk.Label(root,
                         text="No users online, try again later!!",
                         padx=20,
                         pady=10)
            l.pack()
        else:
            l = tk.Label(root,
                         text="Select the person whose face you want to see!!",
                         padx=20,
                         pady=20)
            l.pack()

        for i in range(len(names)):
            b = tk.Button(
                root,
                text=names[i],
                command=lambda name=names[i]: self.decide_target(root, name))
            b.pack()

        qb = tk.Button(root,
                       text="Quit",
                       command=lambda: self.decide_target(root, None))
        qb.pack()
        root.mainloop()

    def decide_target(self, root, target):
        if target:
            self.send(bytes(target, ENCODING))
        else:
            self.send(bytes("VIDEO_CALL_ABORT", ENCODING))
        root.destroy()

    def update_gui(self, msg, is_sent=False):
        display_listbox.insert("end", msg.decode(ENCODING))

    def receive_vcall(self, from_uname):
        # get username of who wants to talk with you
        root = tk.Tk()
        root.geometry("300x300")
        l = tk.Label(root,
                     text="Your beloved %s wants to see your face !!" %
                     (from_uname),
                     padx=20,
                     pady=20)
        l.pack()
        b1 = tk.Button(
            root,
            text="Accept",
            command=lambda: self.send_confirmation(root, from_uname, True))
        b1.pack()

        b2 = tk.Button(
            root,
            text="Reject",
            command=lambda: self.send_confirmation(root, from_uname, False))
        b2.pack()
        root.mainloop()

    def send_confirmation(self, root, accept_from, decision):
        if decision:
            msg = bytes("VIDEO_CALL_ACCEPT", ENCODING)
        else:
            msg = bytes("VIDEO_CALL_REJECTED", ENCODING)
        self.send(msg)
        time.sleep(1)
        self.send(bytes(accept_from, ENCODING))
        root.destroy()