--- mythtv.orig/libs/libmyth/audiooutputalsa.h
+++ mythtv/libs/libmyth/audiooutputalsa.h
@@ -9,44 +9,6 @@
 
 using namespace std;
 
-class ALSAVolumeInfo
-{
-  public:
-    ALSAVolumeInfo(long  playback_vol_min,
-                   long  playback_vol_max) :
-        range_multiplier(1.0f),
-        volume_min(playback_vol_min), volume_max(playback_vol_max)
-    {
-        float range = (float) (volume_max - volume_min);
-        if (range > 0.0f)
-            range_multiplier = 100.0f / range;
-        range_multiplier_inv = 1.0f / range_multiplier;
-    }
-
-    int ToMythRange(long alsa_volume)
-    {
-        long toz = alsa_volume - volume_min;
-        int val = (int) (toz * range_multiplier);
-        val = (val < 0)   ? 0   : val;
-        val = (val > 100) ? 100 : val;
-        return val;
-    }
-
-    long ToALSARange(int myth_volume)
-    {
-        float tos = myth_volume * range_multiplier_inv;
-        long val = (long) (tos + volume_min + 0.5);
-        val = (val < volume_min) ? volume_min : val;
-        val = (val > volume_max) ? volume_max : val;
-        return val;
-    }
-
-    float range_multiplier;
-    float range_multiplier_inv;
-    long  volume_min;
-    long  volume_max;
-};
-
 class AudioOutputALSA : public AudioOutputBase
 {
   public:
@@ -72,22 +34,25 @@
                              unsigned int rate, unsigned int buffer_time,
                              unsigned int period_time);
 
-
     // Volume related
-    void SetCurrentVolume(QString control, int channel, int volume);
-    void OpenMixer(bool setstartingvolume);
-    void CloseMixer(void);
-    void SetupMixer(void);
-    ALSAVolumeInfo GetVolumeRange(snd_mixer_elem_t *elem) const;
+    bool OpenMixer(void);
 
   private:
     snd_pcm_t   *pcm_handle;
     int          numbadioctls;
     QMutex       killAudioLock;
-    snd_mixer_t *mixer_handle;
-    QString      mixer_control; // e.g. "PCM"
     snd_pcm_sframes_t (*pcm_write_func)(snd_pcm_t*, const void*, 
                                         snd_pcm_uframes_t);
+    struct {
+        QByteArray         device;
+        QByteArray         control;
+        snd_mixer_t*       handle;
+        snd_mixer_elem_t*  elem;
+        long               volmin;
+        long               volmax;
+        long               volrange;
+    } mixer;
+
 };
 
 #endif
--- mythtv.orig/libs/libmyth/audiooutputalsa.cpp
+++ mythtv/libs/libmyth/audiooutputalsa.cpp
@@ -21,9 +21,11 @@
 AudioOutputALSA::AudioOutputALSA(const AudioSettings &settings) :
     AudioOutputBase(settings),
     pcm_handle(NULL),             numbadioctls(0),
-    killAudioLock(false),         mixer_handle(NULL),
-    mixer_control(QString::null)
+    killAudioLock(false)
 {
+    mixer.handle = NULL;
+    mixer.elem = NULL;
+
     // Set everything up
     Reconfigure(settings);
 }
@@ -127,16 +129,21 @@
     // it really is
     audio_buffer_unused = soundcard_buffer_size - (fragment_size * 4);
 
-    if (internal_vol)
-        OpenMixer(set_initial_vol);
-    
+    if (internal_vol && !OpenMixer())
+    {
+        CloseDevice();
+        return false;
+    }
+
     // Device opened successfully
     return true;
 }
 
 void AudioOutputALSA::CloseDevice()
 {
-    CloseMixer();
+    if (mixer.handle != NULL)
+        snd_mixer_close(mixer.handle);
+    mixer.handle = NULL;
     if (pcm_handle != NULL)
     {
         snd_pcm_close(pcm_handle);
@@ -475,231 +482,155 @@
     return 0;
 }
 
-
 int AudioOutputALSA::GetVolumeChannel(int channel) const
 {
-    long actual_volume;
-
-    if (mixer_handle == NULL)
-        return 100;
-
-    QByteArray mix_ctl = mixer_control.toAscii();
-    snd_mixer_selem_id_t *sid;
-    snd_mixer_selem_id_alloca(&sid);
-    snd_mixer_selem_id_set_index(sid, 0);
-    snd_mixer_selem_id_set_name(sid, mix_ctl.constData());
-
-    snd_mixer_elem_t *elem = snd_mixer_find_selem(mixer_handle, sid);
-    if (!elem)
-    {
-        VERBOSE(VB_IMPORTANT, QString("Mixer unable to find control %1")
-                .arg(mixer_control));
-        return 100;
-    }
+    if (!mixer.elem)
+        return 0;
 
-    snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;
-    if (!snd_mixer_selem_has_playback_channel(elem, chan))
+    int retvol = 0;
+    long mixervol;
+    int chk;
+    if ((chk = snd_mixer_selem_get_playback_volume(mixer.elem,
+                 (snd_mixer_selem_channel_id_t)channel, &mixervol)) < 0)
+        VERBOSE(VB_IMPORTANT, LOC_ERR
+                + QString("failed to get channel %1 volume, mixer %2/%3: %4")
+                          .arg(channel).arg(mixer.device.constData())
+                          .arg(mixer.control.constData())
+                          .arg(snd_strerror(chk)));
+    else
     {
-        snd_mixer_selem_id_set_index(sid, channel);
-        if ((elem = snd_mixer_find_selem(mixer_handle, sid)) == NULL)
-        {
-            VERBOSE(VB_IMPORTANT, QString("Mixer unable to find control %1 %2")
-                    .arg(mixer_control).arg(channel));
-            return 100;
-        }
+        retvol = (mixer.volrange != 0L) ? (mixervol - mixer.volmin) * 100.0f
+                                          / mixer.volrange + .5f
+                                        : 0;
+        retvol = max(retvol, 0);
+        retvol = min(retvol, 100);
+        VERBOSE(VB_AUDIO+VB_EXTRA, LOC + QString("get volume channel %1: %2")
+                                                 .arg(channel).arg(retvol));
     }
-
-    ALSAVolumeInfo vinfo = GetVolumeRange(elem);
-
-    snd_mixer_selem_get_playback_volume(
-        elem, (snd_mixer_selem_channel_id_t)channel, &actual_volume);
-
-    return vinfo.ToMythRange(actual_volume);
+    return retvol;
 }
 
 void AudioOutputALSA::SetVolumeChannel(int channel, int volume)
 {
-    SetCurrentVolume(mixer_control, channel, volume);
-}
-
-void AudioOutputALSA::SetCurrentVolume(QString control, int channel, int volume)
-{
-    VERBOSE(VB_AUDIO, QString("Setting %1 volume to %2")
-            .arg(control).arg(volume));
-
-    if (!mixer_handle)
-        return; // no mixer, nothing to do
-
-    QByteArray ctl = control.toAscii();
-    snd_mixer_selem_id_t *sid;
-    snd_mixer_selem_id_alloca(&sid);
-    snd_mixer_selem_id_set_index(sid, 0);
-    snd_mixer_selem_id_set_name(sid, ctl.constData());
-
-    snd_mixer_elem_t *elem = snd_mixer_find_selem(mixer_handle, sid);
-    if (!elem)
-    {
-        VERBOSE(VB_IMPORTANT, QString("Mixer unable to find control %1")
-                .arg(control));
+    if (!(internal_vol && mixer.elem))
         return;
-    }
-
-    snd_mixer_selem_channel_id_t chan = (snd_mixer_selem_channel_id_t) channel;
-    if (!snd_mixer_selem_has_playback_channel(elem, chan))
-    {
-        snd_mixer_selem_id_set_index(sid, channel);
-        if ((elem = snd_mixer_find_selem(mixer_handle, sid)) == NULL)
-        {
-            VERBOSE(VB_IMPORTANT,
-                    QString("mixer unable to find control %1 %2")
-                    .arg(control).arg(channel));
-            return;
-        }
-    }
-
-    ALSAVolumeInfo vinfo = GetVolumeRange(elem);
-
-    long set_vol = vinfo.ToALSARange(volume);
 
-    int err = snd_mixer_selem_set_playback_volume(elem, chan, set_vol);
-    if (err < 0)
-    {
-        VERBOSE(VB_IMPORTANT, QString("mixer set channel %1 err %2: %3")
-                .arg(channel).arg(err).arg(snd_strerror(err)));
-    }
+    long mixervol = volume * mixer.volrange / 100.0f - mixer.volmin + 0.5f;
+    mixervol = max(mixervol, mixer.volmin);
+    mixervol = min(mixervol, mixer.volmax);
+    int chk;
+    if ((chk = snd_mixer_selem_set_playback_volume(mixer.elem,
+                 (snd_mixer_selem_channel_id_t)channel, mixervol)) < 0)
+        VERBOSE(VB_IMPORTANT, LOC_ERR
+                + QString("failed to set channel %1 volume").arg(channel));
     else
-    {
-        VERBOSE(VB_AUDIO, QString("channel %1 vol set to %2")
-                .arg(channel).arg(set_vol));
-    }
-
-    if (snd_mixer_selem_has_playback_switch(elem))
-    {
-        int unmute = (0 != set_vol);
-        if (snd_mixer_selem_has_playback_switch_joined(elem))
-        {
-            // Only mute if all the channels should be muted.
-            for (int i = 0; i < audio_channels; i++)
-            {
-                if (0 != GetVolumeChannel(i))
-                    unmute = 1;
-            }
-        }
-
-        err = snd_mixer_selem_set_playback_switch(elem, chan, unmute);
-        if (err < 0)
-        {
-            VERBOSE(VB_IMPORTANT, LOC_ERR +
-                    QString("Mixer set playback switch %1 err %2: %3")
-                    .arg(channel).arg(err).arg(snd_strerror(err)));
-        }
-        else
-        {
-            VERBOSE(VB_AUDIO, LOC +
-                    QString("channel %1 playback switch set to %2")
-                    .arg(channel).arg(unmute));
-        }
-    }
+        VERBOSE(VB_AUDIO+VB_EXTRA, LOC
+                + QString("channel %1 volume set %2 => %3")
+                          .arg(channel).arg(volume).arg(mixervol));
 }
 
-void AudioOutputALSA::OpenMixer(bool setstartingvolume)
+bool AudioOutputALSA::OpenMixer(void)
 {
-    int volume;
-
-    mixer_control = gContext->GetSetting("MixerControl", "PCM");
-
-    SetupMixer();
-
-    if (mixer_handle != NULL && setstartingvolume)
+    if (!pcm_handle)
     {
-        volume = gContext->GetNumSetting("MasterMixerVolume", 80);
-        SetCurrentVolume("Master", 0, volume);
-        SetCurrentVolume("Master", 1, volume);
-
-        volume = gContext->GetNumSetting("PCMMixerVolume", 80);
-        SetCurrentVolume("PCM", 0, volume);
-        SetCurrentVolume("PCM", 1, volume);
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "mixer setup without a pcm??");
+        return false;
+    }
+    mixer.device = gContext->GetSetting("MixerDevice", "default");
+    if (mixer.device.startsWith("ALSA:"))
+        mixer.device.remove(0, 5);
+    mixer.control = gContext->GetSetting("MixerControl", "PCM");
+    QString mixer_device_tag = QString("mixer device %1")
+                                       .arg(mixer.device.constData());
+    int chk;
+    if ((chk = snd_mixer_open(&mixer.handle, 0)) < 0)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR
+                + QString("failed to open %1: %2")
+                          .arg(mixer_device_tag).arg(snd_strerror(chk)));
+        return false;
     }
-}
-
-void AudioOutputALSA::CloseMixer(void)
-{
-    if (mixer_handle != NULL)
-        snd_mixer_close(mixer_handle);
-    mixer_handle = NULL;
-}
-
-void AudioOutputALSA::SetupMixer(void)
-{
-    int err;
-
-    QString alsadevice = gContext->GetSetting("MixerDevice", "default");
-    QString device = alsadevice.remove(QString("ALSA:"));
-
-    if (mixer_handle != NULL)
-        CloseMixer();
 
-    VERBOSE(VB_AUDIO, QString("Opening mixer %1").arg(device));
+    struct snd_mixer_selem_regopt regopts =
+        {1, SND_MIXER_SABSTRACT_NONE, mixer.device.constData(), NULL, NULL};
 
-    // TODO: This is opening card 0. Fix for case of multiple soundcards
-    if ((err = snd_mixer_open(&mixer_handle, 0)) < 0)
+    if ((chk = snd_mixer_selem_register(mixer.handle, &regopts, NULL)) < 0)
     {
-        Warn(QString("Mixer device open error %1: %2")
-             .arg(err).arg(snd_strerror(err)));
-        mixer_handle = NULL;
-        return;
+        snd_mixer_close(mixer.handle);
+        mixer.handle = NULL;
+        VERBOSE(VB_IMPORTANT, LOC_ERR
+                + QString("failed to register %1: %2")
+                          .arg(mixer_device_tag).arg(snd_strerror(chk)));
+        return false;
     }
 
-    QByteArray dev = device.toAscii();
-    if ((err = snd_mixer_attach(mixer_handle, dev.constData())) < 0)
+    if ((chk = snd_mixer_load(mixer.handle)) < 0)
     {
-        Warn(QString("Mixer attach error %1: %2"
-                     "\n\t\t\tCheck Mixer Name in Setup: '%3'")
-             .arg(err).arg(snd_strerror(err)).arg(device));
-        CloseMixer();
-        return;
+        snd_mixer_close(mixer.handle);
+        mixer.handle = NULL;
+        VERBOSE(VB_IMPORTANT, LOC_ERR
+                + QString("failed to load %1: %2")
+                          .arg(mixer_device_tag).arg(snd_strerror(chk)));
+        return false;
     }
 
-    if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL)) < 0)
-    {
-        Warn(QString("Mixer register error %1: %2")
-             .arg(err).arg(snd_strerror(err)));
-        CloseMixer();
-        return;
+    mixer.elem = NULL;
+    unsigned int elcount = snd_mixer_get_count(mixer.handle);
+    snd_mixer_elem_t* elx = snd_mixer_first_elem(mixer.handle);
+    for (unsigned int ctr = 0; elx != NULL && ctr < elcount; ++ctr)
+    {
+        if (!strcmp(mixer.control.constData(), snd_mixer_selem_get_name(elx))
+            && !snd_mixer_selem_is_enumerated(elx)
+            && snd_mixer_selem_has_playback_volume(elx)
+            && snd_mixer_selem_is_active(elx))
+        {
+            mixer.elem = elx;
+            VERBOSE(VB_AUDIO+VB_EXTRA, LOC + mixer_device_tag
+                    + QString("found playback control %1 on %2 :-)")
+                              .arg(mixer.control.constData())
+                              .arg(mixer_device_tag));
+            break;
+        }
+        elx = snd_mixer_elem_next(elx);
+    }
+    if (!mixer.elem)
+    {
+        snd_mixer_close(mixer.handle);
+        mixer.handle = NULL;
+        VERBOSE(VB_IMPORTANT, LOC_ERR
+                + QString("no playback control %1 found on %2")
+                          .arg(mixer.control.constData()).arg(mixer_device_tag));
+        return false;
     }
-
-    if ((err = snd_mixer_load(mixer_handle)) < 0)
+    if ((snd_mixer_selem_get_playback_volume_range(mixer.elem, &mixer.volmin,
+                                                   &mixer.volmax) < 0))
     {
-        Warn(QString("Mixer load error %1: %2")
-             .arg(err).arg(snd_strerror(err)));
-        CloseMixer();
-        return;
+        snd_mixer_close(mixer.handle);
+        mixer.handle = NULL;
+        VERBOSE(VB_IMPORTANT, LOC_ERR + mixer_device_tag
+                + QString("failed to get volume range on %1/%2")
+                          .arg(mixer_device_tag).arg(mixer.control.constData()));
+        return false;
     }
-}
-
-ALSAVolumeInfo AudioOutputALSA::GetVolumeRange(snd_mixer_elem_t *elem) const
-{
-    long volume_min, volume_max;
-
-    int err = snd_mixer_selem_get_playback_volume_range(
-        elem, &volume_min, &volume_max);
-
-    if (err < 0)
-    {
-        static bool first_time = true;
-        if (first_time)
-        {
-            VERBOSE(VB_IMPORTANT,
-                    "snd_mixer_selem_get_playback_volume_range()" + ENO);
-            first_time = false;
-        }
+    mixer.volrange = mixer.volmax - mixer.volmin;
+    VERBOSE(VB_AUDIO+VB_EXTRA, LOC
+            + QString("mixer volume range on %1/%2 - min %3, max %4, range %5")
+                      .arg(mixer_device_tag).arg(mixer.control.constData())
+                      .arg(mixer.volmin).arg(mixer.volmax).arg(mixer.volrange));
+
+    VERBOSE(VB_AUDIO, LOC + QString("%1/%2 set up successfully")
+                                    .arg(mixer_device_tag)
+                                    .arg(mixer.control.constData()));
+    if (set_initial_vol)
+    {
+        int initial_vol;
+        if ( mixer.control == "PCM")
+            initial_vol = gContext->GetNumSetting("PCMMixerVolume", 80);
+        else
+            initial_vol = gContext->GetNumSetting("MasterMixerVolume", 80);
+        for (int ch = 0; ch < audio_channels; ++ch)
+            SetVolumeChannel(ch, initial_vol);
     }
 
-    ALSAVolumeInfo vinfo(volume_min, volume_max);
-
-    VERBOSE(VB_AUDIO, QString("Volume range is %1 to %2, mult=%3")
-            .arg(vinfo.volume_min).arg(vinfo.volume_max)
-            .arg(vinfo.range_multiplier));
-
-    return vinfo;
-}
+    return true;
+}
\ No newline at end of file
