[mythtv] [PATCH] volume control for OSS and ALSA

David George david at thegeorges.us
Tue Oct 26 14:29:47 UTC 2004


This is a standalone patch against CVS as of this morning (which 
includes the first part of the big audio update).

Just posting it so people can try it out before it gets merged into the 
big audio update.  OSS and ALSA have been tested.

Just an FYI for those with Intel ICH4 sound on their motherboard and 
*optical* output.  It doesn't appear that the mixer settings will change 
the volume.  This isn't just in Myth, it affects other ALSA applications 
like mplayer and aplay also (I also tested changing the mixer settings 
with alsamixer and gnome-alsamixer).  When I moved the cables to analog 
5.1 the volume control worked.  Just warning you so no-one beats there 
head against the wall.
--
David

-------------- next part --------------
Index: libs/libmyth/libmyth.pro
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmyth/libmyth.pro,v
retrieving revision 1.55
diff -u -r1.55 libmyth.pro
--- libs/libmyth/libmyth.pro	26 Oct 2004 01:16:38 -0000	1.55
+++ libs/libmyth/libmyth.pro	26 Oct 2004 14:12:51 -0000
@@ -14,7 +14,7 @@
 HEADERS += volumecontrol.h uitypes.h xmlparse.h mythplugin.h mythdbcon.h
 HEADERS += mythdialogs.h audiooutput.h inetcomms.h httpcomms.h mythmedia.h 
 HEADERS += uilistbtntype.h uiphoneentry.h generictree.h screensaver.h
-HEADERS += managedlist.h DisplayRes.h audiooutputbase.h
+HEADERS += managedlist.h DisplayRes.h audiooutputbase.h volumecontrolbase.h
 
 SOURCES += dialogbox.cpp lcddevice.cpp mythcontext.cpp mythwidgets.cpp 
 SOURCES += oldsettings.cpp remotefile.cpp settings.cpp themedmenu.cpp
@@ -22,7 +22,7 @@
 SOURCES += mythplugin.cpp mythdialogs.cpp audiooutput.cpp inetcomms.cpp 
 SOURCES += httpcomms.cpp mythmedia.cpp uilistbtntype.cpp uiphoneentry.cpp
 SOURCES += generictree.cpp managedlist.cpp DisplayRes.cpp DisplayResX.cpp
-SOURCES += audiooutputbase.cpp
+SOURCES += audiooutputbase.cpp volumecontrolbase.cpp
 
 LIBS += -L../libmythsamplerate
 LIBS += -lmythsamplerate-$${LIBVERSION}
@@ -37,8 +37,9 @@
 inc.files += uilistbtntype.h uiphoneentry.h generictree.h managedlist.h
 
 using_oss {
-    SOURCES += audiooutputoss.cpp
-    HEADERS += audiooutputoss.h
+    DEFINES += USE_OSS
+    SOURCES += audiooutputoss.cpp volumecontroloss.cpp
+    HEADERS += audiooutputoss.h volumecontroloss.h
 }
 
 unix {
@@ -78,8 +79,8 @@
 
 using_alsa {
     DEFINES += USE_ALSA
-    HEADERS += audiooutputalsa.h
-    SOURCES += audiooutputalsa.cpp
+    HEADERS += audiooutputalsa.h volumecontrolalsa.h
+    SOURCES += audiooutputalsa.cpp volumecontrolalsa.cpp
     LIBS += $$ALSA_LIBS
 }
 
Index: libs/libmyth/volumecontrol.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmyth/volumecontrol.cpp,v
retrieving revision 1.13
diff -u -r1.13 volumecontrol.cpp
--- libs/libmyth/volumecontrol.cpp	22 Oct 2004 09:32:54 -0000	1.13
+++ libs/libmyth/volumecontrol.cpp	26 Oct 2004 14:12:51 -0000
@@ -1,201 +1,34 @@
-#include "volumecontrol.h"
-
-#ifdef USING_OSS
-#include <sys/soundcard.h>
-#endif
-
-#include <sys/ioctl.h>
-#include <fcntl.h>
+#include <qstring.h>
 #include <cstdio>
-#include <unistd.h>
+#include <cstdlib>
 
-#include <iostream>
 using namespace std;
 
-#include "mythcontext.h"
-
-VolumeControl::VolumeControl(bool setstartingvolume)
-{
-    mixerfd = -1;
-    volume = 0;
-
-#ifdef USING_OSS
-    mute = false;
-    current_mute_state = MUTE_OFF;
-  
-    QString device = gContext->GetSetting("MixerDevice", "/dev/mixer");
-    mixerfd = open(device.ascii(), O_RDONLY);
-
-    QString controlLabel = gContext->GetSetting("MixerControl", "PCM");
-
-    if (controlLabel == "Master")
-    {
-        control = SOUND_MIXER_VOLUME;
-    }
-    else
-    {
-        control = SOUND_MIXER_PCM;
-    }
-
-    if (mixerfd < 0)
-    {
-        cerr << "Unable to open mixer: '" << device << "'\n";
-        return;
-    }
-
-    int realvol;
-
-    if (setstartingvolume)
-    {
-        volume = gContext->GetNumSetting("MasterMixerVolume", 80);
-        realvol = (volume << 8) + volume;
-        int ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_VOLUME), &realvol);
-        if (ret < 0)
-            perror("Setting master volume: ");
-
-        volume = gContext->GetNumSetting("PCMMixerVolume", 80);
-        realvol = (volume << 8) + volume;
-        ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_PCM), &realvol);
-        if (ret < 0)
-            perror("Setting PCM volume: ");
-    }
-
-    internal_volume = GetCurrentVolume();
+#include "volumecontrol.h"
+#ifdef USE_OSS
+#include "volumecontroloss.h"
 #endif
-}
-
-VolumeControl::~VolumeControl()
-{
-    if (mixerfd >= 0)
-        close(mixerfd);
-}
-
-int VolumeControl::GetCurrentVolume(void)
-{
-#ifdef USING_OSS
-    int realvol;
-    
-    if (mute)
-    {
-        return internal_volume;
-    }
-    else
-    {
-        int ret = ioctl(mixerfd, MIXER_READ(control), &realvol);
-        if (ret < 0)
-        {
-            perror("Reading PCM volume: ");
-        }
-        volume = realvol & 0xff; // just use the left channel
-        internal_volume = volume;
-    }
-#endif    
-
-    return volume;
-}
-
-void VolumeControl::SetCurrentVolume(int value)
-{
-#ifdef USING_OSS
-    volume = value;
-
-    if (volume > 100)
-        volume = 100;
-    if (volume < 0)
-        volume = 0;
-
-    internal_volume = volume;
-    if (mixerfd >= 0)
-    {
-        if (!mute)
-        {
-            int realvol = (volume << 8) + volume;
-            int ret = ioctl(mixerfd, MIXER_WRITE(control), &realvol);
-            if (ret < 0)
-                perror("Setting volume: ");
-        }
-    }
-
-    //mute = false;
-
-    QString controlLabel = gContext->GetSetting("MixerControl", "PCM");
-    controlLabel += "MixerVolume";
-    gContext->SaveSetting(controlLabel, volume);
+#ifdef USE_ALSA
+#include "volumecontrolalsa.h"
 #endif
-}
-
-void VolumeControl::AdjustCurrentVolume(int change)
-{
-    int newvol = GetCurrentVolume() + change;
-
-    SetCurrentVolume(newvol);
-}
 
-void VolumeControl::SetMute(bool on)
+VolumeControl *VolumeControl::OpenVolume(QString audiodevice,
+                                         bool setstartingvolume)
 {
-#ifdef USING_OSS
-    int realvol;
-
-    if (on)
+    if (audiodevice.startsWith("ALSA:"))
     {
-        realvol = 0;
+#ifdef USE_ALSA
+        return new VolumeControlALSA(setstartingvolume);
+#else
+        VERBOSE(VB_IMPORTANT, "Audio is set to an ALSA device "
+                "but ALSA support is not compiled in!\n");
+        return NULL;
+#endif
     }
+#if defined(USE_OSS)
     else
-    {
-        realvol = (internal_volume << 8) + internal_volume;
-    }
-    if (mixerfd >= 0)
-    {
-        int ret = ioctl(mixerfd, MIXER_WRITE(control), &realvol);
-        if (ret < 0)
-            perror("Setting mute:");
-    }
-
-    mute = on;
+        return new VolumeControlOSS(setstartingvolume);
 #endif
-}
-
-void VolumeControl::ToggleMute(void)
-{
-    SetMute(!mute);
-}
-
-kMuteState VolumeControl::IterateMutedChannels(void)
-{
-// current_mute_state is initialized to "MUTE_OFF".  If individual muting
-// is enabled, each call to SetMute will advance to the next state:
-// MUTE_OFF -> MUTE_LEFT -> MUTE_RIGHT -> MUTE_BOTH -> MUTE_OFF
-#ifdef USING_OSS
-    int realvol;
 
-    switch (current_mute_state)
-    {
-       case MUTE_OFF:
-           current_mute_state = MUTE_LEFT;
-           realvol = (internal_volume << 8) + 0;
-           break;
-       case MUTE_LEFT:
-           current_mute_state = MUTE_RIGHT;
-           realvol = (0 << 8) + internal_volume;
-           break;
-       case MUTE_RIGHT:
-           current_mute_state = MUTE_BOTH;
-           realvol = 0;
-           break;
-       case MUTE_BOTH:
-           current_mute_state = MUTE_OFF;
-           realvol = (internal_volume << 8) + internal_volume;
-           break;
-    }
-
-    if (mixerfd >= 0)
-    {
-        int ret = ioctl(mixerfd, MIXER_WRITE(control), &realvol);
-        if (ret < 0)
-            perror("IterateMutedChannels:");
-    }
-
-    return (current_mute_state);
-
-#endif
+    return NULL;
 }
Index: libs/libmyth/volumecontrol.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmyth/volumecontrol.h,v
retrieving revision 1.4
diff -u -r1.4 volumecontrol.h
--- libs/libmyth/volumecontrol.h	2 Mar 2004 21:00:05 -0000	1.4
+++ libs/libmyth/volumecontrol.h	26 Oct 2004 14:12:52 -0000
@@ -1,31 +1,38 @@
 #ifndef VOLUMECONTROL_H_
 #define VOLUMECONTROL_H_
 
+#include <iostream>
+
+using namespace std;
+
+#include "mythcontext.h"
+
 typedef enum { MUTE_OFF=0, MUTE_LEFT, MUTE_RIGHT, MUTE_BOTH } kMuteState;
 
 class VolumeControl
 {
   public:
-    VolumeControl(bool setstartingvolume = true);
-   ~VolumeControl();
+    static VolumeControl *OpenVolume(QString audiodevice,
+                                     bool setstartingvolume);
 
-    int GetCurrentVolume(void);
-    void SetCurrentVolume(int value);
-    void AdjustCurrentVolume(int change);
-
-    void SetMute(bool on);
-    void ToggleMute(void);
-    bool GetMute(void) { return mute; }
-    kMuteState IterateMutedChannels(void);
+    VolumeControl() { lastError = QString::null; };
+    virtual ~VolumeControl() { };
 
-  private:
-    int mixerfd;
-    int volume;
-    int internal_volume;
-    int control;
+    virtual void AdjustCurrentVolume(int change) = 0;
+    virtual int GetCurrentVolume(void) = 0;
+    virtual void SetMute(bool on) = 0;
+    virtual void ToggleMute(void) = 0;
+    virtual bool GetMute(void) = 0;
+    virtual kMuteState IterateMutedChannels(void) = 0;
+
+    QString GetError() { return lastError; };
+
+  protected:
+    void Error(QString msg)
+        { lastError = msg; VERBOSE(VB_ALL, lastError); };
 
-    bool mute;
-    kMuteState current_mute_state;
+  private:
+    QString lastError;
 };
 
 #endif
Index: libs/libmythtv/tv_play.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/tv_play.cpp,v
retrieving revision 1.217
diff -u -r1.217 tv_play.cpp
--- libs/libmythtv/tv_play.cpp	25 Oct 2004 17:22:42 -0000	1.217
+++ libs/libmythtv/tv_play.cpp	26 Oct 2004 14:12:54 -0000
@@ -358,7 +358,10 @@
     }
 
     if (gContext->GetNumSetting("MythControlsVolume", 1))
-        volumeControl = new VolumeControl(true);
+    {
+        QString audiodevice = gContext->GetSetting("AudioOutputDevice");
+        volumeControl = VolumeControl::OpenVolume(audiodevice, true);
+    }
 
     pthread_create(&event, NULL, EventThread, this);
 
-------------- next part --------------
Index: mythmusic/playbackbox.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythmusic/mythmusic/playbackbox.cpp,v
retrieving revision 1.74
diff -u -r1.74 playbackbox.cpp
--- mythmusic/playbackbox.cpp	23 Oct 2004 20:15:06 -0000	1.74
+++ mythmusic/playbackbox.cpp	26 Oct 2004 14:19:12 -0000
@@ -75,7 +75,8 @@
     volume_display_timer = new QTimer(this);
     if (gContext->GetNumSetting("MythControlsVolume", 0))
     {
-        volume_control = new VolumeControl(true);
+        QString audiodevice = gContext->GetSetting("AudioOutputDevice");
+        volume_control = VolumeControl::OpenVolume(audiodevice, true);
         volume_display_timer->start(2000);
         connect(volume_display_timer, SIGNAL(timeout()), this, SLOT(hideVolume()));
     }


More information about the mythtv-dev mailing list