Index: libs/libmythtv/nuppeldecoder.cpp
===================================================================
--- libs/libmythtv/nuppeldecoder.cpp	(revision 22906)
+++ libs/libmythtv/nuppeldecoder.cpp	(working copy)
@@ -1323,6 +1323,24 @@
     return true;
 }
 
+int NuppelDecoder::GetAudioProperties(void)
+{
+    VERBOSE(VB_AUDIO, LOC + QString("Getting Nuppel Audio Props"));
+     
+    if (!mpa_audctx)
+    {
+        VERBOSE(VB_AUDIO, LOC + QString("No Audio Context, ignoring audio props"));
+        return -1;
+    }
+
+    int props = GetAudioPropertiesFromContext(mpa_audctx);
+
+    // no way to find AUD_HARDHEAR so ignore
+    // DH: I don't know what AUD_VISUALIMPAIR is so ignore
+
+    return props;
+}
+
 void NuppelDecoder::SeekReset(long long newKey, uint skipFrames,
                               bool doFlush, bool discardFrames)
 {
Index: libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.cpp	(revision 22906)
+++ libs/libmythtv/NuppelVideoPlayer.cpp	(working copy)
@@ -7914,6 +7914,28 @@
     osdtheme = themename; osdtheme.detach();
 }
 
+int NuppelVideoPlayer::GetAudioProperties(void)
+{
+    using_null_videoout = true;
+
+    VERBOSE(VB_AUDIO, LOC + "opening file for audio props");
+    if (OpenFile(false, 0, false) < 0)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open file for audio props.");
+        return NULL;
+    }
+
+    VERBOSE(VB_AUDIO, LOC + "Getting decoder for audio props");
+    if (GetDecoder()) 
+    {
+	VERBOSE(VB_AUDIO, QString("Found decoder, getting audio props"));
+    	return GetDecoder()->GetAudioProperties();
+    }
+
+    VERBOSE(VB_IMPORTANT, QString("Found no decoder for audio props"));
+    return -1;
+}
+
 // EIA-708 caption support -- end
 
 static unsigned dbg_ident(const NuppelVideoPlayer *nvp)
Index: libs/libmythtv/audiopropsgenerator.cpp
===================================================================
--- libs/libmythtv/audiopropsgenerator.cpp	(revision 0)
+++ libs/libmythtv/audiopropsgenerator.cpp	(revision 0)
@@ -0,0 +1,137 @@
+// MythTV headers
+#include "RingBuffer.h"
+#include "NuppelVideoPlayer.h"
+#include "audiopropsgenerator.h"
+#include "tv_rec.h"
+#include "playercontext.h"
+#include "mythverbose.h"
+
+#define LOC QString("Audio Props: ")
+#define LOC_ERR QString("Audio Props Error: ")
+#define LOC_WARN QString("Audio Props Warning: ")
+
+/** \class AudioPropsGenerator
+ *  \brief This class updates the Audio Properties of a recording.
+ *
+ *   The usage is simple: First, pass a ProgramInfo whose pathname points
+ *   to a local or remote recording to the constructor. Then call either
+ *   Start(void) or Run(void) to update the audio props.
+ *
+ *   Start(void) will create a thread that processes the request.
+ *
+ *   Run(void) will process the request in the current thread, 
+ *
+ *   The AudioPropsGenerator will send Qt signals when the update is ready
+ *   and when the thread finishes running if Start(void) was called.
+ */
+
+/**
+ *  \brief Constructor
+ *
+ *  \param pginfo     ProgramInfo for the reording we want to generate audio props for
+ */
+AudioPropsGenerator::AudioPropsGenerator(const ProgramInfo *pginfo)
+    : programInfo(*pginfo)
+{
+    VERBOSE(VB_AUDIO, LOC + QString("Constructing Audio Props Generator"));
+}
+
+AudioPropsGenerator::~AudioPropsGenerator()
+{
+    VERBOSE(VB_AUDIO, LOC + QString("Deconstructing Audio Props Generator"));
+
+    audioPropsLock.lock();
+    emit audioPropsThreadDone(&programInfo);
+    audioPropsLock.unlock();
+    disconnectSafe();
+}
+
+void AudioPropsGenerator::AttachSignals(QObject *obj)
+{
+    QMutexLocker locker(&audioPropsLock);
+    qRegisterMetaType<bool>("bool &");
+    connect(this, SIGNAL(audioPropsThreadDone(const QString&,bool&)),
+            obj,  SLOT(  audioPropsThreadDone(const QString&,bool&)),
+            Qt::DirectConnection);
+    connect(this, SIGNAL(audioPropsReady(const ProgramInfo*)),
+            obj,  SLOT(  audioPropsReady(const ProgramInfo*)),
+            Qt::DirectConnection);
+}
+
+/** \fn AudioProps::disconnectSafe(void)
+ *  \brief disconnects signals while holding audioPropsLock, ensuring that
+ *         no one will receive a signal from this class after this call.
+ */
+void AudioPropsGenerator::disconnectSafe(void)
+{
+    QMutexLocker locker(&audioPropsLock);
+    QObject::disconnect(this, NULL, NULL, NULL);
+}
+
+/** \fn AudioProps::Start(void)
+ *  \brief This call starts a thread that will update the audio props
+ */
+void AudioPropsGenerator::Start(void)
+{
+    pthread_create(&audioPropsThread, NULL, AudioPropsRun, this);
+    // detach, so we don't have to join thread to free thread local mem.
+    pthread_detach(audioPropsThread);
+}
+
+bool AudioPropsGenerator::Run(void)
+{
+    bool ok = UpdateAudioProps();
+
+    if (ok)
+    {
+        QMutexLocker locker(&audioPropsLock);
+        emit audioPropsReady(&programInfo);
+    }
+
+    return ok;
+}
+
+void *AudioPropsGenerator::AudioPropsRun(void *param)
+{
+    // Lower scheduling priority, to avoid problems with recordings.
+    if (setpriority(PRIO_PROCESS, 0, 9))
+        VERBOSE(VB_IMPORTANT, LOC + "Setting priority failed." + ENO);
+    AudioPropsGenerator *gen = (AudioPropsGenerator*) param;
+    gen->Run();
+    gen->deleteLater();
+    return NULL;
+}
+
+bool AudioPropsGenerator::UpdateAudioProps(void)
+{
+
+    VERBOSE(VB_AUDIO, LOC + QString("Starting Audio Inspection"));
+    PlayerContext *ctx = new PlayerContext(kAudioInspectorInUseID);
+
+    VERBOSE(VB_AUDIO, LOC + QString("Using file: %1").arg(programInfo.pathname));
+    RingBuffer *rbuf = new RingBuffer(programInfo.pathname, false, false, 0);
+
+    VERBOSE(VB_AUDIO, LOC + QString("Setting player"));
+    ctx->SetRingBuffer(rbuf);
+    ctx->SetPlayingInfo(&programInfo);
+    ctx->SetNVP(new NuppelVideoPlayer());
+    ctx->nvp->SetPlayerInfo(NULL, NULL, true, ctx);
+
+    VERBOSE(VB_AUDIO, LOC + QString("Getting audio props"));
+    int audioprops  = ctx->nvp->GetAudioProperties();
+
+    VERBOSE(VB_AUDIO, LOC + QString("Got audio props"));
+    bool updated = audioprops >= 0;
+
+    if (!updated)
+        VERBOSE(VB_IMPORTANT, LOC + QString("NOT Saving audio props for %1").arg(programInfo.title));
+    else
+    {
+        VERBOSE(VB_IMPORTANT, LOC + QString("Saving audio props (%1) for %2").arg(audioprops).arg(programInfo.title));
+        programInfo.SaveAudioProps(audioprops);
+    }
+
+    return updated;
+}
+
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
Index: libs/libmythtv/decoderbase.h
===================================================================
--- libs/libmythtv/decoderbase.h	(revision 22906)
+++ libs/libmythtv/decoderbase.h	(working copy)
@@ -147,6 +147,10 @@
 
     virtual QString GetXDS(const QString&) const { return QString::null; }
 
+    virtual int GetAudioProperties(void) = 0;
+
+    int GetAudioPropertiesFromContext(AVCodecContext *context);
+
     // MHEG/MHI stuff
     virtual bool SetAudioByComponentTag(int) { return false; }
     virtual bool SetVideoByComponentTag(int) { return false; }
Index: libs/libmythtv/avformatdecoder.cpp
===================================================================
--- libs/libmythtv/avformatdecoder.cpp	(revision 22906)
+++ libs/libmythtv/avformatdecoder.cpp	(working copy)
@@ -1859,7 +1859,6 @@
                 VERBOSE(VB_GENERAL, LOC + QString("codec %1 has %2 channels")
                         .arg(codec_id_string(enc->codec_id))
                         .arg(enc->channels));
-
 #if 0
                 // HACK MULTICHANNEL DTS passthru disabled for multichannel,
                 // dont know how to handle this
@@ -4383,6 +4382,69 @@
     return passthru;
 }
 
+// returns the AudioProperties for the current data
+int AvFormatDecoder::GetAudioProperties(void)
+{
+    VERBOSE(VB_AUDIO, LOC + QString("Getting AFD Audio Props"));
+
+    if (!ic)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + QString("No FormatContext, ignoring audio props"));
+        return -1;
+    }
+    
+    int props = 0;
+
+    // first try to find audio properties form the audio tracks
+    sinfo_vec_t::iterator it = tracks[kTrackTypeAudio].begin();
+    for (; it != tracks[kTrackTypeAudio].end(); ++it)
+    // for (uint i = 0; i < ic->nb_streams; i++)
+    {
+        //AVStream *stream = ic->streams[i];
+        AVStream *stream = ic->streams[it->av_stream_index];
+	int i = it->av_stream_index;
+
+        VERBOSE(VB_AUDIO, LOC + QString("Inspecting Audio Stream id #%1 ").arg(i));
+
+        // make sure there's a stream
+        if (!stream)
+        {
+             VERBOSE(VB_IMPORTANT, LOC + QString("No Stream for Stream id #%1").arg(i));
+             continue;
+        }
+
+        AVCodecContext *codec = stream->codec;
+
+        // mmake sure there's a codec
+        if (!codec)
+        {
+             VERBOSE(VB_IMPORTANT, LOC + QString("No Codec for Stream id #%1").arg(i));
+             continue;
+        }
+
+        props |= GetAudioPropertiesFromContext(codec);
+    }
+
+    // if there are any of these assume hard hearing
+    int track_count = kTrackTypeCount;
+    if ( 
+         (track_count >= kTrackTypeSubtitle         && tracks[kTrackTypeSubtitle].size() > 0)         ||
+         (track_count >= kTrackTypeCC608            && tracks[kTrackTypeCC608].size() > 0)            ||
+         (track_count >= kTrackTypeCC708            && tracks[kTrackTypeCC708].size() > 0)            ||
+         (track_count >= kTrackTypeTeletextCaptions && tracks[kTrackTypeTeletextCaptions].size() > 0) ||
+         (track_count >= kTrackTypeTeletextMenu     && tracks[kTrackTypeTeletextMenu].size() > 0)     ||
+         (track_count >= kTrackTypeTextSubtitle     && tracks[kTrackTypeTextSubtitle].size() > 0)     
+        )
+    {
+            VERBOSE(VB_AUDIO, LOC + QString("Found HARDHEARING Track"));
+            props |= AUD_HARDHEAR;
+    }
+
+    // DH: I don't know what AUD_VISUALIMPAIR is, so ignore it
+
+    return props;
+}
+
 /** \fn AvFormatDecoder::SetupAudioStream(void)
  *  \brief Reinitializes audio if it needs to be reinitialized.
  *
@@ -4424,7 +4486,7 @@
     if (info == audioIn)
         return false; // no change
 
-    VERBOSE(VB_AUDIO, LOC + "Initializing audio parms from " +
+    VERBOSE(VB_AUDIO, LOC + "Initializing audio params from " +
             QString("audio track #%1").arg(currentTrack[kTrackTypeAudio]+1));
 
     audioOut = audioIn = info;
Index: libs/libmythtv/libmythtv.pro
===================================================================
--- libs/libmythtv/libmythtv.pro	(revision 22906)
+++ libs/libmythtv/libmythtv.pro	(working copy)
@@ -151,6 +151,7 @@
 HEADERS += viewschdiff.h            livetvchain.h
 HEADERS += playgroup.h
 HEADERS += channelsettings.h        previewgenerator.h
+HEADERS += audiopropsgenerator.h
 HEADERS += transporteditor.h        listingsources.h
 HEADERS += myth_imgconvert.h
 HEADERS += channelgroup.h           channelgroupsettings.h
@@ -173,6 +174,7 @@
 SOURCES += viewschdiff.cpp
 SOURCES += livetvchain.cpp          playgroup.cpp
 SOURCES += channelsettings.cpp      previewgenerator.cpp
+SOURCES += audiopropsgenerator.cpp
 SOURCES += transporteditor.cpp
 SOURCES += channelgroup.cpp         channelgroupsettings.cpp
 SOURCES += myth_imgconvert.cpp
Index: libs/libmythtv/nuppeldecoder.h
===================================================================
--- libs/libmythtv/nuppeldecoder.h	(revision 22906)
+++ libs/libmythtv/nuppeldecoder.h	(working copy)
@@ -52,6 +52,8 @@
     QString GetCodecDecoderName(void) const { return "nuppel"; }
     MythCodecID GetVideoCodecID(void) const;
 
+    int GetAudioProperties(void);
+
   private:
     inline bool ReadFileheader(struct rtfileheader *fileheader);
     inline bool ReadFrameheader(struct rtframeheader *frameheader);
Index: libs/libmythtv/NuppelVideoPlayer.h
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.h	(revision 22906)
+++ libs/libmythtv/NuppelVideoPlayer.h	(working copy)
@@ -211,6 +211,7 @@
     QString   GetXDS(const QString &key) const;
     bool      GetAudioBufferStatus(uint &fill, uint &total) const;
     PIPLocation GetNextPIPLocation(void) const;
+    int       GetAudioProperties(void);
 
     // Bool Gets
     bool    GetRawAudioState(void) const;
Index: libs/libmythtv/decoderbase.cpp
===================================================================
--- libs/libmythtv/decoderbase.cpp	(revision 22906)
+++ libs/libmythtv/decoderbase.cpp	(working copy)
@@ -886,6 +886,65 @@
     return currentTrack[type];
 }
 
+/** \fn DecoderBase::GetAudioPropertiesFromContext(AVCodecContext *context)
+ *  \brief Get Audio Properties Enum from context object
+ *
+ *  \return int with bitwise properties, -1 otherwise
+ */
+int DecoderBase::GetAudioPropertiesFromContext(AVCodecContext *context)
+{
+    int props = 0;
+    // mmake sure there's a context
+    if (!context)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + QString("No context; ignoring audio props"));
+        return -1;
+    }
+
+    // use the channel_layout to approximate the data sound type
+    // we can't use channels because it gets overwritten in AutoSelectAudioTrack
+    int channel_layout = context->channel_layout;
+
+    VERBOSE(VB_AUDIO, LOC + QString("Channel Layout: %1").arg(channel_layout));
+
+    // assume DOLBY
+    if (    (channel_layout & CH_LAYOUT_5POINT1) == CH_LAYOUT_5POINT1 )
+    {
+        VERBOSE(VB_AUDIO, LOC + QString("Found DOLBY"));
+        props |= AUD_DOLBY;
+    }
+
+    // assume SURROUND
+    else if ( (channel_layout & CH_LAYOUT_SURROUND) == CH_LAYOUT_SURROUND)
+    {
+        VERBOSE(VB_AUDIO, LOC + QString("Found SURROUND"));
+        props |= AUD_SURROUND;
+    }
+
+    // assume stereo
+    else if ( (channel_layout & CH_LAYOUT_STEREO) == CH_LAYOUT_STEREO )
+    {
+        VERBOSE(VB_AUDIO, LOC + QString("Found STEREO"));
+        props |= AUD_STEREO;
+    }
+
+    // assume mono
+    else if ((channel_layout & CH_LAYOUT_MONO) == CH_LAYOUT_MONO)
+    {
+        VERBOSE(VB_AUDIO, LOC + QString("Found MONO"));
+        props |= AUD_MONO;
+    }
+    
+    // otherwise unknown
+    else
+    {
+        VERBOSE(VB_AUDIO, LOC + QString("Found UNKNOWN"));
+        props |= AUD_UNKNOWN;
+    }
+
+    return props;
+}
+
 StreamInfo DecoderBase::GetTrackInfo(uint type, uint trackNo) const
 {
     QMutexLocker locker(avcodeclock);
@@ -915,6 +974,8 @@
     return true;
 }
 
+
+
 /** \fn DecoderBase::AutoSelectTrack(uint)
  *  \brief Select best track.
  *
Index: libs/libmythtv/avformatdecoder.h
===================================================================
--- libs/libmythtv/avformatdecoder.h	(revision 22906)
+++ libs/libmythtv/avformatdecoder.h	(working copy)
@@ -200,6 +200,8 @@
     bool GenerateDummyVideoFrame(void);
     bool HasVideo(const AVFormatContext *ic);
 
+    virtual int GetAudioProperties(void);
+
   private:
     class AvFormatDecoderPrivate *d;
 
Index: libs/libmythtv/tv_rec.cpp
===================================================================
--- libs/libmythtv/tv_rec.cpp	(revision 22906)
+++ libs/libmythtv/tv_rec.cpp	(working copy)
@@ -30,6 +30,7 @@
 #include "eitscanner.h"
 #include "RingBuffer.h"
 #include "previewgenerator.h"
+#include "audiopropsgenerator.h"
 #include "storagegroup.h"
 #include "remoteutil.h"
 #include "tvremoteutil.h"
@@ -1120,6 +1151,7 @@
         if (!killFile)
         {
             (new PreviewGenerator(curRecording, PreviewGenerator::kLocal))->Start();
+            (new AudioPropsGenerator(curRecording))->Start();
 
             if (!tvchain)
             {
Index: libs/libmythtv/audiopropsgenerator.h
===================================================================
--- libs/libmythtv/audiopropsgenerator.h	(revision 0)
+++ libs/libmythtv/audiopropsgenerator.h	(revision 0)
@@ -0,0 +1,39 @@
+// -*- Mode: c++ -*-
+#ifndef AUDIOPROPS_GENERATOR_H_
+#define AUDIOPROPS_GENERATOR_H_
+
+#include <pthread.h>
+
+#include <QMutex>
+#include <QString>
+
+#include "programinfo.h"
+
+class MPUBLIC AudioPropsGenerator : public QObject
+{
+    Q_OBJECT
+
+  public:
+    AudioPropsGenerator(const ProgramInfo *pginfo);
+
+    void Start(void);
+    bool Run(void);
+
+  signals:
+    void audioPropsThreadDone(const ProgramInfo*);
+    void audioPropsReady(const ProgramInfo*);
+
+  protected:
+    virtual ~AudioPropsGenerator();
+    bool UpdateAudioProps(void);
+    void disconnectSafe(void);
+    void AttachSignals(QObject *);
+    static void *AudioPropsRun(void*);
+
+  protected:
+    QMutex             audioPropsLock;
+    pthread_t          audioPropsThread;
+    ProgramInfo        programInfo;
+};
+
+#endif //AUDIOPROPS_GENERATOR_H_
Index: libs/libmythtv/dummydecoder.h
===================================================================
--- libs/libmythtv/dummydecoder.h	(revision 22906)
+++ libs/libmythtv/dummydecoder.h	(working copy)
@@ -30,6 +30,8 @@
     virtual MythCodecID GetVideoCodecID(void) const { return kCodec_NONE; }
 
     virtual bool SyncPositionMap(void) { return false; }
+
+    virtual int GetAudioProperties(void) { return -1; }
 };
 
 #endif
Index: libs/libmyth/programinfo.h
===================================================================
--- libs/libmyth/programinfo.h	(revision 22906)
+++ libs/libmyth/programinfo.h	(working copy)
@@ -16,6 +16,7 @@
 #include "mythdbcon.h"
 
 MPUBLIC extern const char *kPreviewGeneratorInUseID;
+MPUBLIC extern const char *kAudioInspectorInUseID;
 
 typedef QHash<QString,QString> InfoMap;
 
@@ -365,6 +366,9 @@
     int GetHeight(void);
     void SetVidpropHeight(int width);
 
+    // Audio Set
+    void SaveAudioProps(int props);
+
     // In-use, autodeletion prevention stuff
     void MarkAsInUse(bool inuse, QString usedFor = "");
 
Index: libs/libmyth/programinfo.cpp
===================================================================
--- libs/libmyth/programinfo.cpp	(revision 22906)
+++ libs/libmyth/programinfo.cpp	(working copy)
@@ -33,6 +33,7 @@
 #define LOC_ERR QString("ProgramInfo, Error: ")
 
 const char *kPreviewGeneratorInUseID = "preview_generator";
+const char *kAudioInspectorInUseID = "audio_inspector";
 
 // works only for integer divisors of 60
 static const uint kUnknownProgramLength = 30;
@@ -2876,6 +2877,31 @@
     return m_videoWidth; 
 } 
 
+/** \fn ProgramInfo::SaveAudioProps(int props)
+ *  \brief Saves the audio properties to DB
+ */
+void ProgramInfo::SaveAudioProps(int props)
+{
+    // first set the props in the object
+    audioproperties = props;
+
+    // next write it to the DB
+    MSqlQuery query(MSqlQuery::InitCon());
+
+    VERBOSE(VB_AUDIO, QString("Setting Audio Props %1").arg(props));
+    query.prepare("UPDATE recordedprogram SET audioprop ="
+    " :PROP WHERE chanid = :CHANID AND starttime = :STARTTIME;");
+
+    query.bindValue(":PROP", props);
+    query.bindValue(":CHANID", chanid);
+    query.bindValue(":STARTTIME", startts);
+
+    if (!query.exec())
+        MythDB::DBError("UpdateRes", query);
+
+}
+
+
 /** \fn ProgramInfo::SetVidpropHeight(int width)
  *  \brief Sets overall average height flag in videoprops.
  */
