diff --git a/mythtv/libs/libmythtv/mythraopconnection.cpp b/mythtv/libs/libmythtv/mythraopconnection.cpp
index 66b97c7..5ad43b7 100644
--- a/mythtv/libs/libmythtv/mythraopconnection.cpp
+++ b/mythtv/libs/libmythtv/mythraopconnection.cpp
@@ -6,6 +6,8 @@
 #include <QUdpSocket>
 #include <QtEndian>
 
+#include <QFile>
+#include <QCryptographicHash>
 #include "mythlogging.h"
 #include "mythcorecontext.h"
 
@@ -14,21 +16,23 @@
 
 #include "mythraopdevice.h"
 #include "mythraopconnection.h"
+#include "mythdirs.h"
 
 #define LOC QString("RAOP Conn: ")
 #define MAX_PACKET_SIZE  2048
 #define DEFAULT_SAMPLE_RATE 44100
 
-RSA* MythRAOPConnection::g_rsa = NULL;
+RSA *MythRAOPConnection::g_rsa = NULL;
 
 MythRAOPConnection::MythRAOPConnection(QTcpSocket *socket, QByteArray id, int port)
-  : m_watchdogTimer(NULL), m_socket(socket), m_hardwareId(id), m_dataPort(port),
-    m_dataSocket(NULL), m_clientControlSocket(NULL), m_clientControlPort(0),
-    m_audio(NULL), m_codec(NULL), m_codeccontext(NULL),
-    m_sampleRate(DEFAULT_SAMPLE_RATE), m_allowVolumeControl(true),
-    m_seenPacket(false), m_lastPacketSequence(0), m_lastPacketTimestamp(0),
-    m_lastSyncTime(0), m_lastSyncTimestamp(0), m_lastLatency(0), m_latencyAudio(0),
-    m_latencyQueued(0), m_latencyCounter(0), m_avSync(0)
+    : m_watchdogTimer(NULL), m_socket(socket), m_hardwareId(id), m_dataPort(port),
+      m_dataSocket(NULL), m_clientControlSocket(NULL), m_clientControlPort(0),
+      m_audio(NULL), m_codec(NULL), m_codeccontext(NULL),
+      m_sampleRate(DEFAULT_SAMPLE_RATE), m_allowVolumeControl(true),
+      m_seenPacket(false), m_authed(false), m_nonce(""),
+      m_lastPacketSequence(0), m_lastPacketTimestamp(0),
+      m_lastSyncTime(0), m_lastSyncTimestamp(0), m_lastLatency(0), m_latencyAudio(0),
+      m_latencyQueued(0), m_latencyCounter(0), m_avSync(0)
 {
 }
 
@@ -37,6 +41,7 @@ MythRAOPConnection::~MythRAOPConnection()
     // stop and delete watchdog timer
     if (m_watchdogTimer)
         m_watchdogTimer->stop();
+
     delete m_watchdogTimer;
     m_watchdogTimer = NULL;
 
@@ -46,6 +51,7 @@ MythRAOPConnection::~MythRAOPConnection()
         m_socket->close();
         m_socket->deleteLater();
     }
+
     m_socket = NULL;
 
     // delete data socket
@@ -55,6 +61,7 @@ MythRAOPConnection::~MythRAOPConnection()
         m_dataSocket->close();
         m_dataSocket->deleteLater();
     }
+
     m_dataSocket = NULL;
 
     // client control socket
@@ -64,6 +71,7 @@ MythRAOPConnection::~MythRAOPConnection()
         m_clientControlSocket->close();
         m_clientControlSocket->deleteLater();
     }
+
     m_clientControlSocket = NULL;
 
     // close audio decoder
@@ -81,6 +89,7 @@ bool MythRAOPConnection::Init(void)
     // connect up the request socket
     m_textStream = new QTextStream(m_socket);
     m_textStream->setCodec("UTF-8");
+
     if (!connect(m_socket, SIGNAL(readyRead()), this, SLOT(readClient())))
     {
         LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to connect client socket signal.");
@@ -89,6 +98,7 @@ bool MythRAOPConnection::Init(void)
 
     // create the data socket
     m_dataSocket = new QUdpSocket();
+
     if (!connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(udpDataReady())))
     {
         LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to connect data socket signal.");
@@ -97,6 +107,7 @@ bool MythRAOPConnection::Init(void)
 
     // try a few ports in case the first is in use
     int baseport = m_dataPort;
+
     while (m_dataPort < baseport + RAOP_PORT_RANGE)
     {
         if (m_dataSocket->bind(gCoreContext->MythHostAddressAny(), m_dataPort))
@@ -105,6 +116,7 @@ bool MythRAOPConnection::Init(void)
                 QString("Bound to port %1 for incoming data").arg(m_dataPort));
             break;
         }
+
         m_dataPort++;
     }
 
@@ -131,7 +143,8 @@ bool MythRAOPConnection::Init(void)
 
 void MythRAOPConnection::udpDataReady()
 {
-    QUdpSocket *sender = (QUdpSocket*)this->sender();
+    QUdpSocket *sender = (QUdpSocket *)this->sender();
+
     if (!sender)
         return;
 
@@ -146,6 +159,7 @@ void MythRAOPConnection::udpDataReady()
 
     // read datagrams
     QByteArray buf;
+
     while (sender->state() == QAbstractSocket::BoundState &&
            sender->hasPendingDatagrams())
     {
@@ -153,7 +167,7 @@ void MythRAOPConnection::udpDataReady()
         QHostAddress peer;
         quint16 port;
 
-        sender->readDatagram(buf.data(), buf.size(),&peer, &port);
+        sender->readDatagram(buf.data(), buf.size(), &peer, &port);
 
         if (!m_audio || !m_codec || !m_codeccontext)
             continue;
@@ -168,7 +182,7 @@ void MythRAOPConnection::udpDataReady()
 
         int offset = type == 0x60 ? 0 : 4;
         uint16_t this_sequence  = ntohs(*(uint16_t *)(buf.data() + offset + 2));
-        uint64_t this_timestamp = FramesToMs(ntohl(*(uint64_t*)(buf.data() + offset + 4)));
+        uint64_t this_timestamp = FramesToMs(ntohl(*(uint64_t *)(buf.data() + offset + 4)));
         uint16_t expected_sequence = m_lastPacketSequence + 1; // should wrap ok
 
         // regular data packet
@@ -199,8 +213,9 @@ void MythRAOPConnection::udpDataReady()
         ExpireResendRequests(timenow);
 
         offset += 12;
-        char* data_in = buf.data() + offset;
+        char *data_in = buf.data() + offset;
         int len       = buf.size() - offset;
+
         if (len < 16)
             continue;
 
@@ -208,7 +223,7 @@ void MythRAOPConnection::udpDataReady()
         unsigned char iv[16];
         unsigned char decrypted_data[MAX_PACKET_SIZE];
         memcpy(iv, m_AESIV.data(), sizeof(iv));
-        AES_cbc_encrypt((const unsigned char*)data_in,
+        AES_cbc_encrypt((const unsigned char *)data_in,
                         decrypted_data, aeslen,
                         &m_aesKey, iv, AES_DECRYPT);
         memcpy(decrypted_data + aeslen, data_in + aeslen, len - aeslen);
@@ -218,9 +233,10 @@ void MythRAOPConnection::udpDataReady()
         tmp_pkt.data = decrypted_data;
         tmp_pkt.size = len;
         int decoded_data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
-        int16_t* samples = (int16_t *)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE * sizeof(int32_t));
+        int16_t *samples = (int16_t *)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE * sizeof(int32_t));
         int used = avcodec_decode_audio3(m_codeccontext, samples,
                                          &decoded_data_size, &tmp_pkt);
+
         if (used != len)
         {
             LOG(VB_GENERAL, LOG_WARNING, LOC +
@@ -256,8 +272,8 @@ void MythRAOPConnection::SendResendRequest(uint64_t timenow,
         return;
 
     int16_t missed = (got < expected) ?
-                (int16_t)(((int32_t)got + UINT16_MAX + 1) - expected) :
-                got - expected;
+                     (int16_t)(((int32_t)got + UINT16_MAX + 1) - expected) :
+                     got - expected;
 
     LOG(VB_GENERAL, LOG_INFO, LOC + QString("Missed %1 packet(s): expected %2 got %3")
         .arg(missed).arg(expected).arg(got));
@@ -288,10 +304,12 @@ void MythRAOPConnection::ExpireResendRequests(uint64_t timenow)
         return;
 
     uint64_t too_old = timenow - 250;
-    QMutableMapIterator<uint16_t,uint64_t> it(m_resends);
+    QMutableMapIterator<uint16_t, uint64_t> it(m_resends);
+
     while (it.hasNext())
     {
         it.next();
+
         if (it.value() < too_old)
         {
             LOG(VB_GENERAL, LOG_WARNING, LOC +
@@ -303,13 +321,14 @@ void MythRAOPConnection::ExpireResendRequests(uint64_t timenow)
 
 void MythRAOPConnection::ProcessSyncPacket(const QByteArray &buf, uint64_t timenow)
 {
-    m_lastSyncTimestamp = FramesToMs(ntohl(*(uint64_t*)(buf.data() + 4)));
-    uint64_t now   = FramesToMs(ntohl(*(uint64_t*)(buf.data() + 16)));
+    m_lastSyncTimestamp = FramesToMs(ntohl(*(uint64_t *)(buf.data() + 4)));
+    uint64_t now   = FramesToMs(ntohl(*(uint64_t *)(buf.data() + 16)));
     m_lastLatency  = now - m_lastSyncTimestamp;
     m_lastSyncTime = timenow;
     uint64_t averageaudio = 0;
     uint64_t averagequeue = 0;
     double   averageav    = 0;
+
     if (m_latencyCounter)
     {
         averageaudio = m_latencyAudio / m_latencyCounter;
@@ -326,23 +345,27 @@ void MythRAOPConnection::ProcessSyncPacket(const QByteArray &buf, uint64_t timen
             .arg(averageaudio).arg(averagequeue)
             .arg(averageaudio + averagequeue).arg(m_lastLatency));
     }
+
     m_latencyAudio = m_latencyQueued = m_latencyCounter = m_avSync = 0;
 }
 
 int MythRAOPConnection::ExpireAudio(uint64_t timestamp)
 {
     int res = 0;
-    QMutableMapIterator<uint64_t,int16_t*> it(m_audioQueue);
+    QMutableMapIterator<uint64_t, int16_t *> it(m_audioQueue);
+
     while (it.hasNext())
     {
         it.next();
+
         if (it.key() < timestamp)
         {
-            av_freep((void *)&(it.value()));
+            av_freep((void *) & (it.value()));
             m_audioQueue.remove(it.key());
             res++;
         }
     }
+
     return res;
 }
 
@@ -358,6 +381,7 @@ void MythRAOPConnection::ProcessAudio(uint64_t timenow)
 
     // expire anything that is late
     int dumped = ExpireAudio(updatedsync);
+
     if (dumped > 0)
     {
         LOG(VB_GENERAL, LOG_INFO, LOC + QString("Dumped %1 audio packets")
@@ -373,10 +397,12 @@ void MythRAOPConnection::ProcessAudio(uint64_t timenow)
     m_latencyQueued += queue_length;
     m_latencyCounter++;
 
-    QMapIterator<uint64_t,int16_t*> it(m_audioQueue);
+    QMapIterator<uint64_t, int16_t *> it(m_audioQueue);
+
     while (it.hasNext())
     {
         it.next();
+
         if (it.key() < ideal_ts)
             m_audio->AddData(it.value(), 1408 /* FIXME */, it.key(), 352);
     }
@@ -389,6 +415,7 @@ void MythRAOPConnection::ResetAudio(void)
     ExpireAudio(UINT64_MAX);
     m_latencyCounter = m_latencyAudio = m_latencyQueued = m_avSync = 0;
     m_seenPacket = false;
+
     if (m_audio)
         m_audio->Reset();
 }
@@ -402,10 +429,12 @@ void MythRAOPConnection::timeout(void)
 void MythRAOPConnection::readClient(void)
 {
     QTcpSocket *socket = (QTcpSocket *)sender();
+
     if (!socket)
         return;
 
     QList<QByteArray> lines;
+
     while (socket->canReadLine())
     {
         QByteArray line = socket->readLine();
@@ -417,6 +446,25 @@ void MythRAOPConnection::readClient(void)
         ProcessRequest(lines);
 }
 
+
+QString MythRAOPConnection::GenerateNonce(void)
+{
+    int nonceParts[4];
+    QString nonce;
+    QTime time = QTime::currentTime();
+    qsrand((uint)time.msec());
+    nonceParts[0] = qrand();
+    nonceParts[1] = qrand();
+    nonceParts[2] = qrand();
+    nonceParts[3] = qrand();
+
+
+    nonce =  QString::number(nonceParts[0], 16).toUpper();
+    nonce += QString::number(nonceParts[1], 16).toUpper();
+    nonce += QString::number(nonceParts[2], 16).toUpper();
+    nonce += QString::number(nonceParts[3], 16).toUpper();
+    return nonce;
+}
 void MythRAOPConnection::ProcessRequest(const QList<QByteArray> &lines)
 {
     if (lines.isEmpty())
@@ -432,23 +480,108 @@ void MythRAOPConnection::ProcessRequest(const QList<QByteArray> &lines)
 
     QByteArray option = lines[0].left(lines[0].indexOf(" "));
 
+    bool passwordAuthEnabled = gCoreContext->GetNumSettingOnHost(
+                                   "RAOPPasswordEnabled",
+                                   gCoreContext->GetHostName(),
+                                   0);
+
+    if (passwordAuthEnabled && !m_authed)
+    {
+
+        if (!tags.contains("Authorization"))
+        {
+            // 60 seconds to enter password.
+            m_watchdogTimer->start(60000);
+
+            if (option != "OPTIONS" && option != "ANNOUNCE"
+                && option != "TEARDOWN")
+            {
+                StartResponse(m_textStream);
+                FinishResponse(m_textStream, m_socket, option, tags["Cseq"]);
+                return;
+            }
+        }
+        else
+        {
+
+            if (m_nonce.isEmpty())
+            {
+                m_nonce = GenerateNonce();
+            }
+
+            QByteArray response = tags["Authorization"].data();
+            int authStart = response.indexOf("response=\"") + 10;
+            QByteArray auth = response.mid(authStart, 32);
+
+            int uriStart = response.indexOf("uri=\"") + 5;
+            int uriLength = response.indexOf("\"", uriStart) - uriStart;
+            QByteArray uri = response.mid(uriStart, uriLength);
+
+            QString password = gCoreContext->GetSettingOnHost("RAOPPassword", 
+                                                gCoreContext->GetHostName(), 
+                                                "");
+
+            QString ha1input = "iTunes:raop:" + password;
+            QString ha2input = option + ":" + uri;
+            QString HA1, HA2, final;
+            QByteArray hashResult;
+
+            m_watchdogTimer->start(10000);
+
+            hashResult = QCryptographicHash::hash(ha1input.toAscii(),
+                                                    QCryptographicHash::Md5);
+            HA1 = QString(hashResult.toHex()).toUpper();
+               
+            hashResult = QCryptographicHash::hash(ha2input.toAscii(),
+                                                    QCryptographicHash::Md5);
+            HA2 = QString(hashResult.toHex()).toUpper();
+
+            final = HA1 + ":" + m_nonce + ":" + HA2;
+            hashResult = QCryptographicHash::hash(final.toAscii(), 
+                                                    QCryptographicHash::Md5);
+            final = QString(hashResult.toHex()).toUpper();
+
+            if (final.toAscii().toHex() == auth.toHex())
+            {
+                m_authed = true;
+                LOG(VB_GENERAL, LOG_INFO, LOC + "RAOP client Authed");
+            }
+            else
+            {
+                if (option != "OPTIONS" && option != "ANNOUNCE"
+                    && option != "TEARDOWN")
+                {
+                    StartResponse(m_textStream);
+                    FinishResponse(m_textStream, m_socket, option, tags["Cseq"]);
+                    return;
+                }
+            }
+        }
+
+    }
+
     if (option == "OPTIONS")
     {
         StartResponse(m_textStream);
+
         if (tags.contains("Apple-Challenge"))
         {
             *m_textStream << "Apple-Response: ";
+
             if (!LoadKey())
                 return;
+
             int tosize = RSA_size(LoadKey());
             unsigned char to[tosize];
 
             QByteArray challenge = QByteArray::fromBase64(tags["Apple-Challenge"].data());
             int challenge_size = challenge.size();
+
             if (challenge_size != 16)
             {
                 LOG(VB_GENERAL, LOG_ERR, LOC +
                     QString("Decoded challenge size %1, expected 16").arg(challenge_size));
+
                 if (challenge_size > 16)
                     challenge_size = 16;
             }
@@ -457,6 +590,7 @@ void MythRAOPConnection::ProcessRequest(const QList<QByteArray> &lines)
             unsigned char from[38];
             memcpy(from, challenge.data(), challenge_size);
             i += challenge_size;
+
             if (m_socket->localAddress().protocol() == QAbstractSocket::IPv4Protocol)
             {
                 uint32_t ip = m_socket->localAddress().toIPv4Address();
@@ -472,10 +606,12 @@ void MythRAOPConnection::ProcessRequest(const QList<QByteArray> &lines)
                 memcpy(from + i, &ip, 16);
                 i += 16;
             }
+
             memcpy(from + i, m_hardwareId.data(), RAOP_HARDWARE_ID_SIZE);
             i += RAOP_HARDWARE_ID_SIZE;
 
             int pad = 32 - i;
+
             if (pad > 0)
             {
                 memset(from + i, 0, pad);
@@ -483,11 +619,11 @@ void MythRAOPConnection::ProcessRequest(const QList<QByteArray> &lines)
             }
 
             LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("Full base64 response: '%1' size %2")
-                .arg(QByteArray((const char*)from, i).toBase64().data()).arg(i));
+                .arg(QByteArray((const char *)from, i).toBase64().data()).arg(i));
 
             RSA_private_encrypt(i, from, to, LoadKey(), RSA_PKCS1_PADDING);
 
-            QByteArray base64 = QByteArray((const char*)to, tosize).toBase64();
+            QByteArray base64 = QByteArray((const char *)to, tosize).toBase64();
 
             for (int pos = base64.size() - 1; pos > 0; pos--)
             {
@@ -505,7 +641,7 @@ void MythRAOPConnection::ProcessRequest(const QList<QByteArray> &lines)
     }
     else if (option == "ANNOUNCE")
     {
-        foreach (QByteArray line, lines)
+        foreach(QByteArray line, lines)
         {
             if (line.startsWith("a=rsaaeskey:"))
             {
@@ -518,14 +654,15 @@ void MythRAOPConnection::ProcessRequest(const QList<QByteArray> &lines)
                 {
                     int size = sizeof(char) * RSA_size(LoadKey());
                     char *decryptedkey = new char[size];
+
                     if (RSA_private_decrypt(decodedkey.size(),
-                                            (const unsigned char*)decodedkey.data(),
-                                            (unsigned char*)decryptedkey,
+                                            (const unsigned char *)decodedkey.data(),
+                                            (unsigned char *)decryptedkey,
                                             LoadKey(), RSA_PKCS1_OAEP_PADDING))
                     {
                         LOG(VB_GENERAL, LOG_DEBUG, LOC +
                             "Successfully decrypted AES key from RSA.");
-                        AES_set_decrypt_key((const unsigned char*)decryptedkey,
+                        AES_set_decrypt_key((const unsigned char *)decryptedkey,
                                             128, &m_aesKey);
                     }
                     else
@@ -533,6 +670,7 @@ void MythRAOPConnection::ProcessRequest(const QList<QByteArray> &lines)
                         LOG(VB_GENERAL, LOG_WARNING, LOC +
                             "Failed to decrypt AES key from RSA.");
                     }
+
                     delete [] decryptedkey;
                 }
 
@@ -549,11 +687,11 @@ void MythRAOPConnection::ProcessRequest(const QList<QByteArray> &lines)
                 m_audioFormat.clear();
                 QByteArray format = line.mid(7).trimmed();
                 QList<QByteArray> fmts = format.split(' ');
-                foreach (QByteArray fmt, fmts)
-                    m_audioFormat.append(fmt.toInt());
+                foreach(QByteArray fmt, fmts)
+                m_audioFormat.append(fmt.toInt());
 
-                foreach (int fmt, m_audioFormat)
-                    LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("Audio parameter: %1").arg(fmt));
+                foreach(int fmt, m_audioFormat)
+                LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("Audio parameter: %1").arg(fmt));
             }
         }
 
@@ -568,7 +706,7 @@ void MythRAOPConnection::ProcessRequest(const QList<QByteArray> &lines)
             int timing_port = 0;
             QString data = tags["Transport"];
             QStringList items = data.split(";");
-            foreach (QString item, items)
+            foreach(QString item, items)
             {
                 if (item.startsWith("control_port"))
                     control_port = item.mid(item.indexOf("=") + 1).trimmed().toUInt();
@@ -578,11 +716,11 @@ void MythRAOPConnection::ProcessRequest(const QList<QByteArray> &lines)
 
             LOG(VB_GENERAL, LOG_INFO, LOC +
                 QString("Negotiated setup with client %1 on port %2")
-                    .arg(m_socket->peerAddress().toString())
-                    .arg(m_socket->peerPort()));
+                .arg(m_socket->peerAddress().toString())
+                .arg(m_socket->peerPort()));
             LOG(VB_GENERAL, LOG_DEBUG, LOC +
                 QString("control port: %1 timing port: %2")
-                    .arg(control_port).arg(timing_port));
+                .arg(control_port).arg(timing_port));
 
             StartResponse(m_textStream);
             *m_textStream << "Transport: " << tags["Transport"];
@@ -600,6 +738,7 @@ void MythRAOPConnection::ProcessRequest(const QList<QByteArray> &lines)
             }
 
             m_clientControlSocket = new QUdpSocket(this);
+
             if (!m_clientControlSocket->bind(control_port))
             {
                 LOG(VB_GENERAL, LOG_ERR, LOC +
@@ -627,14 +766,16 @@ void MythRAOPConnection::ProcessRequest(const QList<QByteArray> &lines)
     }
     else if (option == "SET_PARAMETER")
     {
-        foreach (QByteArray line, lines)
+        foreach(QByteArray line, lines)
         {
             if (line.startsWith("volume:") && m_allowVolumeControl && m_audio)
             {
                 QByteArray rawvol = line.mid(7).trimmed();
                 float volume = (rawvol.toFloat() + 30.0) / 0.3;
+
                 if (volume < 0.01)
                     volume = 0.0;
+
                 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Setting volume to %1 (raw %3)")
                     .arg(volume).arg(rawvol.data()));
                 m_audio->SetCurrentVolume((int)volume);
@@ -663,6 +804,25 @@ void MythRAOPConnection::StartResponse(QTextStream *stream)
 {
     if (!stream)
         return;
+
+    if (gCoreContext->GetNumSettingOnHost("RAOPPasswordEnabled",
+                                          gCoreContext->GetHostName(), 0))
+    {
+        if (!m_authed)
+        {
+
+            if (m_nonce.isEmpty())
+            {
+                m_nonce = GenerateNonce();
+            }
+
+            *stream << "RTSP/1.0 401 Unauthorised\r\n";
+            *stream << "WWW-Authenticate: Digest realm=\"raop\",";
+            *stream << " nonce=\"" + m_nonce + "\"\r\n";
+            return;
+        }
+    }
+
     *stream << "RTSP/1.0 200 OK\r\n";
 }
 
@@ -730,18 +874,21 @@ RSA* MythRAOPConnection::LoadKey(void)
 RawHash MythRAOPConnection::FindTags(const QList<QByteArray> &lines)
 {
     RawHash result;
+
     if (lines.isEmpty())
         return result;
 
     for (int i = 0; i < lines.size(); i++)
     {
         int index = lines[i].indexOf(":");
+
         if (index > 0)
         {
             result.insert(lines[i].left(index).trimmed(),
                           lines[i].mid(index + 1).trimmed());
         }
     }
+
     return result;
 }
 
@@ -755,6 +902,7 @@ bool MythRAOPConnection::CreateDecoder(void)
     avcodeclock->unlock();
 
     m_codec = avcodec_find_decoder(CODEC_ID_ALAC);
+
     if (!m_codec)
     {
         LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create ALAC decoder- going silent...");
@@ -762,10 +910,12 @@ bool MythRAOPConnection::CreateDecoder(void)
     }
 
     m_codeccontext = avcodec_alloc_context();
+
     if (m_codec && m_codeccontext)
     {
-        unsigned char* extradata = new unsigned char[36];
+        unsigned char *extradata = new unsigned char[36];
         memset(extradata, 0, 36);
+
         if (m_audioFormat.size() < 12)
         {
             LOG(VB_GENERAL, LOG_ERR, LOC + "Creating decoder but haven't seen audio format.");
@@ -783,15 +933,18 @@ bool MythRAOPConnection::CreateDecoder(void)
             extradata[19] = m_audioFormat[5]; // rice_initialhistory
             extradata[20] = m_audioFormat[6]; // rice_kmodifier
         }
+
         m_codeccontext->extradata = extradata;
         m_codeccontext->extradata_size = 36;
         m_codeccontext->channels = 2;
+
         if (avcodec_open(m_codeccontext, m_codec) < 0)
         {
             LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to open ALAC decoder - going silent...");
             DestroyDecoder();
             return false;
         }
+
         LOG(VB_GENERAL, LOG_DEBUG, LOC + "Opened ALAC decoder.");
     }
 
@@ -805,6 +958,7 @@ void MythRAOPConnection::DestroyDecoder(void)
         avcodec_close(m_codeccontext);
         av_free(m_codeccontext);
     }
+
     m_codec = NULL;
     m_codeccontext = NULL;
 }
@@ -814,16 +968,18 @@ bool MythRAOPConnection::OpenAudioDevice(void)
     CloseAudioDevice();
 
     m_sampleRate = m_audioFormat.size() >= 12 ? m_audioFormat[11] : DEFAULT_SAMPLE_RATE;
+
     if (m_sampleRate < 1)
         m_sampleRate = DEFAULT_SAMPLE_RATE;
 
     QString passthru = gCoreContext->GetNumSetting("PassThruDeviceOverride", false)
-                        ? gCoreContext->GetSetting("PassThruOutputDevice") : QString::null;
+                       ? gCoreContext->GetSetting("PassThruOutputDevice") : QString::null;
     QString device = gCoreContext->GetSetting("AudioOutputDevice");
 
     m_audio = AudioOutput::OpenAudio(device, passthru, FORMAT_S16, 2,
                                      0, m_sampleRate, AUDIOOUTPUT_MUSIC,
                                      m_allowVolumeControl, false);
+
     if (!m_audio)
     {
         LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to open audio device. Going silent...");
diff --git a/mythtv/libs/libmythtv/mythraopconnection.h b/mythtv/libs/libmythtv/mythraopconnection.h
index 8e34849..0c37047 100644
--- a/mythtv/libs/libmythtv/mythraopconnection.h
+++ b/mythtv/libs/libmythtv/mythraopconnection.h
@@ -47,6 +47,7 @@ class MythRAOPConnection : public QObject
     int     ExpireAudio(uint64_t timestamp);
     void    ProcessAudio(uint64_t timenow);
     void    ResetAudio(void);
+    QString GenerateNonce(void);
     void    ProcessRequest(const QList<QByteArray> &lines);
     void    StartResponse(QTextStream *stream);
     void    FinishResponse(QTextStream *stream, QTcpSocket *socket,
@@ -59,6 +60,7 @@ class MythRAOPConnection : public QObject
     void    CloseAudioDevice(void);
 
     QTimer         *m_watchdogTimer;
+
     // comms socket
     QTcpSocket     *m_socket;
     QTextStream    *m_textStream;
@@ -85,6 +87,8 @@ class MythRAOPConnection : public QObject
     bool            m_allowVolumeControl;
     // audio/packet sync
     bool            m_seenPacket;
+    bool            m_authed;
+    QString         m_nonce;
     int16_t         m_lastPacketSequence;
     uint64_t        m_lastPacketTimestamp;
     uint64_t        m_lastSyncTime;
diff --git a/mythtv/libs/libmythtv/mythraopdevice.cpp b/mythtv/libs/libmythtv/mythraopdevice.cpp
index 8bb5f6f..69212d4 100644
--- a/mythtv/libs/libmythtv/mythraopdevice.cpp
+++ b/mythtv/libs/libmythtv/mythraopdevice.cpp
@@ -10,9 +10,9 @@
 #include "mythraopconnection.h"
 #include "mythraopdevice.h"
 
-MythRAOPDevice* MythRAOPDevice::gMythRAOPDevice = NULL;
-MThread*        MythRAOPDevice::gMythRAOPDeviceThread = NULL;
-QMutex*         MythRAOPDevice::gMythRAOPDeviceMutex = new QMutex(QMutex::Recursive);
+MythRAOPDevice *MythRAOPDevice::gMythRAOPDevice = NULL;
+MThread        *MythRAOPDevice::gMythRAOPDeviceThread = NULL;
+QMutex         *MythRAOPDevice::gMythRAOPDeviceMutex = new QMutex(QMutex::Recursive);
 
 #define LOC QString("RAOP Device: ")
 
@@ -23,6 +23,7 @@ bool MythRAOPDevice::Create(void)
     // create the device thread
     if (!gMythRAOPDeviceThread)
         gMythRAOPDeviceThread = new MThread("RAOPDevice");
+
     if (!gMythRAOPDeviceThread)
     {
         LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create RAOP device thread.");
@@ -32,6 +33,7 @@ bool MythRAOPDevice::Create(void)
     // create the device object
     if (!gMythRAOPDevice)
         gMythRAOPDevice = new MythRAOPDevice();
+
     if (!gMythRAOPDevice)
     {
         LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create RAOP device object.");
@@ -60,11 +62,13 @@ void MythRAOPDevice::Cleanup(void)
         gMythRAOPDevice->Teardown();
 
     QMutexLocker locker(gMythRAOPDeviceMutex);
+
     if (gMythRAOPDeviceThread)
     {
         gMythRAOPDeviceThread->exit();
         gMythRAOPDeviceThread->wait();
     }
+
     delete gMythRAOPDeviceThread;
     gMythRAOPDeviceThread = NULL;
 
@@ -73,8 +77,8 @@ void MythRAOPDevice::Cleanup(void)
 }
 
 MythRAOPDevice::MythRAOPDevice()
-  : QTcpServer(), m_name(QString("MythTV")), m_bonjour(NULL), m_valid(false),
-    m_lock(new QMutex(QMutex::Recursive)), m_setupPort(5000)
+    : QTcpServer(), m_name(QString("MythTV")), m_bonjour(NULL), m_valid(false),
+      m_lock(new QMutex(QMutex::Recursive)), m_setupPort(5000)
 {
     for (int i = 0; i < RAOP_HARDWARE_ID_SIZE; i++)
         m_hardwareId.append((random() % 80) + 33);
@@ -100,7 +104,7 @@ void MythRAOPDevice::Teardown(void)
     m_bonjour = NULL;
 
     // disconnect clients
-    foreach (MythRAOPConnection* client, m_clients)
+    foreach(MythRAOPConnection * client, m_clients)
     {
         disconnect(client->GetSocket(), 0, 0, 0);
         delete client;
@@ -121,6 +125,7 @@ void MythRAOPDevice::Start(void)
 
     // start listening for connections (try a few ports in case the default is in use)
     int baseport = m_setupPort;
+
     while (m_setupPort < baseport + RAOP_PORT_RANGE)
     {
         if (listen(QHostAddress::Any, m_setupPort))
@@ -129,6 +134,7 @@ void MythRAOPDevice::Start(void)
                 QString("Listening for connections on port %1").arg(m_setupPort));
             break;
         }
+
         m_setupPort++;
     }
 
@@ -137,6 +143,7 @@ void MythRAOPDevice::Start(void)
 
     // announce service
     m_bonjour = new BonjourRegister(this);
+
     if (!m_bonjour)
     {
         LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Bonjour object.");
@@ -145,6 +152,7 @@ void MythRAOPDevice::Start(void)
 
     // give each frontend a unique name
     int multiple = m_setupPort - baseport;
+
     if (multiple > 0)
         m_name += QString::number(multiple);
 
@@ -164,7 +172,18 @@ void MythRAOPDevice::Start(void)
     txt.append(4); txt.append("ch=2");
     txt.append(5); txt.append("ss=16");
     txt.append(8); txt.append("sr=44100");
-    txt.append(8); txt.append("pw=false");
+
+    if (gCoreContext->GetNumSettingOnHost("RAOPPasswordEnabled", 
+					gCoreContext->GetHostName(), 
+					0))
+    {
+        txt.append(7); txt.append("pw=true");
+    }
+    else
+    {
+        txt.append(8); txt.append("pw=false");
+    }
+
     txt.append(4); txt.append("vn=3");
     txt.append(9); txt.append("txtvers=1");
 
@@ -186,10 +205,11 @@ void MythRAOPDevice::newConnection(void)
         .arg(client->peerAddress().toString()).arg(client->peerPort()));
 
     int port = 6000;
+
     while (port < (6000 + RAOP_PORT_RANGE))
     {
         bool found = false;
-        foreach (MythRAOPConnection* client, m_clients)
+        foreach(MythRAOPConnection * client, m_clients)
         {
             if (client->GetDataPort() == port)
             {
@@ -197,12 +217,14 @@ void MythRAOPDevice::newConnection(void)
                 port++;
             }
         }
+
         if (!found)
             break;
     }
 
     MythRAOPConnection *obj =
-            new MythRAOPConnection(client, m_hardwareId, port);
+        new MythRAOPConnection(client, m_hardwareId, port);
+
     if (obj->Init())
     {
         m_clients.append(obj);
@@ -220,6 +242,7 @@ void MythRAOPDevice::deleteClient(void)
 {
     QMutexLocker locker(m_lock);
     QList<MythRAOPConnection *>::iterator it;
+
     for (it = m_clients.begin(); it != m_clients.end(); ++it)
     {
         if ((*it)->GetSocket()->state() == QTcpSocket::UnconnectedState)
diff --git a/mythtv/programs/mythfrontend/globalsettings.cpp b/mythtv/programs/mythfrontend/globalsettings.cpp
index 7e6fad3..e864968 100644
--- a/mythtv/programs/mythfrontend/globalsettings.cpp
+++ b/mythtv/programs/mythfrontend/globalsettings.cpp
@@ -2680,6 +2680,29 @@ static HostLineEdit *UDPNotifyPort()
     return ge;
 }
 
+static HostCheckBox *RAOPPasswordEnabled()
+{
+    HostCheckBox *gc = new HostCheckBox("RAOPPasswordEnabled");
+    gc->setLabel(QObject::tr("Enable password protection for RAOP"));
+    gc->setHelpText(QObject::tr("This enables password protection for devices"
+                         "connecting via RAOP. (Requires mythfrontend restart)"
+                    ));
+    gc->setValue(false);
+    return gc;
+}
+
+static HostLineEdit *RAOPPassword()
+{
+    HostLineEdit *ge = new HostLineEdit("RAOPPassword");
+    ge->setLabel(QObject::tr("RAOP Access Password"));
+
+    ge->setValue("");
+    QString help = QObject::tr(
+        "Enter a password.");
+    ge->setHelpText(help);
+    return ge;
+}
+
 static HostCheckBox *RealtimePriority()
 {
     HostCheckBox *gc = new HostCheckBox("RealtimePriority");
@@ -3295,6 +3318,8 @@ MainGeneralSettings::MainGeneralSettings()
     remotecontrol->addChild(NetworkControlEnabled());
     remotecontrol->addChild(NetworkControlPort());
     remotecontrol->addChild(UDPNotifyPort());
+    remotecontrol->addChild(RAOPPasswordEnabled());
+    remotecontrol->addChild(RAOPPassword());
     addChild(remotecontrol);
 }
