def devices(): """ return dict with names and ids of sound devices for playback (aka speakers) """ result=dict() if HAS_SOUNDCARD: for m in soundcard.all_speakers(): result[m.name]=m.id return result
async def async_step_user(self, user_input=None): """Handle the initial step.""" errors = {} if user_input is not None: try: info = await validate_input(self.hass, user_input) return self.async_create_entry(title=info["title"], data=user_input) except InvalidSinkID: errors["base"] = "invalid_sink_id" except Exception: # pylint: disable=broad-except _LOGGER.exception("Unexpected exception") errors["base"] = "unknown" sinks = {sink.id: sink.name + ':' + sink.id for sink in all_speakers()} DATA_SCHEMA = vol.Schema({ vol.Required(CONF_NAME, default="PulseAudio Speaker"): str, vol.Required(CONF_SINK, default=default_speaker().id): vol.In(sinks) }) return self.async_show_form(step_id="user", data_schema=DATA_SCHEMA, errors=errors)
def scard_query_devices(self) -> List[Dict[str, Any]]: speakers = soundcard.all_speakers() result = [] for speaker in speakers: info = speaker._get_info() info['id'] = speaker.id result.append(info) return result
def get_speakers() -> List[str]: """ :return: All speaker names, plus DEFAULT_SOUND_NAME. """ l = [DEFAULT_SOUND_NAME] for m in sc.all_speakers(): l.append(m.name) return l
def scard_query_devices(self) -> List[Dict[int, Dict[str, Any]]]: speakers = soundcard.all_speakers() result = [] for idx, speaker in enumerate(speakers): info = speaker._get_info() info['id'] = speaker.id result.append({idx: info}) return result
def start_mixer(): all_speakers = sc.all_speakers() (speaker1, ) = filter(speaker_name_matcher, all_speakers) output1 = speaker1.player(samplerate=SAMPLERATE, blocksize=BLOCKSIZE) output1.__enter__() all_inputs = sc.all_microphones() (mic1, mic2) = filter(mic_name_matcher, all_inputs) input1 = mic1.recorder(samplerate=SAMPLERATE, blocksize=BLOCKSIZE) input1.__enter__() input2 = mic1.recorder(samplerate=SAMPLERATE, blocksize=BLOCKSIZE) input2.__enter__() all_inputs = sc.all_microphones(include_loopback=True) (loopback, ) = filter(loopback_name_matcher, all_inputs) opendsh = loopback.recorder(samplerate=SAMPLERATE, blocksize=BLOCKSIZE) opendsh.__enter__() player = None playing_count = 0 while True: playing = None i1 = input1.record(numframes=NUMFRAMES) i2 = input2.record(numframes=NUMFRAMES) od = opendsh.record(numframes=NUMFRAMES) if player == Inputs.CHANNEL1 and playing_count < MIN_PLAYING_COUNT: output1.play(i1) playing = Inputs.CHANNEL1 elif player == Inputs.CHANNEL2 and playing_count < MIN_PLAYING_COUNT: output1.play(i2) playing = Inputs.CHANNEL2 elif not is_silent(i1, "channel1"): output1.play(i1) playing = Inputs.CHANNEL1 elif not is_silent(i2, "channel2"): output1.play(i2) playing = Inputs.CHANNEL2 else: output1.play(od) playing = Inputs.OPENDSH if playing != player: logger.debug("switching to source: {} after {} iterations".format( playing, playing_count)) player = playing playing_count = 0 else: playing_count += 1
def pick_device(): devices = sc.all_speakers() for x in range(0, len(devices)): print("{}: {} ({})".format(x, devices[x].name, devices[x].id)) inp = int(input("Enter the device number: ")) if inp > 0 and inp < len(devices): return devices[inp] else: print("Invalid number ", inp) return pick_device()
def __init__(self): # get a list of all speakers: speakers = sc.all_speakers() # get the current default speaker on your system: self.default_speaker = sc.default_speaker() # get a list of all microphones: mics = sc.all_microphones() # get the current default microphone on your system: self.default_mic = self.__get_build_in_mic(mics)
async def validate_input(hass: core.HomeAssistant, data): """Validate the user input allows us to connect. Data has the keys from DATA_SCHEMA with values provided by the user. """ sink_ids = [sink.id for sink in all_speakers()] if data[CONF_SINK] not in sink_ids: raise InvalidSinkID # Return info that you want to store in the config entry. return {"title": "PulseAudio: " + data[CONF_SINK]}
def print_all_devices() -> None: print("speakers") spk_all = sc.all_speakers() spk_default = sc.default_speaker() for spk in spk_all: prefix = "*" if str(spk) == str(spk_default) else " " print(f"{prefix} {spk.name} id: {spk.id}") print("microphones") mic_all = sc.all_microphones() mic_default = sc.default_microphone() for mic in mic_all: prefix = "*" if str(mic) == str(mic_default) else " " print(f"{prefix} {mic.name} id: {mic.id}")
def scard_query_device_details(self, device: Optional[Union[int, str]] = None, kind: Optional[str] = None) -> Any: speakers = soundcard.all_speakers() if type(device) == str: for speaker in speakers: if speaker.id == device: result = speaker._get_info() result['id'] = speaker.id return result else: for idx, speaker in enumerate(speakers): if idx == device: result = speaker._get_info() result['id'] = speaker.id return result raise LookupError("no such device")
def play(): all_speakers = sc.all_speakers() output = all_speakers[1] sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('', 3001)) sock.listen(1) conn, addr = sock.accept() player = output.player(44100) player.__enter__() while True: data = conn.recv(1024) arr = np.frombuffer(data, dtype=np.float32) player.play(arr) conn.close()
def test(self): self.sound_cards = soundcard.all_speakers() self.mics = soundcard.all_microphones() if len(self.sound_cards) > 0: self.sound_card_present = True self.default_sound_card = str(soundcard.default_speaker()).replace( "<", "").replace(">", "") else: self.sound_card_present = False self.default_sound_card = "No default sound card found. May not be enabled or plugged in." if len(self.mics) > 0: self.mic_present = True self.default_mic = str(soundcard.default_microphone()).replace( "<", "").replace(">", "") else: self.mic_present = False self.default_mic = "No default mic found. May not be enabled or plugged in." return self
def run(): print("connecting to socket server") # client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # client.connect((TCP_IP_ADDR, TCP_PORT_NO)) print("getting all microphones") # all_microphones = sc.all_microphones(include_loopback=True) # print("got all microphones: {}".format(all_microphones)) # loopback = next((microphone for microphone in all_microphones if microphone.isloopback and microphone.name.find('Speakers') != -1), None) loopback = sc.default_microphone() if loopback is None: print("No loopback device detected, exiting...") exit(1) print("Found a loopback microphone with: {}".format(loopback)) try: with loopback.recorder( samplerate=44100, channels=2) as mic: #, wave.open('test.wav', 'wb') as wav: # wav.setparams((1, 2, 44100, 0, 'NONE', 'NONE')) spk = next(speaker for speaker in sc.all_speakers() if speaker.name.find('ODAC') != -1) print(spk) # mic.__enter__() # while True: while True: try: data = loopback.record(1024, 44100) spk.play(data, 44100) # byte = data.tobytes() # wav.writeframes(byte) # mic.flush() # byte = bytes('testing', 'utf-8') # client.send(byte) # sys.stdout.flush() # client.sendto(byte, (UDP_IP_ADDR, UDP_PORT_NO)) # mic.flush() except Exception as e: print("Uh oh... failed: {}".format(e)) exit(1) except KeyboardInterrupt: # client.close() wav.close()
def all_outputs(): return sc.all_speakers()
def get_interface(cfo): _test0 = soundcard.all_speakers() _test1 = soundcard.all_microphones() sp = soundcard.get_speaker(cfo.OUT_CARD_NAME) mc = soundcard.get_microphone(cfo.IN_CARD_NAME) return sp, mc
def main(): # extend the OptionParser so that we can print multiple paragraphs in # the help text class MyParser(OptionParser): def format_description(self, formatter): result = [] for paragraph in self.description: result.append(formatter.format_description(paragraph)) return "\n".join(result[:-1]) # drop last \n def format_epilog(self, formatter): result = [] for paragraph in self.epilog: result.append(formatter.format_epilog(paragraph)) return "".join(result) usage = "%prog -s SERVER -p PORT -f FREQ -m MODE [other options]" description = [ "kiwiclientd.py receives audio from a KiwiSDR and plays" " it to a (virtual) sound device. This can be used to" " send KiwiSDR audio to various programs to decode the" " received signals." " This program also accepts hamlib rigctl commands over" " a network socket to change the kiwisdr frequency" " To stream multiple KiwiSDR channels at once, use the" " same syntax, but pass a list of values (where applicable)" " instead of single values. For example, to stream" " two KiwiSDR channels in USB to the virtual sound cards" " kiwisdr0 & kiwisdr1, with the rigctl ports 6400 &" " 6401 respectively, run the following:", "$ kiwiclientd.py -s kiwisdr.example.com -p 8073 -f 10000 -m usb --snddev kiwisnd0,kiwisnd1 --rigctl-port 6400,6401", "" ] epilog = [] # text here would go after the options list parser = MyParser(usage=usage, description=description, epilog=epilog) parser.add_option('-s', '--server-host', dest='server_host', type='string', default='localhost', help='Server host (can be a comma-separated list)', action='callback', callback_args=(str, ), callback=get_comma_separated_args) parser.add_option( '-p', '--server-port', dest='server_port', type='string', default=8073, help='Server port, default 8073 (can be a comma-separated list)', action='callback', callback_args=(int, ), callback=get_comma_separated_args) parser.add_option( '--pw', '--password', dest='password', type='string', default='', help='Kiwi login password (if required, can be a comma-separated list)', action='callback', callback_args=(str, ), callback=get_comma_separated_args) parser.add_option( '--tlimit-pw', '--tlimit-password', dest='tlimit_password', type='string', default='', help= 'Connect time limit exemption password (if required, can be a comma-separated list)', action='callback', callback_args=(str, ), callback=get_comma_separated_args) parser.add_option( '-u', '--user', dest='user', type='string', default='kiwiclientd', help='Kiwi connection user name (can be a comma-separated list)', action='callback', callback_args=(str, ), callback=get_comma_separated_args) parser.add_option( '--log', '--log-level', '--log_level', type='choice', dest='log_level', default='warn', choices=['debug', 'info', 'warn', 'error', 'critical'], help='Log level: debug|info|warn(default)|error|critical') parser.add_option('-q', '--quiet', dest='quiet', default=False, action='store_true', help='Don\'t print progress messages') parser.add_option( '--tlimit', '--time-limit', dest='tlimit', type='float', default=None, help='Record time limit in seconds. Ignored when --dt-sec used.') parser.add_option('--launch-delay', '--launch_delay', dest='launch_delay', type='int', default=0, help='Delay (secs) in launching multiple connections') parser.add_option( '--connect-retries', '--connect_retries', dest='connect_retries', type='int', default=0, help= 'Number of retries when connecting to host (retries forever by default)' ) parser.add_option('--connect-timeout', '--connect_timeout', dest='connect_timeout', type='int', default=15, help='Retry timeout(sec) connecting to host') parser.add_option('-k', '--socket-timeout', '--socket_timeout', dest='socket_timeout', type='int', default=10, help='Socket timeout(sec) during data transfers') parser.add_option( '--OV', dest='ADC_OV', default=False, action='store_true', help='Print "ADC OV" message when Kiwi ADC is overloaded') parser.add_option('-v', '-V', '--version', dest='krec_version', default=False, action='store_true', help='Print version number and exit') group = OptionGroup(parser, "Audio connection options", "") group.add_option( '-f', '--freq', dest='frequency', type='string', default=1000, help='Frequency to tune to, in kHz (can be a comma-separated list)', action='callback', callback_args=(float, ), callback=get_comma_separated_args) group.add_option( '-m', '--modulation', dest='modulation', type='string', default='am', help= 'Modulation; one of am, lsb, usb, cw, nbfm, iq (default passband if -L/-H not specified)' ) group.add_option('--ncomp', '--no_compression', dest='compression', default=True, action='store_false', help='Don\'t use audio compression') group.add_option('-L', '--lp-cutoff', dest='lp_cut', type='float', default=None, help='Low-pass cutoff frequency, in Hz') group.add_option('-H', '--hp-cutoff', dest='hp_cut', type='float', default=None, help='High-pass cutoff frequency, in Hz') group.add_option( '-r', '--resample', dest='resample', type='int', default=0, help= 'Resample output file to new sample rate in Hz. The resampling ratio has to be in the range [1/256,256]' ) group.add_option('-T', '--squelch-threshold', dest='thresh', type='float', default=None, help='Squelch threshold, in dB.') group.add_option( '--squelch-tail', dest='squelch_tail', type='float', default=1, help= 'Time for which the squelch remains open after the signal is below threshold.' ) group.add_option( '-g', '--agc-gain', dest='agc_gain', type='string', default=None, help= 'AGC gain; if set, AGC is turned off (can be a comma-separated list)', action='callback', callback_args=(float, ), callback=get_comma_separated_args) group.add_option('--nb', dest='nb', action='store_true', default=False, help='Enable noise blanker with default parameters.') group.add_option( '--nb-gate', dest='nb_gate', type='int', default=100, help='Noise blanker gate time in usec (100 to 5000, default 100)') group.add_option( '--nb-th', '--nb-thresh', dest='nb_thresh', type='int', default=50, help='Noise blanker threshold in percent (0 to 100, default 50)') parser.add_option_group(group) group = OptionGroup(parser, "Sound device options", "") group.add_option( '--snddev', '--sound-device', dest='sounddevice', type='string', default='', action='callback', help='Sound device to play kiwi audio on (can be comma separated list)', callback_args=(str, ), callback=get_comma_separated_args) group.add_option('--ls-snd', '--list-sound-devices', dest='list_sound_devices', default=False, action='store_true', help='List available sound devices and exit') parser.add_option_group(group) group = OptionGroup(parser, "Rig control options", "") group.add_option('--rigctl', '--enable-rigctl', dest='rigctl_enabled', default=True, action='store_true', help='Enable rigctld backend for frequency changes.') group.add_option( '--rigctl-port', '--rigctl-port', dest='rigctl_port', type='string', default='6400', help= 'Port listening for rigctl commands (default 6400, can be comma separated list', action='callback', callback_args=(int, ), callback=get_comma_separated_args) group.add_option('--rigctl-addr', '--rigctl-address', dest='rigctl_address', type='string', default=None, help='Address to listen on (default 127.0.0.1)') parser.add_option_group(group) (options, unused_args) = parser.parse_args() ## clean up OptionParser which has cyclic references parser.destroy() if options.krec_version: print('kiwiclientd v1.0') sys.exit() if options.list_sound_devices: print(sc.all_speakers()) sys.exit() FORMAT = '%(asctime)-15s pid %(process)5d %(message)s' logging.basicConfig(level=logging.getLevelName(options.log_level.upper()), format=FORMAT) if options.log_level.upper() == 'DEBUG': gc.set_debug(gc.DEBUG_SAVEALL | gc.DEBUG_LEAK | gc.DEBUG_UNCOLLECTABLE) run_event = threading.Event() run_event.set() if options.tlimit is not None and options.dt != 0: print('Warning: --tlimit ignored when --dt-sec option used') options.sdt = 0 options.dir = None options.raw = False options.sound = True options.no_api = False options.tstamp = False options.station = None options.filename = None options.test_mode = False options.is_kiwi_wav = False options.is_kiwi_tdoa = False gopt = options multiple_connections, options = options_cross_product(options) snd_recorders = [] for i, opt in enumerate(options): opt.multiple_connections = multiple_connections opt.idx = i snd_recorders.append( KiwiWorker(args=(KiwiSoundRecorder(opt), opt, run_event))) try: for i, r in enumerate(snd_recorders): if opt.launch_delay != 0 and i != 0 and options[ i - 1].server_host == options[i].server_host: time.sleep(opt.launch_delay) r.start() #logging.info("started kiwi client %d, timestamp=%d" % (i, options[i].timestamp)) logging.info("started kiwi client %d" % i) while run_event.is_set(): time.sleep(.1) except KeyboardInterrupt: run_event.clear() join_threads(snd_recorders) print("KeyboardInterrupt: threads successfully closed") except Exception as e: print_exc() run_event.clear() join_threads(snd_recorders) print("Exception: threads successfully closed") logging.debug('gc %s' % gc.garbage)
def test_speakers(): for speaker in soundcard.all_speakers(): assert isinstance(speaker.name, str) assert hasattr(speaker, 'id') assert isinstance(speaker.channels, int) assert speaker.channels > 0
def first_code(): speakers = sc.all_speakers() defspeaker = sc.default_speaker() print(speakers) print(defspeaker)
def select_audio_mixers(self): self._input_mixer = sc.all_speakers()[0] if len( sc.all_speakers()) > 0 else None self._output_mixer = sc.all_microphones()[0] if len( sc.all_microphones()) > 0 else None
def start_mixer(): all_speakers = sc.all_speakers() (spkr1, spkr2) = filter(speaker_name_matcher, all_speakers) all_inputs = sc.all_microphones() (mic1, mic2) = filter(mic_name_matcher, all_inputs) input1 = mic1.recorder(samplerate=SAMPLE_RATE, blocksize=BLOCK_SIZE) input1.__enter__() input2 = mic2.recorder(samplerate=SAMPLE_RATE, blocksize=BLOCK_SIZE) input2.__enter__() lb = find_loopback_port() opendsh = lb.recorder(samplerate=SAMPLE_RATE, blocksize=BLOCK_SIZE) opendsh.__enter__() output1 = spkr1.player(samplerate=SAMPLE_RATE) output1.__enter__() output2 = spkr2.player(samplerate=SAMPLE_RATE) output2.__enter__() player = None playing_count = 0 while True: playing = None i1 = input1.record(numframes=NUM_FRAMES) i2 = input2.record(numframes=NUM_FRAMES) od = opendsh.record(numframes=NUM_FRAMES) if player == Inputs.CHANNEL1 and playing_count < MIN_PLAYING_COUNT: output1.play(i1) output2.play(i1) playing = Inputs.CHANNEL1 elif player == Inputs.CHANNEL2 and playing_count < MIN_PLAYING_COUNT: output1.play(i2) output2.play(i2) playing = Inputs.CHANNEL2 elif player == Inputs.OPENDSH and playing_count < MIN_PLAYING_COUNT: output1.play(od) output2.play(od) playing = Inputs.OPENDSH elif not is_silent(i1): output1.play(i1) output2.play(i1) playing = Inputs.CHANNEL1 elif not is_silent(i2): output1.play(i2) output2.play(i2) playing = Inputs.CHANNEL2 else: output1.play(od) output2.play(od) playing = Inputs.OPENDSH if playing != player: logger.debug("switching to player: {}".format(playing)) player = playing playing_count = 0 else: playing_count += 1
os.system(screen_clear) lines.reverse() for l in lines: print(l) def start_render_loop(self): while True: self._render() time.sleep(0.01667) if __name__ == '__main__': import soundcard as sc from ..common import samplegen selections = sc.all_speakers() for i, s in enumerate(selections): print("{} : {}".format(i, s)) s = int(input("Speaker Choice: ")) s_name = selections[s].name mixin = sc.get_microphone(id=s_name, include_loopback=True) with mixin.recorder(samplerate=44100) as rec: ar = AudioRenderer(samplegen(rec), char="|") ar.start_render_loop()
import soundcard as sc import struct BLOCKSIZE = 512 NUMFRAMES = 256 mics = sc.all_microphones(include_loopback=True) mic = mics[5] print(mic) recorder = mic.recorder(samplerate=48000, blocksize=BLOCKSIZE) recorder.__enter__() spkrs = sc.all_speakers() spkr = spkrs[0] print(spkr) player = spkr.player(samplerate=48000, blocksize=BLOCKSIZE) player.__enter__() while True: data = recorder.record(numframes=NUMFRAMES) player.play(data) recorder.__exit__() player.__exit__()
arg = arg.split("=") self.kflags[arg[0]] = '='.join(arg[1:]) # Is a flag else: self.flags.append(arg) # Parse shell arguments TODO: proper interface using typer? # Temporary file mostly? args = ArgParser(sys.argv) # List and override soundcard outputs if ("list" in args.flags): print(f"{debug_prefix} Available devices to play audio:") for index, device in enumerate(soundcard.all_speakers()): print(f"{debug_prefix} > ({index}) [{device.name}]") print( f"{debug_prefix} :: Run this script again with [play=N] flag to override" ) sys.exit(0) # Overriding capture stuff output_sound_card = args.kflags.get("play", None) override_record_device = None if output_sound_card is not None: recordable = soundcard.all_speakers() # Error assertion if (len(recordable) < int(cap)) or (int(cap) < 0):