class Volay::Mixer::Pulse

Pulse class for playing with pacmd command

Constants

DEFAULT_VALUE
MAX_VALUE

Attributes

cards[RW]
default_sink_id[R]

Public Class Methods

new() click to toggle source
# File lib/volay/mixer/pulse.rb, line 15
def initialize
  @cards = {}
  refresh
end

Public Instance Methods

change_card(newdefault) click to toggle source

Change card

@param [Integer] newdefault New default index

# File lib/volay/mixer/pulse.rb, line 62
def change_card(newdefault)
  return unless @cards.key?(newdefault)

  # Change default sink
  command("set-default-sink #{@cards[newdefault]['sink']}")

  # Now to move all current playing stuff to the new sink....
  dump = command('list-sink-inputs').lines
  dump.each do |line|
    args = line.split
    # We need to find the item index for each playing stream
    if args[0] == 'index:'
      # And now to shift them all to the new sink.
      command("move-sink-input #{args[1]} #{@cards[newdefault]['sink']}")
    end
  end

  refresh
end
current() click to toggle source
# File lib/volay/mixer/pulse.rb, line 48
def current
  {
    value: current_sink.nil? ? 0 : current_sink['volume'],
    max_value: MAX_VALUE,
    percent: current_sink.nil? ? 0 : volume_percent(current_sink['volume']),
    muted: current_sink.nil? ? true : current_sink['muted'] == 'yes'
  }
end
down(value = DEFAULT_VALUE) click to toggle source
# File lib/volay/mixer/pulse.rb, line 26
def down(value = DEFAULT_VALUE)
  set_volume(
    volume_percent(@cards[@default_sink_id]['volume']) - value
  )
end
refresh() click to toggle source

Refresh cards data

# File lib/volay/mixer/pulse.rb, line 85
def refresh
  cmd = command('dump')
  return unless cmd

  dump = cmd.lines
  dump.each do |line|
    args = line.split

    # We are using the id to actually enumerate all cards.
    if args[1] == 'module-alsa-card'
      number = args[2].sub('device_id="', '').sub('"', '').to_i
      @cards[number] = {}
      @cards[number]['name'] = args[3].sub('name="', '').sub('"', '')
    # we already have something in the array
    elsif @cards.keys.length.positive?
      set_data(args)
    end
  end

  set_long_names
end
toggle() click to toggle source
# File lib/volay/mixer/pulse.rb, line 36
def toggle
  return if current_sink.nil?

  value = if current_sink['muted'] == 'yes'
            'no'
          else
            'yes'
          end
  current_sink['muted'] = value
  command("set-sink-mute #{@cards[@default_sink_id]['sink']} #{value}")
end
up(value = DEFAULT_VALUE) click to toggle source
# File lib/volay/mixer/pulse.rb, line 20
def up(value = DEFAULT_VALUE)
  set_volume(
    volume_percent(@cards[@default_sink_id]['volume']) + value
  )
end
value=(value) click to toggle source
# File lib/volay/mixer/pulse.rb, line 32
def value=(value)
  set_volume(value.to_i)
end

Private Instance Methods

command(cmd) click to toggle source

Run command

@param [String] cmd Command to run

# File lib/volay/mixer/pulse.rb, line 194
def command(cmd)
  command = "pacmd #{cmd}"
  result = Mixlib::ShellOut.new(command)
  Volay::Config.logger.debug(command)
  result.run_command

  return unless result.exitstatus.zero?

  Volay::Config.logger.error(result.stderr) unless result.stderr.empty?
  Volay::Config.logger.debug(result.stdout) unless result.stdout.empty?
  result.stdout
end
current_sink() click to toggle source

Get current sink

@return [Hash]

# File lib/volay/mixer/pulse.rb, line 171
def current_sink
  @cards[@default_sink_id]
end
set_data(args) click to toggle source

Set cards data such as default sink volume and if card is muted

@param [Hash] args Parameters

# File lib/volay/mixer/pulse.rb, line 124
def set_data(args)
  @cards.each do |id, card|
    next if args[1].nil? || !args[1].include?(card['name'])

    case args[0]
    when 'set-default-sink'
      @default_sink_id = id
    when 'set-sink-volume'
      @cards[id]['volume'] = args[2].hex
      @cards[id]['sink'] = args[1]
    when 'set-sink-mute'
      @cards[id]['muted'] = args[2]
    end
  end
end
set_long_names() click to toggle source

Get long name from list-cards command

# File lib/volay/mixer/pulse.rb, line 143
def set_long_names
  dump = command(
    "list-cards | grep -e device.string -e 'name:' -e 'card_name'"
  )
         .split('name: ')
         .reject { |x| x.strip.empty? }

  dump.each do |card|
    id = nil
    name = nil
    card.lines.each do |line|
      args = line.strip.split(' = ')
      if args[0] == 'device.string'
        id = args[1].delete('"').to_i
      elsif args[0] == 'alsa.card_name'
        name = args[1].delete('"')
      end
    end

    @cards[id]['long_name'] = name
  end
end
set_volume(volume) click to toggle source

Set up volume

@param [Integer] volume Volume to set up, must be a percentage

# File lib/volay/mixer/pulse.rb, line 180
def set_volume(volume)
  return if current_sink.nil?

  volume = [[0, (volume * MAX_VALUE / 100)].max, MAX_VALUE].min
  @cards[@default_sink_id]['volume'] = volume
  sink = @cards[@default_sink_id]['sink']
  command("set-sink-volume #{sink} #{format('0x%<v>x', v: volume)}")
end
volume_percent(value) click to toggle source

Get volume percent

@return Integer

# File lib/volay/mixer/pulse.rb, line 114
def volume_percent(value)
  value * 100 / MAX_VALUE
end