from __future__ import unicode_literals # So that `print` can print Unicode characters in names import logging import sys logger = logging.getLogger(__name__) def get_microphones(audio): """ Get audio devices which have input channels. :param audio: An instance of PyAudio to use. :type audio: pyaudio.PyAudio :return: An interator of PaAudio dicts containing information about the microphone devices. :rtype: Iterator[dict] """ for i in range(audio.get_device_count()): device = audio.get_device_info_by_index(i) if device["maxInputChannels"] > 0: yield device def choose_mic_interactive(audio): """ Choose a microphone to use, interactively in the CLI. :param audio: An instance of PyAudio to use. :type audio: pyaudio.PyAudio :return: A dictionary from PyAudio containing information about the microphone to use, or None if there is no microphone. :rtype: dict | None """ microphones = list(get_microphones(audio)) if len(microphones) == 0: return None print("Found {} microphones:".format(len(microphones))) for i, mic in enumerate(microphones): print("- {}: {}".format(i, mic["name"])) chosen_microphone = None while chosen_microphone is None: chosen = raw_input("Which device would you like to use?\n> ") try: chosen = int(chosen) if chosen < 0 or chosen >= len(microphones): raise ValueError() chosen_microphone = microphones[chosen] except ValueError: print("Please enter a number between 0 and {}".format(len(microphones)-1)) logger.info("Chose microphone \"{}\"".format(chosen_microphone["name"])) return chosen_microphone def choose_mic_default(audio): """ Get the system's default microphone to use. :param audio: An instance of PyAudio to use. :type audio: pyaudio.PyAudio :return: A dictionary from PyAudio containing information about the microphone to use, or None if there is no microphone. :rtype: dict | None """ try: return audio.get_default_input_device_info() except IOError: return None def choose_mic_arguments(audio): """ Get a microphone to use from command line arguments. :param audio: An instance of PyAudio to use. :type audio: pyaudio.PyAudio :return: A dictionary from PyAudio containing information about the microphone to use, or None if there is no microphone satisfied by the arguments. :rtype: dict | None """ microphone_name = None for i, arg in enumerate(sys.argv): if arg == "--microphone" and len(sys.argv) > i+1: microphone_name = sys.argv[i+1].strip() if arg.startswith("--microphone="): pre_fix_len = len("--microphone=") microphone_name = arg[pre_fix_len:].strip() if not microphone_name: return None available_mics = list(get_microphones(audio)) for mic in available_mics: if mic["name"] == microphone_name: return mic available_mic_names = [mic["name"] for mic in available_mics] logger.warning("Microphone \"{}\" not found. Choose one of {}" .format(microphone_name, available_mic_names)) return None def choose_mic(audio): """ Get a microphone to use. Firstly, tries to see if there's an application argument specifying the microphone to use. If not, get the default microphone. :param audio: An instance of PyAudio to use. :type audio: pyaudio.PyAudio :return: A dictionary from PyAudio containing information about the microphone to use, or None if there is no microphone. :rtype: dict | None """ chosen_mic = choose_mic_arguments(audio) if chosen_mic: return chosen_mic return choose_mic_default(audio)