예제 #1
0
def set_name(client: Client, formatter: F = None) -> None:
    """
    "Change my name" client menu option.

    ---
    Arguments
    ---

        client (Client)
    The client instance which the name will be changed.

        formatter (Formatter, None)
    A Formatter to format some of the screen text.
    """

    # If a string Formatter was not provided,...
    if formatter is None:

        # ... instantiates a new one.
        formatter = F().magenta()

    # Asks the user for the client name until it is valid.
    while True:
        print(formatter.erase(title()))
        print(_l(formatter.erase('Choose how you want to be called.')))

        try:

            # Waits for the user to provide the client name.
            client.set_name(input(_lt('Your name: ')))

            break

        # Empty name.
        except InvalidNameError:
            err = 'You must provide a name!'

        print(_lt(error(err)))
        press_enter_to('try again', F().red(), F().white())
예제 #2
0
def server_option() -> None:
    """
    "Server" main menu option.
    """

    # Instantiates a brand new server.
    server = Server(GREEN)

    try:
        while True:
            print(F().blue(title()))
            print(_l(F().blue('Configure the connection for this server.')))

            try:

                # Waits for the user to provide the server port number.
                port = input(
                    _lt('Port number [{}]: '.format(
                        F().bold().magenta(DEFAULT_PORT))))

                print()

                # Sets the feedback animation thread...
                thread = Thread(target=ellipsis,
                                args=(_l('Starting'), F().yellow()),
                                daemon=True)

                # ... and starts it.
                thread.start()

                try:

                    # Binds the port number to the server and tries to connect.
                    server.connect(port=port)

                # Ctrl+C pressed.
                except (EOFError, KeyboardInterrupt):

                    # Stops the feedback animation thread.
                    thread.alive = False

                    print(_lt(_lt(error('Operation canceled by the user!'))))
                    press_enter_to('try again', F().red(), F().white())

                    continue

                # Stops the feedback animation thread when the connection is established.
                thread.alive = False

                print(_lt(_lt(success('Server started successfully!'))))
                press_enter_to('continue', F().green(), F().white())

                break

            # Port is not valid.
            except InvalidPortError:
                err = 'The provided port number is invalid!'

            # Port is already in use.
            except PortAlreadyUsedError as _e:
                err = 'The port number {:d} is already in use!'.format(_e.port)

            # Port number out of range.
            except PortOutOfRangeError:
                err = 'The port number must be between 0 and 65535!'

            # Stops the feedback animation thread.
            thread.alive = False

            print(_lt(_lt(error(err))))
            press_enter_to('try again', F().red(), F().white())

        server.log(F().green(title(clear_screen=False)))

        # Gets the connection address.
        host, port = server.address()

        # Shows the address in the log.
        server.log(
            _lt(
                label(F().bold().green(
                    'Connection established at {}:{}!'.format(host, port)))))

        # Info message.
        server.log(_lt(label(F().cyan('Recording audio through microphone'))))
        server.log(_lt(label(F().bold().blue('Press Ctrl+C to shutdown'))))

        try:

            # Runs this until Ctrl+C is pressed.
            while True:

                # Accepts a new client.
                client = server.hello()

                # Starts the thread that handles this client.
                Thread(target=handle_client,
                       args=(
                           server,
                           client,
                       ),
                       daemon=True).start()

        # Ctrl+C pressed.
        except (EOFError, KeyboardInterrupt):
            server.log(_ltb(label(error('Closing connection...'))))

            # Shutdowns the server.
            server.disconnect()

            press_enter_to('back to main menu', F().red(), F().white())

    # Ctrl+C pressed.
    except (EOFError, KeyboardInterrupt):
        pass

    # Shutdowns the server.
    server.disconnect()

    del server
예제 #3
0
def client_option() -> None:
    """
    "Client" main menu option.
    """

    # Instantiates a brand new client.
    client = Client()

    try:

        # Waits for the user to provide the client name.
        set_name(client, F().blue())

        while True:
            print(F().magenta(title()))
            print(
                _l(F().magenta('Welcome, {}!'.format(F().bold(
                    client.get_name())))))
            print(_ltb('What do you want to do?'))

            # Sets the client menu options, with their respective methods.
            options = [['Connect to a server', 'connect'],
                       ['Change my name', 'set_name']]

            # Lists the options.
            for i, option in enumerate(options):
                print(_l(label(option[0], F().red(i + 1), F())))

            print(_l(label('Quit to main menu', F().red(0), F())))

            # Reads the chosen option.
            try:
                opt = int(input(_lt('Your option: ')))

                # Checks whether the option is available.
                if opt not in range(0, len(options) + 1):
                    raise ValueError()

            # Invalid or nonexisting option.
            except ValueError:
                print(_lt(error('Invalid option!')))
                press_enter_to('try again', F().red(), F().white())

                continue

            # If the option is 0, quit to main menu.
            if not opt:
                break

            try:

                # If no, runs the corresponding function.
                globals()[options[opt - 1][1]](client)

            # Ctrl+C pressed.
            except (EOFError, KeyboardInterrupt):
                pass

    # Ctrl+C pressed.
    except (EOFError, KeyboardInterrupt):
        pass

    del client
예제 #4
0
def connect(client: Client) -> None:
    """
    "Connect to a server" client menu option.

    ---
    Arguments
    ---

        client (Client)
    The client instance which wants to connect to a server.
    """

    # Asks the user for the modulation type until it is valid.
    while True:
        print(F().magenta(title()))
        print(_l(F().magenta('Choose a modulation type.\n')))

        # Sets the available modulation types.
        options = [
            [
                '{} - {}'.format(F().bold('AM'),
                                 F().italic('Amplitude Modulation')), AM
            ],
            [
                '{} - {}'.format(
                    F().bold('AM-SC'),
                    F().italic(
                        'Amplitude Modulation with Suppressed Carrier')), AM_SC
            ], [F().italic('No modulation'), NO_MOD]
        ]

        # Lists the options.
        for i, option in enumerate(options):
            print(_l(label(option[0], F().red(i + 1), F())))

        # Reads the chosen option.
        try:
            opt = int(input(_lt('Your option: ')))

            # Checks whether the option is avaliable.
            if opt not in range(1, len(options) + 1):
                raise ValueError()

        # Invalid or nonexisting option.
        except ValueError:
            print(_lt(error('Invalid option!')))
            press_enter_to('try again', F().red(), F().white())

            continue

        # If the option is 0, go back to client menu.
        if not opt:
            break

        # If no, saves the modulation type in a variable.
        modulation = options[opt - 1][1]

        # Goes to the next step.
        break

    # Asks the user for the connection settings until they are valid.
    while True:
        print(F().magenta(title()))
        print(_l(F().magenta('Configure the connection with the server.')))

        try:

            # Waits for the user to provide the hostname.
            host = input(
                _lt('Hostname [{}]: '.format(
                    F().bold().magenta(DEFAULT_HOST))))

            # Waits for the user to provide the port number.
            port = input(
                _l('Port number [{}]: '.format(
                    F().bold().magenta(DEFAULT_PORT))))

            print()

            # Sets the feedback animation thread...
            thread = Thread(target=ellipsis,
                            args=(_l('Connecting'), F().yellow()),
                            daemon=True)

            # ... and starts it.
            thread.start()

            try:

                # Tries to connect with the server.
                client.connect(modulation, host, port)

            # Ctrl+C pressed.
            except (EOFError, KeyboardInterrupt):

                # Stops the feedback animation thread.
                thread.alive = False

                print(_lt(_lt(error('Operation canceled by the user!'))))
                press_enter_to('try again', F().red(), F().white())

                continue

            # Stops the feedback animation thread when the connection is established.
            thread.alive = False

            print(_lt(_lt(success('Connection established!'))))
            press_enter_to('continue', F().green(), F().white())

            # Sends a confirmation of receiving to the server.
            client.send_str('OK')

            break

        # Connection with the server was refused.
        except ConnectionRefusedError:
            err = 'The connection with this server was refused!'

        # Connection timeout.
        except ConnectionTimeoutError:
            err = 'The connection attempt has timed out!'

        # Port is not valid.
        except InvalidPortError:
            err = 'Invalid port number!'

        # Unknown or nonexistent host.
        except UnknownHostError:
            err = 'Unknown host!'

        # Stops the feedback animation thread.
        thread.alive = False

        print(_lt(_lt(error(err))))
        press_enter_to('try again', F().red(), F().white())

    # Receives some informations and instructions from the server.
    client.log(client.recv_str())
    client.log(client.recv_str())

    # Opens a new speaker.
    with sd.OutputStream(blocksize=CHUNK_SIZE,
                         channels=CHANNELS,
                         dtype=np.int16,
                         samplerate=FRAME_RATE) as speaker:
        try:

            # Receives the first package.
            package = client.recv()

            # Wait for new packages from the server while they are not empty.
            while len(package) != 0:

                # Gets the audio from the package.
                received = M(modulation, package)

                # If the client chosen no modulated audio,...
                if modulation == NO_MOD:

                    # ... then just speaks the original package...
                    speaker.write(received.output())

                    # ... and receives the next one.
                    package = client.recv()

                    continue

                # Demodulates the received audio.
                demodulated = received.demodulate()

                # Filters the demodulated audio.
                filtered = demodulated.lowpass()

                # Outputs the filtered audio in the speaker.
                speaker.write(filtered.output())

                # Receives the next package.
                package = client.recv()

            # Logs the server shutdown.
            client.log(_ltb(label(error('The server has been shut down!'))))

        # The server has shut down.
        except ConnectionResetError:

            # Logs the server shutdown.
            client.log(_ltb(label(error('The server has been shut down!'))))

        # Ctrl+C pressed.
        except (EOFError, KeyboardInterrupt):

            # Logs the client disconnecting.
            client.log(_ltb(label(error('Disconnecting from the server...'))))

    # Disconnects from the server.
    client.disconnect()

    press_enter_to('back to the client menu', F().red(), F().white())
예제 #5
0
    while True:
        print(F().blue(header()))

        if _video_file is None:

            # Let the user set the input video file.
            _video_file = input(input_message)
        else:

            # Print in case of passing by argument.
            print('{}{}'.format(input_message, _video_file))

        # Invalid input.
        if not _video_file:
            print(_lt(error('Invalid input!')))
            press_enter_to('try again', F().red(), F().white())

            _video_file = None

            continue

        # Input is not a file.
        if not path.isfile(_video_file):
            print(_lt(error('The input path is not a valid file!')))
            press_enter_to('try again', F().red(), F().white())

            _video_file = None

            continue