[LINUX] Script for switching audio on the fly
#1
I finally found a way to easily switch audio in linux xbmc on the fly.

1. I made an alsa conf (/etc/asound.conf) using the settings from chris80 that had posted in a previous thread (here) and customizing them for my hardware:

Code:
# ---------------------------------------------------------------------
# Hardware - do not use directly
# ---------------------------------------------------------------------

pcm.analog-hw {
  type hw
  card 0
  device 0
}
ctl.analog-hw {
  type hw
  card 0
}

# ---------------------------------------------------------------------

pcm.digital-hw {
  type hw
  card 1
  device 7
}
ctl.digital-hw {
  type hw
  card 1
}

# -------------------------------------------------------------------------

pcm.dmix-analog {
  type dmix
  ipc_key 1234
  slave {
    pcm "analog-hw"
    period_time 0
    period_size 1024
    buffer_size 4096
    rate 48000
  }
}
ctl.dmix-analog {
  type hw
  card 0
}

# -------------------------------------------------------------------------

pcm.dmix-digital {
  type dmix
  ipc_key 1235
  slave {
    pcm "digital-hw"
    period_time 0
    period_size 1024
    buffer_size 4096
    rate 48000
  }
}
ctl.dmix-digital {
  type hw
  card 1
}

# --------------------------------------------------------------------------

pcm.analog {
  type plug
  slave.pcm "analog-hw"
  hint {
    show on
    description "Analog Output - Use analog outputs, converting samples, format, and rate as necessary."
  }
}
ctl.analog {
  type hw
  card 0
}

# -----------------------------------------------------------------------------

pcm.mixed-analog {
  type plug
  slave.pcm "dmix-analog"
  hint {
    show on
    description "Mixed Analog Output - Use analog outputs, converting samples, format, and rate as necessary. Allows mixing with system sounds."
  }
}
ctl.mixed-analog {
  type hw
  card 0
}

# --------------------------------------------------------------------------------

pcm.digital {
  type plug
  slave.pcm "digital-hw"
  hint {
    show on
    description "Digital Output (HDMI) - Use digital outputs, converting samples, format, and rate as necessary."
  }
}
ctl.digital {
  type hw
  card 1
}

# ----------------------------------------------------------------------------------

pcm.mixed-digital {
  type plug
  slave.pcm "dmix-digital"
  hint {
    show on
    description "Mixed Digital Output - Use digital outputs, converting samples, format, and rate as necessary. Allows mixing with system sounds."
  }
}
ctl.mixed-digital {
  type hw
  card 1
}

# ---------------------------------------------------------------------------------
# -----------------------------------------------------------------------------------

pcm.xbmc {
  type plug
  slave {
    pcm multi
    rate 48000
    channels 8
  }
  ttable.0.0 1.0
  ttable.1.1 1.0
  ttable.2.0 0.7
  ttable.3.1 0.7
  ttable.4.0 0.7
  ttable.4.1 0.7
  ttable.5.0 0.5
  ttable.5.1 0.5

  ttable.0.2 1.0
  ttable.1.3 1.0
  ttable.2.4 1.0
  ttable.3.5 1.0
  ttable.4.6 1.0
  ttable.5.7 1.0

  hint {
        show on
        description "XBMC device for hdmi 2 channel and analog up to 6 channels"
  }
}
ctl.xbmc {
  type hw
  card 0
}

pcm.multi {
  type multi
  slaves.a.pcm "mixed-digital"
  slaves.a.channels 2
  slaves.b.pcm "analog-hw"
  slaves.b.channels 6

  # HDMI

  bindings.0.slave a
  bindings.0.channel 0
  bindings.1.slave a
  bindings.1.channel 1

  # ANALOG 5.1

  bindings.2.slave b
  bindings.2.channel 0
  bindings.3.slave b
  bindings.3.channel 1
  bindings.4.slave b
  bindings.4.channel 2
  bindings.5.slave b
  bindings.5.channel 3
  bindings.6.slave b
  bindings.6.channel 4
  bindings.7.slave b
  bindings.7.channel 5
}
ctl.multi {
  type hw
  card 0
}

Notice that the multi plug uses the analog hardware directly wereas for the hdmi it uses the mixed-digital plug (that downmixes to 2 channels).


The above configuration creates an "xbmc" alsa plug that uses my 2 cards (onboard analog 5.1 and the nvidia hdmi out) at the same time. It simultaneously sends 5.1 channels to the onboard audio chip and 2 channels to the HDMI with downmixing (all this is done by alsa).

I checked that everything worked well with:
Code:
speaker-test -c6 -Dxbmc

2. I made a python script (/usr/local/bin/SwitchAudio.py) that mutes and unmutes accordinly the 2 different sound hardware through amixer:

Code:
from subprocess import Popen, PIPE
import sys
import os
import xbmc, xbmcgui

class AudioSwitcher:
        def __init__(self):
                self.amixerOutput = "";
                self.p = "";

        def switch(self):
                self.p = Popen('/usr/bin/amixer -c 1 get IEC958,1', shell=True, stdout=PIPE, stderr=PIPE);
                self.output = self.p.stdout.read();
                self.isInStr = '[on]';

                if self.isInStr in self.output:
                        # HDMI is on, switch to surround
                        print "Switching to surroung";

                        # HDMI
                        os.system("amixer -c 1 set IEC958,1 off");

                        # RCL analog 5.1
                        os.system("amixer -c 0 set Front on");
                        os.system("amixer -c 0 set Surround on");
                        os.system("amixer -c 0 set Center on");
                        os.system("amixer -c 0 set LFE on");
                        self.displayMessage("Surround");
                else:
                        # HDMI is off, switch to HDMI
                        print "Switching to HDMI";
                        # HDMI
                        os.system("amixer -c 1 set IEC958,1 on");

                        # RCL analog 5.1
                        os.system("amixer -c 0 set Front off");
                        os.system("amixer -c 0 set Surround off");
                        os.system("amixer -c 0 set Center off");
                        os.system("amixer -c 0 set LFE off");
                        self.displayMessage("HDMI");


        def displayMessage(self, message):
                        xbmc.executebuiltin('XBMC.Notification(\"Audio\", \"' + message + '\",1)');


switcher = AudioSwitcher();
switcher.switch();
del switcher;

So when one hardware sound card is muted, it gets unmuted and the other one gets muted, creating in essence the on the fly audio "switching". Wink

3. In userdata/keymaps/remote.xml I added a command to a remote button to execute the script:

<blue>RunScript("/usr/local/bin/SwitchAudio.py")</blue>

4. Now when I press the blue button on my remote the audio switches (mutes one plug and unmutes the other one) on the fly! Smile

I hope this will help others too.
Reply

Logout Mark Read Team Forum Stats Members Help
[LINUX] Script for switching audio on the fly0