Georg K�nzel wrote:

I have a SB 5.1 digital card and using the analog
output for 6 speakers. Problem: it is not a 5.1
speaker system with its own remote control.
Rear is connected to a hifi-system, front to an
active stereo speaker-set, front is the tv itself
and subwoofer an active subwoofer.

How to control all these speakers at once ?
I would like to use my happauge remote
or my keyboard, but freevo allows only control
over one audio ctrl. Any ideas to control IGaine,
Digital, OGaine and Volume at once ?


This is a small mixer plugin for freevo.
the idea was to control more than one mixer slider at a time
and control sliders that are not present in the ossmixer
like IEC958 (digital output).

You can simply put the script in src/plugins
and activate it with:
plugin.activate('alsa_mixer').
Be sure to remove the old one with: plugin.remove('mixer').

You then need a config line like this:
MAJOR_AUDIO_CTRLS = ['Master','Surround','IEC958']

some problems:
- the volume in/decreases not so fast than in the original mixer
- in digital audio control in/decreasing isnt supported so it only
can mute the channel

Good luck.

Mike


#if 0 /*
# -----------------------------------------------------------------------
# Freevo - A Home Theater PC framework
# Copyright (C) 2002 Krister Lagerstrom, et al. 
# Please see the file freevo/Docs/CREDITS for a complete list of authors.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MER-
# CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ----------------------------------------------------------------------- */
#endif
"""Simple ALSA mixer
"""

import fcntl
import struct
import os
import popen2

import config
import rc
import plugin
from event import *


class PluginInterface(plugin.DaemonPlugin):
    # These magic numbers were determined by writing a C-program using the
    # macros in /usr/include/linux/... and printing the values.
    # They seem to work on my machine. XXX Is there a real python interface?
    SOUND_MIXER_WRITE_VOLUME = 0xc0044d00
    SOUND_MIXER_WRITE_PCM = 0xc0044d04
    SOUND_MIXER_WRITE_LINE = 0xc0044d06
    SOUND_MIXER_WRITE_MIC = 0xc0044d07
    SOUND_MIXER_WRITE_RECSRC = 0xc0044dff
    SOUND_MIXER_LINE = 7
    SOUND_MASK_LINE = 64
    
    def __init__(self):
        plugin.DaemonPlugin.__init__(self)
        self.plugin_name = 'MIXER'
        self.mixfd = None
        self.muted = 0
        
        # If you're using ALSA or something and you don't set the mixer, why are
        # we trying to open it?
        if config.DEV_MIXER:    
            try:
                self.mixfd = open(config.DEV_MIXER, 'r')
            except IOError:
                print 'Couldn\'t open mixer %s' % config.DEV_MIXER
                return

        if 0:
            self.mainVolume   = 0
            self.pcmVolume    = 0
            self.lineinVolume = 0
            self.micVolume    = 0
            self.igainVolume  = 0 # XXX Used on SB Live
            self.ogainVolume  = 0 # XXX Ditto

            if self.mixfd:
                data = struct.pack( 'L', self.SOUND_MASK_LINE )
                try:
                    fcntl.ioctl( self.mixfd.fileno(), self.SOUND_MIXER_WRITE_RECSRC, 
data )
                except IOError:
                    _debug_('IOError for ioctl')
                    pass
                
        if config.MAJOR_AUDIO_CTRL == 'VOL':
            self.setMainVolume(config.DEFAULT_VOLUME)
            if config.CONTROL_ALL_AUDIO:
                self.setPcmVolume(config.MAX_VOLUME)
                # XXX This is for SB Live cards should do nothing to others
                # XXX Please tell if you have problems with this.
                self.setOgainVolume(config.MAX_VOLUME)
        elif config.MAJOR_AUDIO_CTRL == 'PCM':
            self.setPcmVolume(config.DEFAULT_VOLUME)
            if config.CONTROL_ALL_AUDIO:
                self.setMainVolume(config.MAX_VOLUME)
                # XXX This is for SB Live cards should do nothing to others
                # XXX Please tell if you have problems with this.
                self.setOgainVolume(config.MAX_VOLUME)
        else:
            _debug_("No appropriate audio channel found for mixer")

        if config.CONTROL_ALL_AUDIO:
            self.setLineinVolume(0)
            self.setMicVolume(0)


    def eventhandler(self, event = None, menuw=None, arg=None):
        """
        eventhandler to handle the VOL events
        """
        if event == MIXER_VOLUP:
            if config.MAJOR_AUDIO_CTRL == 'VOL':
                self.incMainVolume(event.arg)
                rc.post_event(Event(OSD_MESSAGE, arg=_('Volume: %s%%') % 
self.getVolume()))
            elif config.MAJOR_AUDIO_CTRL == 'PCM':
                self.incPcmVolume(event.arg)
                rc.post_event(Event(OSD_MESSAGE, arg=_('Volume: %s%%') % 
self.getVolume()))
            return True
        
        elif event == MIXER_VOLDOWN:
            if( config.MAJOR_AUDIO_CTRL == 'VOL' ):
                self.decMainVolume(event.arg)
                rc.post_event(Event(OSD_MESSAGE, arg=_('Volume: %s%%') % 
self.getVolume()))
            elif( config.MAJOR_AUDIO_CTRL == 'PCM' ):
                self.decPcmVolume(event.arg)
                rc.post_event(Event(OSD_MESSAGE, arg=_('Volume: %s%%') % 
self.getVolume()))
            return True

        elif event == MIXER_MUTE:
            if self.getMuted() == 1:
                rc.post_event(Event(OSD_MESSAGE, arg=_('Volume: %s%%') % 
self.getVolume()))
                self.setMuted(0)
            else:
                rc.post_event(Event(OSD_MESSAGE, arg=_('Mute')))
                self.setMuted(1)
            return True

        return False
        
        
    def _setVolume(self, device, volume):
        if self.mixfd:
            if volume < 0:
                volume = 0
            if volume > 100:
                volume = 100
            vol = (volume << 8) | (volume)
            data = struct.pack('L', vol)
            try:
                fcntl.ioctl(self.mixfd.fileno(), device, data)
            except IOError:
                _debug_('IOError for ioctl')
                pass

    def _setVolumeAlsa(self, volume):
        cmd = ""
        for slider in config.MAJOR_AUDIO_CTRLS:
            cmd += 'amixer -q set %s %s%% &' % (slider, volume)
        popen2.Popen3(cmd)


    def setMuted(self, mute):
        self.muted = mute
        cmd = ""
        if self.muted == 1:
            for slider in config.MAJOR_AUDIO_CTRLS:
                cmd += 'amixer -q set %s mute &' % (slider)
        else:
            for slider in config.MAJOR_AUDIO_CTRLS:
                cmd += 'amixer -q set %s unmute &' % (slider)
        popen2.Popen3(cmd)
            
            
    def getMuted(self):
        return(self.muted)

#    def setMuted(self, mute):
#        self.muted = mute
#        self._setMuted()

    def getVolume(self):
        #if config.MAJOR_AUDIO_CTRL == 'VOL':
        #    return self.mainVolume
        #elif config.MAJOR_AUDIO_CTRL == 'PCM':
        #    return self.pcmVolume
        return self.mainVolume
        
    def getMainVolume(self):
        return(self.mainVolume)

    def setMainVolume(self, volume):
        self.mainVolume = volume
        self._setVolumeAlsa(self.mainVolume)

    def incMainVolume(self, step=5):
        self.mainVolume += step
        if self.mainVolume > 100:
            self.mainVolume = 100
        self._setVolumeAlsa(self.mainVolume)

    def decMainVolume(self, step=5):
        self.mainVolume -= step
        if self.mainVolume < 0:
            self.mainVolume = 0
        self._setVolumeAlsa(self.mainVolume)

    def getPcmVolume(self):
        return self.pcmVolume
    
    def setPcmVolume(self, volume):
        self.pcmVolume = volume
        self._setVolume(self.SOUND_MIXER_WRITE_PCM, volume)

    def incPcmVolume(self, step=5):
        self.pcmVolume += step
        if self.pcmVolume > 100:
            self.pcmvolume = 100
        self._setVolume( self.SOUND_MIXER_WRITE_PCM, self.pcmVolume )

    def decPcmVolume(self, step=5):
        self.pcmVolume -= step
        if self.pcmVolume < 0:
            self.pcmVolume = 0
        self._setVolume( self.SOUND_MIXER_WRITE_PCM, self.pcmVolume )
    
    def setLineinVolume(self, volume):
        if config.CONTROL_ALL_AUDIO:
            self.lineinVolume = volume
            self._setVolume(self.SOUND_MIXER_WRITE_LINE, volume)

    def getLineinVolume(self):
        return self.lineinVolume
       
    def setMicVolume(self, volume):
        if config.CONTROL_ALL_AUDIO:
            self.micVolume = volume
            self._setVolume(self.SOUND_MIXER_WRITE_MIC, volume)

    def setIgainVolume(self, volume):
        """For Igain (input from TV etc) on emu10k cards"""
        if config.CONTROL_ALL_AUDIO:
            if volume > 100:
                volume = 100 
            elif volume < 0:
                volume = 0
            self.igainVolume = volume
            os.system('aumix -i%s > /dev/null 2>&1 &' % volume)

    def getIgainVolume(self):
        return self.igainVolume

    def decIgainVolume(self, step=5):
        self.igainVolume -= step
        if self.igainVolume < 0:
            self.igainVolume = 0
        os.system('aumix -i-%s > /dev/null 2>&1 &' % step)
        
    def incIgainVolume(self, step=5):
        self.igainVolume += step
        if self.igainVolume > 100:
            self.igainVolume = 100
        os.system('aumix -i+%s > /dev/null 2>&1 &' % step)
        
    def setOgainVolume(self, volume):
        """For Ogain on SB Live Cards"""
        if volume > 100:
            volume = 100 
        elif volume < 0:
            volume = 0
        self.ogainVolume = volume
        os.system('aumix -o%s > /dev/null 2>&1' % volume)

    def reset(self):
        if config.CONTROL_ALL_AUDIO:
            self.setLineinVolume(0)
            self.setMicVolume(0)
            if config.MAJOR_AUDIO_CTRL == 'VOL':
                self.setPcmVolume(config.MAX_VOLUME)
            elif config.MAJOR_AUDIO_CTRL == 'PCM':
                self.setMainVolume(config.MAX_VOLUME)

        self.setIgainVolume(0) # SB Live input from TV Card.

Reply via email to