Volumechanger.sh

From MythTV Official Wiki
Jump to: navigation, search

Important.png Note: The correct title of this article is volumechanger.sh. It appears incorrectly here due to technical restrictions.


Author Pieter Hoekstra
Description Script to control volume, even when not playing media, with OSD-support
Supports Version22.png  Version23.png  Version24.png  Version25.png  


Why this script

  • Be able to control volume all the time, even when not playing media or playing other media-players, like MPD, mplayer or mythnetvision
  • Apply different volumes to different channels. My center-speaker is now always 1.5 times louder
  • Myth currently does not support my soundcard (Xonar D2X) master volume and is changing only one channel. Probably should file a bug for that...

OSD requires

  • osd_cat (Ubuntu package: xosd-bin)
  • Frontend control socket enabled
  • Configure internal volume with a dummy soundcard (So it seems myth is changing volume and displays a nice OSD)
  • Configure Frontend display/username in script

Script

Script.png volumechanger.sh

#!/bin/bash

# Frontend display/username (Needed for OSD)
export DISPLAY=:0
export XAUTHORITY=/home/mediacenter/.Xauthority
#gdm:
#export XAUTHORITY=`find /var/run/gdm/ -name database | grep mediacenter`

CARD="hw:CARD=D2X"

# Change volume:
VOLUMEDB=$(amixer -D $CARD set Master $1 | sed '/^ *Front Left: /{s/^.*\[-\([0-9]*\).*dB\].*/\1/;p;};d;')
VOLUME=$(amixer -D $CARD get Master | sed '/^ *Front Left: /{s/^.*\[\([0-9]*\).*\%\].*/\1/;p;};d;')

# Multiply Center-volume with 2/3 (in Db this is louder)
let CVOLUMEDB=($VOLUMEDB)*2/3
amixer -d -D $CARD set Master "center -${CVOLUMEDB}dB"



if [ "$2" != "noosd" ]; then
        # OSD with notify-send. Dont use it anymore, it stays to long on the screen
        #
        #STATUS=$(amixer -D 'hw:CARD=D2X' sget Master | awk '$1 == "Front" && $2 == "Left:" { print $NF; }')
        #if [ $STATUS = '[off]' ]; then
        #       ICON=notification-audio-volume-muted
        #elif [ $VOLUME -lt 33 ]; then
        #       ICON=notification-audio-volume-low
        #elif [ $VOLUME -lt 66 ]; then
        #       ICON=notification-audio-volume-medium
        #else
        #       ICON=notification-audio-volume-high
        #fi
        #notify-send "Volume" -i $ICON -h int:value:$VOLUME -h string:x-canonical-private-synchronous: -u critical

        # OSD with Frontend control socket, using Myth internal volume control with dummy-soundcard and osd_cat fallback
        if ! echo "play volume $VOLUME%" | nc localhost 6546 | grep "OK"; then
                killall osd_cat
                osd_cat -b percentage -P $VOLUME -p bottom -A center -d5  -c grey -f -misc-fixed-medium-r-semicondensed--*-500-*-*-c-*-*-* &
        fi
fi

#if ! pidof -xs lcd.pl; then
#        /path/to/lcd.pl &
#fi

Adding to Lirc

Config added to /etc/lirc/lircrc:

begin
    remote = devinput
    prog = irexec
    button = KEY_VOLUMEDOWN
#    config = amixer sset Master 2dB-
    config = /path/to/volumechanger.sh 2dB-
    repeat = 1
    delay = 0
end
begin
    remote = devinput
    prog = irexec
    button = KEY_VOLUMEUP
#    config = amixer sset Master 2dB+
    config = /path/to/volumechanger.sh 2dB+
    repeat = 1
    delay = 0
end
begin
    remote = devinput
    prog = irexec
    button = KEY_MUTE
#    config = amixer sset Master toggle
    config = /path/to/volumechanger.sh toggle
    repeat = 0
    delay = 0
end

LCD support

Below is a hack to add the volume-changing to LCD as well. Add this to volumechanger.sh at the bottom to enable:

if ! pidof -xs lcd.pl; then
        /path/to/lcd.pl &
fi


Script.png lcd.pl

#!/usr/bin/perl -w

use 5.004;
use strict;
use IO::Socket;
use Fcntl;

# Host which runs lcdproc daemon (LCDd)
my $server = "localhost";

# Port on which LCDd listens to requests
my $port = "13666";

# wait-time (in seconds) when we are all done
my $waittime = 5;

############################################################
# End of user configurable parts
############################################################

my $progname = $0;
   $progname =~ s#.*/(.*?)$#$1#;

# Connect to the server...
my $remote = IO::Socket::INET->new(
                Proto     => "tcp",
                PeerAddr  => $server,
                PeerPort  => $port,
        ) or die "Cannot connect to LCDproc port ($server:$port)\n";

# Make sure our messages get there right away
$remote->autoflush(1);

print $remote "hello\n";
my $lcdconnect = <$remote>;

# Turn off blocking mode...
fcntl($remote, F_SETFL, O_NONBLOCK);

# Set up some screen widgets...
print $remote "client_set name volume\n";

print $remote "screen_add volume\n";
print $remote "screen_set volume name {Volume} priority input heartbeat off\n";

print $remote "widget_add volume title string\n";
print $remote "widget_add volume vol hbar\n";

my $counter = 20;
my $status;
my $db;
my $ostatus = "";
my $mix;
my $volume;

while($counter > 0)
{
        $mix = `amixer -D hw:CARD=D2X sget Master`;
        if ($mix =~ / *Front Left:.+ \[(.*)%\] \[(.*).\d0dB\]/)
        {
                $volume = $1;
                $db = "$2dB";
        }
        if ($mix =~ / *Front Left:.+ \[(.*)\]/)
        {
                $status = ($1 eq 'off' ? 'Uit' : "$volume% $db");
        }

        print $remote "widget_set volume vol 1 2 $volume\n";
        if ($status ne $ostatus)
        {
                print $remote "widget_set volume title 1 1 {Volume $status} \n";
                $counter = 20;
                $ostatus = $status;
        }

        $counter--;
        select(undef, undef, undef, 0.1);
}

while(defined(my $input = <$remote>)) { }
close($remote);
exit;