Index: mythplugins/mythmusic/mythmusic/playbackbox.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/playbackbox.cpp	(revision 16268)
+++ mythplugins/mythmusic/mythmusic/playbackbox.cpp	(working copy)
@@ -1968,11 +1968,14 @@
             OutputEvent *aoe = (OutputEvent *) event;
 
             VERBOSE(VB_IMPORTANT, QString("%1 %2").arg(statusString)
-                .arg(*aoe->errorMessage()));
-            MythPopupBox::showOkPopup(gContext->GetMainWindow(), 
-                                      statusString,
-                                      QString("MythMusic has encountered the following error:\n%1")
-                                      .arg(*aoe->errorMessage()));
+                    .arg(aoe->GetErrorMessage()));
+
+            MythPopupBox::showOkPopup(
+                gContext->GetMainWindow(), 
+                statusString,
+                tr("MythMusic has encountered the following error") +
+                QString(":\n%1").arg(aoe->GetErrorMessage()));
+
             stopAll();
 
             break;
Index: mythplugins/mythmusic/mythmusic/musicplayer.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/musicplayer.cpp	(revision 16268)
+++ mythplugins/mythmusic/mythmusic/musicplayer.cpp	(working copy)
@@ -466,11 +466,14 @@
                 OutputEvent *aoe = (OutputEvent *) event;
 
                 VERBOSE(VB_IMPORTANT, QString("Output Error - %1")
-                        .arg(*aoe->errorMessage()));
-                MythPopupBox::showOkPopup(gContext->GetMainWindow(),
-                        "Output Error:",
-                        QString("MythMusic has encountered the following error:\n%1")
-                                .arg(*aoe->errorMessage()));
+                        .arg(aoe->GetErrorMessage()));
+
+                MythPopupBox::showOkPopup(
+                    gContext->GetMainWindow(),
+                    tr("Output Error") + ":",
+                    tr("MythMusic has encountered the following error") +
+                    QString(":\n%1").arg(aoe->GetErrorMessage()));
+
                 stop(true);
 
                 break;
Index: mythtv/libs/libmythtv/programinfo.cpp
===================================================================
--- mythtv/libs/libmythtv/programinfo.cpp	(revision 16268)
+++ mythtv/libs/libmythtv/programinfo.cpp	(working copy)
@@ -278,7 +278,7 @@
 #define LONGLONG_TO_LIST(x)  INT_TO_LIST((int)((x) >> 32))  \
                              INT_TO_LIST((int)((x) & 0xffffffffLL))
 
-#define STR_TO_LIST(x)       if ((x).isNull()) list << ""; else list << (x);
+#define STR_TO_LIST(x)       if ((x).isNull()) list << ""; else list << QDeepCopy<QString>(x);
 #define DATE_TO_LIST(x)      STR_TO_LIST((x).toString(Qt::ISODate))
 
 #define FLOAT_TO_LIST(x)     sprintf(tmp, "%f", (x)); list << tmp;
@@ -368,7 +368,7 @@
                                    VERBOSE(VB_IMPORTANT, listerror); \
                                    return false;      \
                                }                      \
-                               ts = *it++;            \
+                               ts = QDeepCopy<QString>(*it++); \
                                if (ts.isNull())       \
                                    ts = "";           
                                
Index: mythtv/libs/libmyth/output.h
===================================================================
--- mythtv/libs/libmyth/output.h	(revision 16268)
+++ mythtv/libs/libmyth/output.h	(working copy)
@@ -1,3 +1,4 @@
+// -*- Mode: c++ -*-
 // Copyright (c) 2000-2001 Brad Hughes <bhughes@trolltech.com>
 //
 // Use, modification and distribution is allowed without limitation,
@@ -10,9 +11,6 @@
 class OutputListeners;
 class OutputEvent;
 
-#include <qthread.h>
-#include <qevent.h>
-#include <qptrlist.h>
 #include "mythobservable.h"
 
 class QObject;
@@ -24,79 +22,81 @@
 
 class MPUBLIC OutputEvent : public MythEvent
 {
-public:
-    enum Type { Playing = (User + 200), Buffering, Info, Paused,
-		Stopped, Error };
+  public:
+    enum Type
+    {
+        Playing = MythOutputEventBegin,
+        Buffering,
+        Info,
+        Paused,
+        Stopped,
+        Error,
+    };
 
-    OutputEvent(Type t)
-	: MythEvent(t), error_msg(0), elasped_seconds(0), written_bytes(0),
-	  brate(0), freq(0), prec(0), chan(0)
+    OutputEvent(Type t) :
+	MythEvent(t), error_msg(QString::null),
+        elapsed_seconds(0), written_bytes(0),
+        brate(0), freq(0), prec(0), chan(0)
     { ; }
 
-    OutputEvent(long s, unsigned long w, int b, int f, int p, int c)
-	: MythEvent(Info), error_msg(0), elasped_seconds(s), written_bytes(w),
-	  brate(b), freq(f), prec(p), chan(c)
+    OutputEvent(long s, unsigned long w, int b, int f, int p, int c) :
+	MythEvent(Info), error_msg(QString::null), elapsed_seconds(s),
+        written_bytes(w), brate(b), freq(f), prec(p), chan(c)
     { ; }
 
-    OutputEvent(const QString &e)
-	: MythEvent(Error), elasped_seconds(0), written_bytes(0),
-	  brate(0), freq(0), prec(0), chan(0)
-    {
-        error_msg = new QString(e.utf8());
-    }
+    OutputEvent(const QString &e);
 
+    virtual MythEvent *clone(void) const { return new OutputEvent(*this); }
 
-    ~OutputEvent()
-    {
-        if (error_msg)
-            delete error_msg;
-    }
+    virtual ~OutputEvent() {}
 
-    const QString *errorMessage() const { return error_msg; }
+    QString GetErrorMessage(void)    const;
+    long elapsedSeconds(void)        const { return elapsed_seconds; }
+    unsigned long writtenBytes(void) const { return written_bytes;   }
+    int bitrate(void)                const { return brate; }
+    int frequency(void)              const { return freq;  }
+    int precision(void)              const { return prec;  }
+    int channels(void)               const { return chan;  }
 
-    const long &elapsedSeconds() const { return elasped_seconds; }
-    const unsigned long &writtenBytes() const { return written_bytes; }
-    const int &bitrate() const { return brate; }
-    const int &frequency() const { return freq; }
-    const int &precision() const { return prec; }
-    const int &channels() const { return chan; }
+  protected:
+    OutputEvent(const OutputEvent&);
+    OutputEvent(void);                            // prevent default ctor
+    OutputEvent &operator=(const OutputEvent &o); // prevent default copy ctor
 
-    virtual OutputEvent *clone() { return new OutputEvent(*this); };
-
-private:
-    QString *error_msg;
-
-    long elasped_seconds;
+  protected:
+    QString       error_msg;
+    long          elapsed_seconds;
     unsigned long written_bytes;
-    int brate, freq, prec, chan;
+    int           brate;
+    int           freq;
+    int           prec;
+    int           chan;
 };
 
 
 class MPUBLIC OutputListeners : public MythObservable
 {
-public:
-    OutputListeners();
-    virtual ~OutputListeners();
+  public:
+    OutputListeners() : m_bufsize(0) {}
+    virtual ~OutputListeners() {}
 
     void addVisual(MythTV::Visual *);
     void removeVisual(MythTV::Visual *);
-    
-    QMutex *mutex() { return &mtx; }
 
-    void setBufferSize(unsigned int sz) { bufsize = sz; }
-    unsigned int bufferSize() const { return bufsize; }
+    void setBufferSize(unsigned int sz) { m_bufsize = sz; }
+    unsigned int bufferSize(void) const { return m_bufsize; }
 
-protected:
+  protected:
     void error(const QString &e);
-    void dispatchVisual(uchar *b, unsigned long b_len, 
-                       unsigned long written, int chan, int prec);
-    void prepareVisuals();
+    void dispatchVisual(
+        uchar *buffer, unsigned long b_len,
+        unsigned long written, int chan, int prec);
+    void prepareVisuals(void);
 
-private:
-    QMutex mtx;
-    QPtrList<MythTV::Visual> visuals;
-    
-    unsigned int bufsize;
+  private:
+    typedef vector<MythTV::Visual*> VisualList;
+    VisualList   m_visuals;
+    unsigned int m_bufsize;
 };
 
 
Index: mythtv/libs/libmyth/mythcontext.cpp
===================================================================
--- mythtv/libs/libmyth/mythcontext.cpp	(revision 16268)
+++ mythtv/libs/libmyth/mythcontext.cpp	(working copy)
@@ -3991,7 +3991,7 @@
     return QDeepCopy<QString>(x11_display);
 }
 
-void MythContext::dispatch(MythEvent &event)
+void MythContext::dispatch(const MythEvent &event)
 {
     if (print_verbose_messages & VB_NETWORK)
         VERBOSE(VB_NETWORK, QString("MythEvent: %1").arg(event.Message()));
@@ -3999,7 +3999,7 @@
     MythObservable::dispatch(event);
 }
 
-void MythContext::dispatchNow(MythEvent &event)
+void MythContext::dispatchNow(const MythEvent &event)
 {
     if (print_verbose_messages & VB_NETWORK)
         VERBOSE(VB_NETWORK, QString("MythEvent: %1").arg(event.Message()));
Index: mythtv/libs/libmyth/mythcontext.h
===================================================================
--- mythtv/libs/libmyth/mythcontext.h	(revision 16268)
+++ mythtv/libs/libmyth/mythcontext.h	(working copy)
@@ -106,7 +106,7 @@
 
 /// Update this whenever the plug-in API changes.
 /// Including changes in the libmythtv class methods used by plug-ins.
-#define MYTH_BINARY_VERSION "0.21.20080224-1"
+#define MYTH_BINARY_VERSION "0.21.20080226-1"
 
 /** \brief Increment this whenever the MythTV network protocol changes.
  *
@@ -318,8 +318,8 @@
     QString removeCurrentLocation(void);
     QString getCurrentLocation(void);
 
-    void dispatch(MythEvent &event);
-    void dispatchNow(MythEvent &event);
+    void dispatch(const MythEvent &event);
+    void dispatchNow(const MythEvent &event);
 
     void sendPlaybackStart(void);
     void sendPlaybackEnd(void);
Index: mythtv/libs/libmyth/output.cpp
===================================================================
--- mythtv/libs/libmyth/output.cpp	(revision 16268)
+++ mythtv/libs/libmyth/output.cpp	(working copy)
@@ -1,70 +1,115 @@
-// Copyright (c) 2000-2001 Brad Hughes <bhughes@trolltech.com>
-//
-// Use, modification and distribution is allowed without limitation,
-// warranty, or liability of any kind.
-//
+// -*- Mode: c++ -*-
+/*
+ * Copyright (c) 2000-2001 Brad Hughes <bhughes@trolltech.com>
+ * Copyright (c) 2008 Daniel Kristjansson <danielk@cuymedia.net>
+ *
+ *   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
+ *   MERCHANTABILITY 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
+ */
 
+#include <algorithm> // for find
+using namespace std;
+
 #include <qobject.h>
 #include <qapplication.h>
+#include <qdeepcopy.h>
 
 #include "output.h"
 #include "visual.h"
 
-OutputListeners::OutputListeners()
+OutputEvent::OutputEvent(const OutputEvent &other) :
+    MythEvent(other), error_msg(QString::null),
+    elapsed_seconds(other.elapsed_seconds),
+    written_bytes(other.written_bytes),
+    brate(other.brate), freq(other.freq),
+    prec(other.prec), chan(other.chan)
 {
-    bufsize=0;
+    if (!other.error_msg.isNull())
+        error_msg = QDeepCopy<QString>(other.error_msg);
 }
 
+OutputEvent::OutputEvent(const QString &e) :
+    MythEvent(Error), error_msg(QString::null),
+    elapsed_seconds(0), written_bytes(0),
+    brate(0), freq(0), prec(0), chan(0)
+{
+    error_msg = QDeepCopy<QString>(QString(e.utf8()));
+}
 
-OutputListeners::~OutputListeners()
+QString OutputEvent::GetErrorMessage(void) const
 {
+    return QDeepCopy<QString>(error_msg);
 }
 
+void OutputListeners::error(const QString &e)
+{
+    QMutexLocker locker(&m_lock);
 
-void OutputListeners::error(const QString &e) {
-    QObject *object = firstListener();
-    while (object) {
-	QApplication::postEvent(object, new OutputEvent(e));
-	object = nextListener();
-    }
+    ListenerList::iterator it = m_listeners.begin();
+    for ( ; it != m_listeners.end(); ++it)
+        QApplication::postEvent(*it, new OutputEvent(e));
 }
 
-void OutputListeners::addVisual(MythTV::Visual *v)
+void OutputListeners::addVisual(MythTV::Visual *visual)
 {
-    if (visuals.find(v) == -1) {
-       visuals.append(v);
-    }
+    QMutexLocker locker(&m_lock);
+
+    VisualList::iterator it = 
+        find(m_visuals.begin(), m_visuals.end(), visual);
+
+    if (it == m_visuals.end())
+        m_visuals.push_back(visual);
 }
 
-void OutputListeners::removeVisual(MythTV::Visual *v)
+void OutputListeners::removeVisual(MythTV::Visual *visual)
 {
-    visuals.remove(v);
+    QMutexLocker locker(&m_lock);
+
+    VisualList::iterator it = 
+        find(m_visuals.begin(), m_visuals.end(), visual);
+
+    if (it != m_visuals.end())
+        m_visuals.erase(it);
 }
 
-void OutputListeners::dispatchVisual(uchar *buffer, unsigned long b_len,
-                        unsigned long written, int chan, int prec)
+void OutputListeners::dispatchVisual(
+    uchar *buffer, unsigned long b_len,
+    unsigned long written, int chan, int prec)
 {
-    if (! buffer)
-       return;
+    if (!buffer)
+        return;
 
-    MythTV::Visual *visual = visuals.first();
-    while (visual) {
-       visual->mutex()->lock();
-       visual->add(buffer, b_len, written, chan, prec);
-       visual->mutex()->unlock();
+    QMutexLocker locker(&m_lock);
 
-       visual = visuals.next();
+    VisualList::iterator it = m_visuals.begin();
+    for ( ; it != m_visuals.end(); ++it)
+    {
+       (*it)->mutex()->lock();
+       (*it)->add(buffer, b_len, written, chan, prec);
+       (*it)->mutex()->unlock();
     }
 }
 
-void OutputListeners::prepareVisuals()
+void OutputListeners::prepareVisuals(void)
 {
-    MythTV::Visual *visual = visuals.first();
-    while (visual) {
-       visual->mutex()->lock();
-       visual->prepare();
-       visual->mutex()->unlock();
+    QMutexLocker locker(&m_lock);
 
-       visual = visuals.next();
+    VisualList::iterator it = m_visuals.begin();
+    for ( ; it != m_visuals.end(); ++it)
+    {
+       (*it)->mutex()->lock();
+       (*it)->prepare();
+       (*it)->mutex()->unlock();
     }
 }
Index: mythtv/libs/libmyth/mythobservable.cpp
===================================================================
--- mythtv/libs/libmyth/mythobservable.cpp	(revision 16268)
+++ mythtv/libs/libmyth/mythobservable.cpp	(working copy)
@@ -1,8 +1,31 @@
+// -*- Mode: c++ -*-
+/*
+ * Copyright (c) 2008 Daniel Kristjansson <danielk@cuymedia.net>
+ *
+ *   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
+ *   MERCHANTABILITY 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
+ */
+
+#include <algorithm> // for find
+using namespace std;
+
 #include <qobject.h>
 #include <qapplication.h>
+
 #include "mythobservable.h"
 
-MythObservable::MythObservable()
+MythObservable::MythObservable() : m_lock(true)
 {
 }
 
@@ -12,50 +35,46 @@
 
 void MythObservable::addListener(QObject *listener)
 {
-    if (m_listeners.find(listener) == -1)
-        m_listeners.append(listener);
+    QMutexLocker locker(&m_lock);
+
+    ListenerList::iterator it = 
+        find(m_listeners.begin(), m_listeners.end(), listener);
+
+    if (it == m_listeners.end())
+        m_listeners.push_back(listener);
 }
 
 void MythObservable::removeListener(QObject *listener)
 {
-    if (m_listeners.find(listener) != -1)
-        m_listeners.remove(listener);
-}
+    QMutexLocker locker(&m_lock);
 
-QObject* MythObservable::firstListener()
-{
-    return m_listeners.first();
+    ListenerList::iterator it = 
+        find(m_listeners.begin(), m_listeners.end(), listener);
+
+    if (it != m_listeners.end())
+        m_listeners.erase(it);
 }
 
-QObject* MythObservable::nextListener()
+void MythObservable::dispatch(const MythEvent &event)
 {
-    return m_listeners.next();
-}
+    QMutexLocker locker(&m_lock);
 
-QPtrList<QObject> MythObservable::getListeners()
-{
-    return m_listeners;
+    ListenerList::iterator it = m_listeners.begin();
+    for ( ; it != m_listeners.end(); ++it)
+        QApplication::postEvent(*it, event.clone());
 }
 
-void MythObservable::dispatch(MythEvent &event)
+void MythObservable::dispatchNow(const MythEvent &event)
 {
-    QObject *listener = firstListener();
-    while (listener)
-    {
-        QApplication::postEvent(listener, event.clone());
-        listener = nextListener();
-    }
-}
+    QMutexLocker locker(&m_lock);
 
-void MythObservable::dispatchNow(MythEvent &event)
-{
-    QObject *listener = firstListener();
-    while (listener)
+    ListenerList::iterator it = m_listeners.begin();
+    for ( ; it != m_listeners.end(); ++it)
     {
         // Note: unlike postEvent, send event does not take
         // ownership of pointer and will not delete it.
-        QApplication::sendEvent(listener, &event);
-        listener = nextListener();
+        MythEvent *tmp = event.clone();
+        QApplication::sendEvent(*it, tmp);
+        delete tmp;
     }
 }
-
Index: mythtv/libs/libmyth/mythevent.h
===================================================================
--- mythtv/libs/libmyth/mythevent.h	(revision 16268)
+++ mythtv/libs/libmyth/mythevent.h	(working copy)
@@ -1,3 +1,4 @@
+// -*- Mode: c++ -*-
 #ifndef MYTHEVENT_H_
 #define MYTHEVENT_H_
 
@@ -16,23 +17,38 @@
 class MPUBLIC MythEvent : public QCustomEvent
 {
   public:
-    enum Type { MythEventMessage = (User + 1000) };
+    enum Type
+    {
+        MythEventBegin       = (User + 200),
+        MythEventMessage     = MythEventBegin,
+        MythEventEnd         = (User + 299),
+        MythOutputEventBegin = (User + 300),
+        // defined in output.h
+        MythOutputEventEnd   = (User + 399),
+    };
 
     MythEvent(int t);
     MythEvent(const QString &lmessage);
     MythEvent(const QString &lmessage, const QStringList &lextradata);
+    virtual MythEvent *clone(void) const { return new MythEvent(*this); }
     
     virtual ~MythEvent();
 
-    const QString& Message() const { return message; }
-    const QString& ExtraData(int idx = 0) const;
-    const QStringList& ExtraDataList() const { return extradata; } 
-    int ExtraDataCount() const { return extradata.size(); }
+    QString Message(void) const;
+    QString ExtraData(int idx = 0) const;
+    QStringList ExtraDataList(void) const;
+    unsigned int ExtraDataCount(void) const;
 
-    virtual MythEvent* clone() { return new MythEvent(message, extradata); }
+    /// Note: do not assign the strings from this except with QDeepCopy
+    const QStringList &ExtraDataListUnsafe(void) const;
 
-  private:
-    QString message;
+  protected:
+    MythEvent(const MythEvent &other);
+    MythEvent(void);                          // prevent default ctor
+    MythEvent &operator=(const MythEvent &o); // prevent default copy ctor
+
+  protected:
+    QString     message;
     QStringList extradata;
 };
 
Index: mythtv/libs/libmyth/mythevent.cpp
===================================================================
--- mythtv/libs/libmyth/mythevent.cpp	(revision 16268)
+++ mythtv/libs/libmyth/mythevent.cpp	(working copy)
@@ -1,8 +1,32 @@
 // -*- Mode: c++ -*-
+/*
+ * Copyright (c) 2008 Daniel Kristjansson <danielk@cuymedia.net>
+ *
+ *   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
+ *   MERCHANTABILITY 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
+ */
 
 #include "mythevent.h"
 #include <qdeepcopy.h>
 
+MythEvent::MythEvent(const MythEvent &other) :
+    QCustomEvent(MythEventMessage)
+{
+    message   = QDeepCopy<QString>(other.message);
+    extradata = QDeepCopy<QStringList>(other.extradata);
+}
+
 MythEvent::MythEvent(int t) :
     QCustomEvent(t), message(QString::null), extradata("empty")
 {
@@ -26,9 +50,29 @@
 {
 }
 
-const QString &MythEvent::ExtraData(int idx) const
+QString MythEvent::Message(void) const
 {
+    return QDeepCopy<QString>(message);
+}
+
+QString MythEvent::ExtraData(int idx) const
+{
     if (((uint)idx) < extradata.size())
-        return extradata[idx];
+        return QDeepCopy<QString>(extradata[idx]);
     return QString::null;
 } 
+
+QStringList MythEvent::ExtraDataList(void) const
+{
+    return QDeepCopy<QStringList>(extradata);
+}
+
+const QStringList &MythEvent::ExtraDataListUnsafe(void) const
+{
+    return extradata;
+}
+
+unsigned int MythEvent::ExtraDataCount(void) const
+{
+    return extradata.size();
+}
Index: mythtv/libs/libmyth/mythobservable.h
===================================================================
--- mythtv/libs/libmyth/mythobservable.h	(revision 16268)
+++ mythtv/libs/libmyth/mythobservable.h	(working copy)
@@ -1,7 +1,14 @@
 #ifndef MYTHOBSERVABLE_H_
 #define MYTHOBSERVABLE_H_
 
-#include <qptrlist.h>
+// C++ headers
+#include <vector>
+using namespace std;
+
+// Qt headers
+#include <qmutex.h>
+
+// MythTV headers
 #include "mythexp.h"
 #include "mythevent.h"
 
@@ -14,19 +21,6 @@
     listeners and iterating across them. It is typically used to post
     events to listening QObjects.
 
-       For example, to post a custom event with event id 100 to all listeners :
-
-       \code
-       void dispatch()
-       {
-           QObject *listener = firstListener();
-               while (listener) {
-                   QApplication::postEvent (listener, new QCustomEvent(100));
-               listener = nextListener();  
-           }
-       }
-       \endcode
-
     MythEvents can be dispatched to all listeners by calling dispatch
     or dispatchNow. The former is much preferred as it uses
     QApplication::postEvent() while the latter uses the blocking
@@ -61,57 +55,6 @@
     */
     void removeListener(QObject *listener);
 
-    /** \brief Begin iteration across listeners
-
-        If you simply need to iterate across the listeners, use \p
-        firstListener and \p nextListener to iterate across the
-        listeners. Ie. instead of 
-
-        \code
-        {
-            QPtrList<QObject> listeners = getListeners();
-            QObject *listener = listeners.first();
-            while (listener) {
-                // use listener...
-                listener = listeners.next();
-            }
-        }
-        \endcode
-
-        you can avoid the copy and just do
-
-        \code
-        {
-            QObject *listener = firstListener();
-            while (listener) {
-                // use listener...
-                listener = nextListener();
-            }
-        } 
-        \endcode
-
-        \returns pointer to the first listener, NULL if there are no listeners
-    */
-    QObject* firstListener();
-
-    /** \brief Continue iteration to the next listener
-
-        See firstListener. Returns NULL if there are no more listeners.
-
-        \returns pointer to the next listener, NULL if there are no more listeners
-    */
-    QObject* nextListener();
-
-    /** \brief Get a copy of the list of listener
-
-        If you need access to more than just iteration via
-        firstListener/nextListerner, you can call this to obtain a
-        QPtrList with all the listeners.
-
-        \returns a copy of the list of listener
-    */
-    QPtrList<QObject> getListeners(void);
-
     /** \brief Dispatch an event to all listeners 
                        
         Makes a copy of the event on the heap by calling
@@ -120,7 +63,7 @@
                
         \param event a MythEvent to dispatch.
     */
-    void dispatch(MythEvent &event);
+    void dispatch(const MythEvent &event);
 
     /** \brief Dispatch an event to all listeners 
                        
@@ -131,10 +74,13 @@
 
         \param event a MythEvent to dispatch.
     */
-    void dispatchNow(MythEvent &event);
+    void dispatchNow(const MythEvent &event);
 
-  private:
-    QPtrList<QObject> m_listeners;
+  protected:
+    typedef vector<QObject*> ListenerList;
+
+    mutable QMutex   m_lock;
+    ListenerList     m_listeners;
 };
 
 #endif /* MYTHOBSERVABLE_H */
