2011-04-11, 00:56
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:
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:
2. I made a python script (/usr/local/bin/SwitchAudio.py) that mutes and unmutes accordinly the 2 different sound hardware through amixer:
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".
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!
I hope this will help others too.
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".
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!
I hope this will help others too.