Beispiel #1
0
def _modify_config(config_contents, key, value):
    """Return a string representing the modified contents of the config file.

    Parameters
    ----------
    config_contents : string
        Contents of the config file in ~/.config/alsacontrol/config.
        It is not edited in place and the config file is not overwritten.
    key : string
        Settings key that should be modified
    value : string, int
        Value to write
    """
    logger.info('Setting "%s" to "%s"', key, value)

    split = config_contents.split('\n')
    if split[-1] == '':
        split = split[:-1]

    found = False
    setting = f'{key}={value}'
    for i, line in enumerate(split):
        strip = line.strip()
        if strip.startswith('#'):
            continue
        if strip.startswith(f'{key}='):
            # replace the setting
            logger.debug('Overwriting "%s=%s" in config', key, value)
            split[i] = setting
            found = True
            break
    if not found:
        logger.debug('Adding "%s=%s" to config', key, value)
        split.append(setting)
    return '\n'.join(split)
Beispiel #2
0
 def create_config_file(self):
     """Create an empty config if it doesn't exist."""
     if not os.path.exists(os.path.dirname(self._path)):
         os.makedirs(os.path.dirname(self._path))
     if not os.path.exists(self._path):
         logger.info('Creating config file "%s"', self._path)
         os.mknod(self._path)
Beispiel #3
0
def start_daemon(debug=True):
    """Start the alsacontrol daemon."""
    logger.info('Starting the alsacontrol daemon')
    cmd = ['alsacontrol-daemon-gtk']
    if debug:
        cmd.append('-d')
    subprocess.Popen(cmd)
Beispiel #4
0
def stop_pulse():
    """Stop the pulseaudio service using systemctl."""
    if is_pulse_running():
        logger.info('Stopping pulseaudio')
        os.system('systemctl --user stop pulseaudio.service')
        os.system('systemctl --user stop pulseaudio.socket')
        os.system('pulseaudio -k')
    else:
        logger.info('Pulseaudio is not running')
Beispiel #5
0
def create_asoundrc():
    """Create and populate ~/.config/alsacontrol/asoundrc."""
    pcm_input, pcm_output = get_pcms()

    if pcm_output == 'jack':
        last_output_step = 'alsacontrol-plug'
    elif should_use_dmix(pcm_output):
        last_output_step = 'alsacontrol-dmix'
    else:
        last_output_step = pcm_output
    # either from asym directly to the last step, or over softvol
    if get_config().get('output_use_softvol'):
        output_pcm_asym = 'alsacontrol-output-softvol'
        output_pcm_softvol = last_output_step
    else:
        output_pcm_asym = last_output_step
        output_pcm_softvol = 'null'

    if pcm_input == 'jack':
        last_input_step = 'alsacontrol-plug'
    elif should_use_dsnoop(pcm_input):
        last_input_step = 'alsacontrol-dsnoop'
    else:
        last_input_step = pcm_input
    # either from asym directly to the last step, or over softvol
    if get_config().get('input_use_softvol'):
        input_pcm_asym = 'alsacontrol-input-softvol'
        input_pcm_softvol = last_input_step
    else:
        input_pcm_asym = last_input_step
        input_pcm_softvol = 'null'

    # dmix and dsnoop always have to be the last step
    asoundrc_config = {
        'output_pcm_asym': output_pcm_asym,
        'output_pcm_softvol': output_pcm_softvol,
        'output_pcm': pcm_output,
        'output_channels': get_config().get('output_channels'),
        'input_pcm_asym': input_pcm_asym,
        'input_pcm_softvol': input_pcm_softvol,
        'input_pcm': pcm_input,
    }

    template_path = os.path.join(get_data_path(), 'asoundrc-template')
    with open(template_path, 'r') as template_file:
        template = template_file.read()

    asoundrc_content = template.format(**asoundrc_config)

    with open(alsactl_asoundrc, 'w+') as asoundrc_file:
        logger.info('Writing file %s', alsactl_asoundrc)
        asoundrc_file.write(asoundrc_content)
Beispiel #6
0
def get_pcms():
    """Return the configured input and output pcm string."""
    pcm_input = get_config().get('pcm_input')
    pcm_output = get_config().get('pcm_output')
    if pcm_input == 'null':
        logger.warning('No input specified')
    else:
        logger.info('Using input %s', pcm_input)
    if pcm_output == 'null':
        logger.warning('No output specified')
    else:
        logger.info('Using output %s', pcm_output)
    return pcm_input, pcm_output
Beispiel #7
0
 def log_new_pcms(self):
     """Write to the console if new cards are added. Return True if so."""
     # using .cards() isntead of .pcms() is MUCH faster
     cards = set(get_cards())
     changes = 0
     if self.cards is None:
         # first time running, don't log yet
         pass
     else:
         for card in self.cards.difference(cards):
             logger.info('Card "%s" was removed', card)
             changes += 1
         for card in cards.difference(self.cards):
             logger.info('Found new card "%s"', card)
             changes += 1
     self.cards = cards
     return changes > 0
Beispiel #8
0
    def toggle_speaker_test(self):
        """Run the speaker-test script or stop it, if it is running.

        Returns the subprocess or False if it has been stopped.
        """
        if self.speaker_test_process is None:
            num_channels = get_config().get('output_channels')
            cmd = f'speaker-test -D default -c {num_channels} -twav'
            logger.info('Testing speakers, %d channels (%s)', num_channels, cmd)
            process = subprocess.Popen(
                cmd.split(),
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                preexec_fn=os.setsid
            )
            self.speaker_test_process = process
            return process

        self.stop_speaker_test()
        return False
Beispiel #9
0
    def stop_speaker_test(self):
        """Stop the speaker test if it is running."""
        if self.speaker_test_process is None:
            return

        return_code = self.speaker_test_process.poll()
        if return_code is None:
            pid = self.speaker_test_process.pid
            logger.info('Stopping speaker test')
            try:
                os.killpg(os.getpgid(pid), signal.SIGTERM)
            except ProcessLookupError:
                logger.debug(
                    'Tried to stop speaker-test process that has already '
                    'been stopped'
                )
                # It has already been stopped
            if debug_log_on():
                stdout = self._read_from_std(self.speaker_test_process.stdout)
                for line in stdout:
                    logger.debug('speaker-test stdout: %s', line)
            self.speaker_test_process = None
Beispiel #10
0
 def check_mtime(self):
     """Check if the config file has been modified and reload if needed."""
     if os.path.getmtime(self._path) != self.mtime:
         logger.info('Config changed, reloading')
         self.load_config()
Beispiel #11
0
def stop_daemon():
    """Stop the alsacontrol daemon."""
    # stops alsacontrol-daemon-gtk or alsacontrol-daemon-qt if that should
    # ever exist in the future
    logger.info('Stopping the alsacontrol daemon')
    os.system('pkill -f alsacontrol-daemon')