diff --git a/mythtv/libs/libmythui/libmythui.pro b/mythtv/libs/libmythui/libmythui.pro
index 0f0a49b..64c68bb 100644
--- a/mythtv/libs/libmythui/libmythui.pro
+++ b/mythtv/libs/libmythui/libmythui.pro
@@ -31,6 +31,7 @@ HEADERS += mythvirtualkeyboard.h mythuishape.h mythuiguidegrid.h
 HEADERS += mythrender_base.h mythfontmanager.h mythuieditbar.h
 HEADERS += mythdisplay.h mythuivideo.h mythudplistener.h
 HEADERS += mythuiexp.h mythuisimpletext.h mythuistatetracker.h
+HEADERS += mythanimation.h
 
 SOURCES  = mythmainwindow.cpp mythpainter.cpp mythimage.cpp mythrect.cpp
 SOURCES += myththemebase.cpp  mythpainter_qimage.cpp mythpainter_yuva.cpp
@@ -49,6 +50,7 @@ SOURCES += mythvirtualkeyboard.cpp mythuishape.cpp mythuiguidegrid.cpp
 SOURCES += mythfontmanager.cpp mythuieditbar.cpp
 SOURCES += mythdisplay.cpp mythuivideo.cpp mythudplistener.cpp
 SOURCES += mythuisimpletext.cpp mythuistatetracker.cpp
+SOURCES += mythanimation.cpp
 
 
 inc.path = $${PREFIX}/include/mythtv/libmythui/
@@ -67,6 +69,7 @@ inc.files += mythvirtualkeyboard.h mythuishape.h mythuiguidegrid.h
 inc.files += mythuieditbar.h mythuifilebrowser.h mythuivideo.h
 inc.files += mythuiexp.h mythuisimpletext.h mythuiactions.h
 inc.files += mythuistatetracker.h
+inc.files += mythanimation.h
 
 INSTALLS += inc
 
diff --git a/mythtv/libs/libmythui/mythanimation.cpp b/mythtv/libs/libmythui/mythanimation.cpp
new file mode 100644
index 0000000..6e56050
--- /dev/null
+++ b/mythtv/libs/libmythui/mythanimation.cpp
@@ -0,0 +1,253 @@
+#include "mythanimation.h"
+#include "mythuitype.h"
+#include "mythmainwindow.h"
+
+#include <QDomDocument>
+
+MythAnimation::MythAnimation(MythUIType* parent, Type type)
+    : m_parent(parent), m_type(type), m_when(AboutToShow),
+      m_active(false), m_looped(false), m_reversible(false)
+{
+}
+
+void MythAnimation::Activate(void)
+{
+    m_active = true;
+    setCurrentTime(0);
+}
+
+MythAnimation::When MythAnimation::GetWhen(void) const
+{
+    return m_when;
+}
+
+void MythAnimation::updateCurrentValue(const QVariant& value)
+{
+    if (!m_active)
+        return;
+
+    m_value = value;
+    if (m_parent)
+    {
+        if (Position == m_type)
+            m_parent->SetPosition(m_value.toPoint());
+        else if (Alpha == m_type)
+            m_parent->SetAlpha(m_value.toInt());
+        else if (Size == m_type)
+            m_parent->SetSize(m_value.toSize());
+        else if (Zoom == m_type)
+            m_parent->SetZoom(m_value.toFloat());
+        else if (Angle == m_type)
+            m_parent->SetAngle(m_value.toFloat());
+    }
+}
+
+void MythAnimation::CopyFrom(const MythAnimation* animation)
+{
+    m_type = animation->m_type;
+    m_value = animation->m_value;
+    m_when = animation->m_when;
+    m_looped = animation->m_looped;
+    m_reversible = animation->m_reversible;
+
+    setStartValue(animation->startValue());
+    setEndValue(animation->endValue());
+    setEasingCurve(animation->easingCurve());
+    setDuration(animation->duration());
+    if (m_looped)
+        setLoopCount(-1);
+}
+
+void MythAnimation::incrementCurrentTime(void)
+{
+    if (!m_active)
+        return;
+
+    int time = currentTime();
+    if (direction() == Forward)
+        time += GetMythMainWindow()->GetDrawInterval();
+    else
+        time -= GetMythMainWindow()->GetDrawInterval();
+
+    setCurrentTime(time);
+
+    if (endValue() == currentValue())
+    {
+        if (direction() == Forward)
+        {
+            if (m_reversible)
+                setDirection(Backward);
+            else if (!m_looped)
+                m_active = false;
+        }
+    }
+    else if (startValue() == currentValue())
+    {
+        if (direction() == Backward)
+        {
+            if (m_reversible)
+                setDirection(Forward);
+            else if (!m_looped)
+                m_active = false;
+        }
+    }
+}
+
+void MythAnimation::setEasingCurve(const QString& curve)
+{
+    if (curve == "Linear") setEasingCurve(QEasingCurve::Linear);
+    else if (curve == "InQuad") setEasingCurve(QEasingCurve::InQuad);
+    else if (curve == "OutQuad") setEasingCurve(QEasingCurve::OutQuad);
+    else if (curve == "InOutQuad") setEasingCurve(QEasingCurve::InOutQuad);
+    else if (curve == "OutInQuad") setEasingCurve(QEasingCurve::OutInQuad);
+    else if (curve == "InCubic") setEasingCurve(QEasingCurve::InCubic);
+    else if (curve == "OutCubic") setEasingCurve(QEasingCurve::OutCubic);
+    else if (curve == "InOutCubic") setEasingCurve(QEasingCurve::InOutCubic);
+    else if (curve == "OutInCubic") setEasingCurve(QEasingCurve::OutInCubic);
+    else if (curve == "InQuart") setEasingCurve(QEasingCurve::InQuart);
+    else if (curve == "OutQuart") setEasingCurve(QEasingCurve::OutQuart);
+    else if (curve == "InOutQuart") setEasingCurve(QEasingCurve::InOutQuart);
+    else if (curve == "OutInQuart") setEasingCurve(QEasingCurve::OutInQuart);
+    else if (curve == "InQuint") setEasingCurve(QEasingCurve::InQuint);
+    else if (curve == "OutQuint") setEasingCurve(QEasingCurve::OutQuint);
+    else if (curve == "InOutQuint") setEasingCurve(QEasingCurve::InOutQuint);
+    else if (curve == "OutInQuint") setEasingCurve(QEasingCurve::OutInQuint);
+    else if (curve == "InSine") setEasingCurve(QEasingCurve::InSine);
+    else if (curve == "OutSine") setEasingCurve(QEasingCurve::OutSine);
+    else if (curve == "InOutSine") setEasingCurve(QEasingCurve::InOutSine);
+    else if (curve == "OutInSine") setEasingCurve(QEasingCurve::OutInSine);
+    else if (curve == "InExpo") setEasingCurve(QEasingCurve::InExpo);
+    else if (curve == "OutExpo") setEasingCurve(QEasingCurve::OutExpo);
+    else if (curve == "InOutExpo") setEasingCurve(QEasingCurve::InOutExpo);
+    else if (curve == "OutInExpo") setEasingCurve(QEasingCurve::OutInExpo);
+    else if (curve == "InCirc") setEasingCurve(QEasingCurve::InCirc);
+    else if (curve == "OutCirc") setEasingCurve(QEasingCurve::OutCirc);
+    else if (curve == "InOutCirc") setEasingCurve(QEasingCurve::InOutCirc);
+    else if (curve == "OutInCirc") setEasingCurve(QEasingCurve::OutInCirc);
+    else if (curve == "InElastic") setEasingCurve(QEasingCurve::InElastic);
+    else if (curve == "OutElastic") setEasingCurve(QEasingCurve::OutElastic);
+    else if (curve == "InOutElastic") setEasingCurve(QEasingCurve::InOutElastic);
+    else if (curve == "OutInElastic") setEasingCurve(QEasingCurve::OutInElastic);
+    else if (curve == "InOutBack") setEasingCurve(QEasingCurve::InOutBack);
+    else if (curve == "OutInBack") setEasingCurve(QEasingCurve::OutInBack);
+    else if (curve == "InBounce") setEasingCurve(QEasingCurve::InBounce);
+    else if (curve == "OutBounce") setEasingCurve(QEasingCurve::OutBounce);
+    else if (curve == "InOutBounce") setEasingCurve(QEasingCurve::InOutBounce);
+    else if (curve == "OutInBounce") setEasingCurve(QEasingCurve::OutInBounce);
+    else if (curve == "InCurve") setEasingCurve(QEasingCurve::InCurve);
+    else if (curve == "OutCurve") setEasingCurve(QEasingCurve::OutCurve);
+    else if (curve == "SineCurve") setEasingCurve(QEasingCurve::SineCurve);
+    else if (curve == "CosineCurve") setEasingCurve(QEasingCurve::CosineCurve);
+}
+
+void MythAnimation::setEasingCurve(QEasingCurve curve)
+{
+    QVariantAnimation::setEasingCurve(curve);
+}
+
+bool MythAnimation::ParseElement(const QDomElement& element)
+{
+    bool result = true;
+    QVariant startValue;
+    QVariant endValue;
+
+    QString when = element.attribute("when", "AboutToShow");
+    if (when == "AboutToShow")
+        m_when = AboutToShow;
+    else if (when == "AboutToHide")
+        m_when = AboutToHide;
+
+    m_looped = parseBool(element.attribute("looped", "false"));
+    m_reversible = parseBool(element.attribute("reversible", "false"));
+
+    if (element.attribute("type", "") == "alpha")
+    {
+        parseAlpha(element, startValue, endValue);
+    }
+    else if (element.attribute("type", "") == "position")
+    {
+        parsePosition(element, startValue, endValue);
+    }
+    else if (element.attribute("type", "") == "size")
+    {
+        parseSize(element, startValue, endValue);
+    }
+    else if (element.attribute("type", "") == "zoom")
+    {
+        parseZoom(element, startValue, endValue);
+    }
+    else if (element.attribute("type", "") == "angle")
+    {
+        parseAngle(element, startValue, endValue);
+    }
+    else
+        result = false;
+
+    if (result)
+    {
+        setStartValue(startValue);
+        setEndValue(endValue);
+        setDuration(element.attribute("duration", "500").toInt());
+        setEasingCurve(element.attribute("easingcurve"));
+        if (m_looped)
+            setLoopCount(-1);
+    }
+
+    return result;
+}
+
+void MythAnimation::parseAlpha(const QDomElement& element, QVariant& startValue, QVariant& endValue)
+{
+    m_type = Alpha;
+    startValue = element.attribute("start", "0").toInt();
+    endValue = element.attribute("end", "0").toInt();
+}
+
+void MythAnimation::parsePosition(const QDomElement& element, QVariant& startValue, QVariant& endValue)
+{
+    m_type = Position;
+
+    MythPoint start = parsePoint(element.attribute("start", "0,0"), false);
+    MythPoint startN = parsePoint(element.attribute("start", "0,0"));
+    MythPoint end = parsePoint(element.attribute("end", "0,0"), false);
+    MythPoint endN = parsePoint(element.attribute("end", "0,0"));
+
+    if (start.x() == -1)
+        startN.setX(m_parent->GetArea().x());
+
+    if (start.y() == -1)
+        startN.setY(m_parent->GetArea().y());
+
+    if (end.x() == -1)
+        endN.setX(m_parent->GetArea().x());
+
+    if (end.y() == -1)
+        endN.setY(m_parent->GetArea().y());
+
+    startN.CalculatePoint(m_parent->GetArea());
+    endN.CalculatePoint(m_parent->GetArea());
+
+    startValue = startN.toQPoint();
+    endValue = endN.toQPoint();
+}
+
+void MythAnimation::parseSize(const QDomElement& element, QVariant& startValue, QVariant& endValue)
+{
+    m_type = Size;
+    startValue = XMLParseBase::parseSize(element.attribute("start", "0,0"));
+    endValue = XMLParseBase::parseSize(element.attribute("end", "0,0"));
+}
+
+void MythAnimation::parseZoom(const QDomElement& element, QVariant& startValue, QVariant& endValue)
+{
+    m_type = Zoom;
+    startValue = element.attribute("start", "0").toFloat();
+    endValue = element.attribute("end", "0").toFloat();
+}
+
+void MythAnimation::parseAngle(const QDomElement& element, QVariant& startValue, QVariant& endValue)
+{
+    m_type = Angle;
+    startValue = element.attribute("start", "0").toFloat();
+    endValue = element.attribute("end", "0").toFloat();
+}
diff --git a/mythtv/libs/libmythui/mythanimation.h b/mythtv/libs/libmythui/mythanimation.h
new file mode 100644
index 0000000..a6040cb
--- /dev/null
+++ b/mythtv/libs/libmythui/mythanimation.h
@@ -0,0 +1,55 @@
+#ifndef MYTHANIMATION_H_
+#define MYTHANIMATION_H_
+
+#include "xmlparsebase.h"
+#include <QVariantAnimation>
+
+class MythUIType;
+
+struct Effects
+{
+    int alpha;
+    float zoom;
+    float angle;
+    Effects(int alpha_ = 255, float zoom_ = 1.0, float angle_ = 0.0) : alpha(alpha_), zoom(zoom_), angle(angle_) {}
+};
+
+class MythAnimation : public QVariantAnimation, XMLParseBase
+{
+  public:
+    enum Type {Alpha, Position, Size, Zoom, Angle};
+    enum When {AboutToHide, AboutToShow};
+
+    MythAnimation(MythUIType* parent = NULL, Type type = Position);
+
+    void Activate(void);
+    void CopyFrom(const MythAnimation* animation);
+    bool ParseElement(const QDomElement& element);
+    When GetWhen(void) const;
+
+    QVariant value() const { return m_value; }
+
+    void updateCurrentValue(const QVariant& value);
+
+    void incrementCurrentTime(void);
+
+    void setEasingCurve(const QString& curve);
+    void setEasingCurve(QEasingCurve curve);
+
+  private:
+    void parseAlpha(const QDomElement& element, QVariant& startValue, QVariant& endValue);
+    void parsePosition(const QDomElement& element, QVariant& startValue, QVariant& endValue);
+    void parseSize(const QDomElement& element, QVariant& startValue, QVariant& endValue);
+    void parseZoom(const QDomElement& element, QVariant& startValue, QVariant& endValue);
+    void parseAngle(const QDomElement& element, QVariant& startValue, QVariant& endValue);
+
+    MythUIType* m_parent;
+    Type m_type;
+    When m_when;
+    QVariant m_value;
+    bool m_active;
+    bool m_looped;
+    bool m_reversible;
+};
+
+#endif
diff --git a/mythtv/libs/libmythui/mythmainwindow.cpp b/mythtv/libs/libmythui/mythmainwindow.cpp
index a01931f..884f892 100644
--- a/mythtv/libs/libmythui/mythmainwindow.cpp
+++ b/mythtv/libs/libmythui/mythmainwindow.cpp
@@ -158,6 +158,7 @@ class MythMainWindowPrivate
 
         sysEventHandler(NULL),
 
+        drawInterval(1000 / 70),
         drawTimer(NULL),
         mainStack(NULL),
 
@@ -235,6 +236,7 @@ class MythMainWindowPrivate
 
     QObject *sysEventHandler;
 
+    int drawInterval;
     MythSignalingTimer *drawTimer;
     QVector<MythScreenStack *> stackList;
     MythScreenStack *mainStack;
@@ -479,7 +481,7 @@ MythMainWindow::MythMainWindow(const bool useDB)
     connect(d->hideMouseTimer, SIGNAL(timeout()), SLOT(HideMouseTimeout()));
 
     d->drawTimer = new MythSignalingTimer(this, SLOT(animate()));
-    d->drawTimer->start(1000 / 70);
+    d->drawTimer->start(d->drawInterval);
 
     d->AllowInput = true;
 
@@ -2456,6 +2458,11 @@ void MythMainWindow::SetUIScreenRect(QRect &rect)
     d->uiScreenRect = rect;
 }
 
+int MythMainWindow::GetDrawInterval() const
+{
+    return d->drawInterval;
+}
+
 void MythMainWindow::StartLIRC(void)
 {
 #ifdef USE_LIRC
diff --git a/mythtv/libs/libmythui/mythmainwindow.h b/mythtv/libs/libmythui/mythmainwindow.h
index 388ca3f..c1702b6 100644
--- a/mythtv/libs/libmythui/mythmainwindow.h
+++ b/mythtv/libs/libmythui/mythmainwindow.h
@@ -105,6 +105,7 @@ class MUI_PUBLIC MythMainWindow : public QWidget
     QRect GetUIScreenRect();
     void  SetUIScreenRect(QRect &rect);
 
+    int GetDrawInterval() const;
     int NormalizeFontSize(int pointSize);
     MythRect NormRect(const MythRect &rect);
     QPoint NormPoint(const QPoint &point);
diff --git a/mythtv/libs/libmythui/mythpainter.h b/mythtv/libs/libmythui/mythpainter.h
index 1625aa2..70bcc48 100644
--- a/mythtv/libs/libmythui/mythpainter.h
+++ b/mythtv/libs/libmythui/mythpainter.h
@@ -21,6 +21,7 @@ class QColor;
 
 class MythFontProperties;
 class MythImage;
+struct Effects;
 
 typedef QVector<QTextLayout *>            LayoutVector;
 typedef QVector<QTextLayout::FormatRange> FormatVector;
@@ -67,6 +68,9 @@ class MUI_PUBLIC MythPainter
     virtual void DrawEllipse(const QRect &area, const QBrush &fillBrush,
                              const QPen &linePen, int alpha);
 
+    virtual void SetTransform(const Effects &zoom, QPointF center = QPointF()) { }
+    virtual void RestoreTransform(void) { }
+
     MythImage *GetFormatImage();
     void DeleteFormatImage(MythImage *im);
 
diff --git a/mythtv/libs/libmythui/mythpainter_ogl.cpp b/mythtv/libs/libmythui/mythpainter_ogl.cpp
index 2dd047c..85e17fa 100644
--- a/mythtv/libs/libmythui/mythpainter_ogl.cpp
+++ b/mythtv/libs/libmythui/mythpainter_ogl.cpp
@@ -227,3 +227,15 @@ void MythOpenGLPainter::DeleteFormatImagePriv(MythImage *im)
         m_ImageExpireList.remove(im);
     }
 }
+
+void MythOpenGLPainter::SetTransform(const Effects &fx, QPointF center)
+{
+    if (realRender)
+        realRender->SetTransform(fx, center);
+}
+
+void MythOpenGLPainter::RestoreTransform(void)
+{
+    if (realRender)
+        realRender->RestoreTransform();
+}
diff --git a/mythtv/libs/libmythui/mythpainter_ogl.h b/mythtv/libs/libmythui/mythpainter_ogl.h
index 34fffb0..600c930 100644
--- a/mythtv/libs/libmythui/mythpainter_ogl.h
+++ b/mythtv/libs/libmythui/mythpainter_ogl.h
@@ -34,6 +34,9 @@ class MUI_PUBLIC MythOpenGLPainter : public MythPainter
                                const QBrush &fillBrush, const QPen &linePen,
                                int alpha);
 
+    virtual void SetTransform(const Effects &fx, QPointF center = QPointF());
+    virtual void RestoreTransform(void);
+
   protected:
     virtual MythImage* GetFormatImagePriv(void) { return new MythImage(this); }
     virtual void DeleteFormatImagePriv(MythImage *im);
diff --git a/mythtv/libs/libmythui/mythrender_opengl.cpp b/mythtv/libs/libmythui/mythrender_opengl.cpp
index b7bf454..1d463a3 100644
--- a/mythtv/libs/libmythui/mythrender_opengl.cpp
+++ b/mythtv/libs/libmythui/mythrender_opengl.cpp
@@ -1,6 +1,7 @@
 #include <algorithm>
 using namespace std;
 
+#include "mythanimation.h"
 #include "mythlogging.h"
 #include "mythrender_opengl.h"
 #include "mythxdisplay.h"
@@ -258,6 +259,24 @@ void MythRenderOpenGL::SetFence(void)
     doneCurrent();
 }
 
+void MythRenderOpenGL::SetTransform(const Effects &fx, QPointF center)
+{
+    makeCurrent();
+    glPushMatrix();
+    glTranslatef(center.x(), center.y(), 0.0);
+    glScalef(fx.zoom, fx.zoom, 1.0);
+    glRotatef(fx.angle, 0, 0, 1);
+    glTranslatef(-center.x(), -center.y(), 0.0);
+    doneCurrent();
+}
+
+void MythRenderOpenGL::RestoreTransform(void)
+{
+    makeCurrent();
+    glPopMatrix();
+    doneCurrent();
+}
+
 void* MythRenderOpenGL::GetTextureBuffer(uint tex, bool create_buffer)
 {
     if (!m_textures.contains(tex))
diff --git a/mythtv/libs/libmythui/mythrender_opengl.h b/mythtv/libs/libmythui/mythrender_opengl.h
index 05f9384..adc0f8e 100644
--- a/mythtv/libs/libmythui/mythrender_opengl.h
+++ b/mythtv/libs/libmythui/mythrender_opengl.h
@@ -33,6 +33,8 @@
 #include "mythrender_base.h"
 #include "mythrender_opengl_defs.h"
 
+struct Effects;
+
 typedef enum
 {
     kGLFeatNone    = 0x0000,
@@ -127,6 +129,8 @@ class MUI_PUBLIC MythRenderOpenGL : public QGLContext, public MythRender
     virtual void SetColor(int r, int g, int b, int a) { }
     void  SetBackground(int r, int g, int b, int a);
     void  SetFence(void);
+    void  SetTransform(const Effects &fx, QPointF center = QPointF());
+    void  RestoreTransform(void);
 
     void* GetTextureBuffer(uint tex, bool create_buffer = true);
     void  UpdateTexture(uint tex, void *buf);
diff --git a/mythtv/libs/libmythui/mythscreentype.cpp b/mythtv/libs/libmythui/mythscreentype.cpp
index 0c495a1..ca05ecf 100644
--- a/mythtv/libs/libmythui/mythscreentype.cpp
+++ b/mythtv/libs/libmythui/mythscreentype.cpp
@@ -15,6 +15,7 @@
 #include "mythprogressdialog.h"
 #include "mythuigroup.h"
 #include "mythlogging.h"
+#include "mythanimation.h"
 
 QEvent::Type ScreenLoadCompletionEvent::kEventType =
     (QEvent::Type) QEvent::registerEventType();
@@ -237,6 +238,8 @@ void MythScreenType::aboutToHide(void)
                 GetMythMainWindow()->GetPaintWindow()->setMask(m_SavedMask);
         }
     }
+
+    ActivateAnimations(MythAnimation::AboutToHide);
 }
 
 void MythScreenType::aboutToShow(void)
@@ -253,6 +256,8 @@ void MythScreenType::aboutToShow(void)
             GetMythMainWindow()->GetPaintWindow()->setMask(region);
         }
     }
+
+    ActivateAnimations(MythAnimation::AboutToShow);
 }
 
 bool MythScreenType::IsDeleting(void) const
@@ -546,7 +551,7 @@ bool MythScreenType::ParseElement(
     }
     else
     {
-        return false;
+        return MythUIType::ParseElement(filename, element, showWarnings);
     }
 
     return true;
diff --git a/mythtv/libs/libmythui/mythuitype.cpp b/mythtv/libs/libmythui/mythuitype.cpp
index c6ce242..45ca7d6 100644
--- a/mythtv/libs/libmythui/mythuitype.cpp
+++ b/mythtv/libs/libmythui/mythuitype.cpp
@@ -11,6 +11,7 @@
 #include "mythlogging.h"
 
 // MythUI headers
+#include "mythanimation.h"
 #include "mythgesture.h"
 #include "mythimage.h"
 #include "mythpainter.h"
@@ -41,7 +42,6 @@ MythUIType::MythUIType(QObject *parent, const QString &name)
     m_Area = MythRect(0, 0, 0, 0);
     m_MinArea = MythRect(0, 0, 0, 0);
     m_NeedsRedraw = false;
-    m_Alpha = 255;
     m_AlphaChangeMode = m_AlphaChange = m_AlphaMin = 0;
     m_AlphaMax = 255;
     m_Moving = false;
@@ -71,6 +71,7 @@ MythUIType::MythUIType(QObject *parent, const QString &name)
 MythUIType::~MythUIType()
 {
     delete m_Fonts;
+    qDeleteAll(m_animations);
 }
 
 /**
@@ -272,6 +273,16 @@ MythUIType *MythUIType::GetChildAt(const QPoint &p, bool recursive,
     return NULL;
 }
 
+void MythUIType::ActivateAnimations(MythAnimation::When when)
+{
+    foreach (MythAnimation* animation, m_animations)
+        if (animation->GetWhen() == when)
+            animation->Activate();
+
+    foreach (MythUIType* uiType, m_ChildrenList)
+        uiType->ActivateAnimations(when);
+}
+
 bool MythUIType::NeedsRedraw(void) const
 {
     return m_NeedsRedraw;
@@ -402,16 +413,16 @@ void MythUIType::HandleAlphaPulse(void)
     if (m_AlphaChangeMode == 0)
         return;
 
-    m_Alpha += m_AlphaChange;
+    m_Effects.alpha += m_AlphaChange;
 
-    if (m_Alpha > m_AlphaMax)
-        m_Alpha = m_AlphaMax;
+    if (m_Effects.alpha > m_AlphaMax)
+        m_Effects.alpha = m_AlphaMax;
 
-    if (m_Alpha < m_AlphaMin)
-        m_Alpha = m_AlphaMin;
+    if (m_Effects.alpha < m_AlphaMin)
+        m_Effects.alpha = m_AlphaMin;
 
     // Reached limits so change direction
-    if (m_Alpha == m_AlphaMax || m_Alpha == m_AlphaMin)
+    if (m_Effects.alpha == m_AlphaMax || m_Effects.alpha == m_AlphaMin)
     {
         if (m_AlphaChangeMode == 2)
         {
@@ -441,6 +452,10 @@ void MythUIType::Pulse(void)
     HandleMovementPulse();
     HandleAlphaPulse();
 
+    QList<MythAnimation*>::Iterator i;
+    for (i = m_animations.begin(); i != m_animations.end(); ++i)
+        (*i)->incrementCurrentTime();
+
     QList<MythUIType *>::Iterator it;
 
     for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
@@ -449,7 +464,7 @@ void MythUIType::Pulse(void)
 
 int MythUIType::CalcAlpha(int alphamod)
 {
-    return (int)(m_Alpha * (alphamod / 255.0));
+    return (int)(m_Effects.alpha * (alphamod / 255.0));
 }
 
 void MythUIType::DrawSelf(MythPainter *, int, int, int, QRect)
@@ -470,6 +485,10 @@ void MythUIType::Draw(MythPainter *p, int xoffset, int yoffset, int alphaMod,
     if (!realArea.intersects(clipRect))
         return;
 
+    QPointF center(xoffset + m_Area.x() + m_Area.width() / 2.0,
+                   yoffset + m_Area.y() + m_Area.height() / 2.0);
+    p->SetTransform(m_Effects, center);
+
     DrawSelf(p, xoffset, yoffset, alphaMod, clipRect);
 
     QList<MythUIType *>::Iterator it;
@@ -494,6 +513,8 @@ void MythUIType::Draw(MythPainter *p, int xoffset, int yoffset, int alphaMod,
             p->DrawText(realArea, objectName(), 0, font, 255, realArea);
         }
     }
+
+    p->RestoreTransform();
 }
 
 void MythUIType::SetPosition(int x, int y)
@@ -894,25 +915,47 @@ void MythUIType::AdjustAlpha(int mode, int alphachange, int minalpha,
     m_AlphaMin = minalpha;
     m_AlphaMax = maxalpha;
 
-    if (m_Alpha > m_AlphaMax)
-        m_Alpha = m_AlphaMax;
+    if (m_Effects.alpha > m_AlphaMax)
+        m_Effects.alpha = m_AlphaMax;
 
-    if (m_Alpha < m_AlphaMin)
-        m_Alpha = m_AlphaMin;
+    if (m_Effects.alpha < m_AlphaMin)
+        m_Effects.alpha = m_AlphaMin;
 }
 
 void MythUIType::SetAlpha(int newalpha)
 {
-    if (m_Alpha == newalpha)
+    if (m_Effects.alpha == newalpha)
         return;
 
-    m_Alpha = newalpha;
+    m_Effects.alpha = newalpha;
     SetRedraw();
 }
 
 int MythUIType::GetAlpha(void) const
 {
-    return m_Alpha;
+    return m_Effects.alpha;
+}
+
+void MythUIType::SetZoom(float newzoom)
+{
+    m_Effects.zoom = newzoom;
+    SetRedraw();
+}
+
+float MythUIType::GetZoom(void) const
+{
+    return m_Effects.zoom;
+}
+
+void MythUIType::SetAngle(float newangle)
+{
+    m_Effects.angle = newangle;
+    SetRedraw();
+}
+
+float MythUIType::GetAngle(void) const
+{
+    return m_Effects.angle;
 }
 
 /** \brief Key event handler
@@ -1052,7 +1095,7 @@ void MythUIType::CopyFrom(MythUIType *base)
     m_MinSize = base->m_MinSize;
     m_Vanish = base->m_Vanish;
     m_Vanished = false;
-    m_Alpha = base->m_Alpha;
+    m_Effects = base->m_Effects;
     m_AlphaChangeMode = base->m_AlphaChangeMode;
     m_AlphaChange = base->m_AlphaChange;
     m_AlphaMin = base->m_AlphaMin;
@@ -1063,6 +1106,14 @@ void MythUIType::CopyFrom(MythUIType *base)
     m_XYSpeed = base->m_XYSpeed;
     m_deferload = base->m_deferload;
 
+    QList<MythAnimation*>::Iterator i;
+    for (i = base->m_animations.begin(); i != base->m_animations.end(); ++i)
+    {
+        MythAnimation* animation = new MythAnimation(this);
+        animation->CopyFrom(*i);
+        m_animations.push_back(animation);
+    }
+
     QList<MythUIType *>::Iterator it;
 
     for (it = base->m_ChildrenList.begin(); it != base->m_ChildrenList.end();
@@ -1116,17 +1167,17 @@ bool MythUIType::ParseElement(
     }
     else if (element.tagName() == "alpha")
     {
-        m_Alpha = getFirstText(element).toInt();
+        m_Effects.alpha = getFirstText(element).toInt();
         m_AlphaChangeMode = 0;
     }
     else if (element.tagName() == "alphapulse")
     {
         m_AlphaChangeMode = 2;
         m_AlphaMin = element.attribute("min", "0").toInt();
-        m_Alpha = m_AlphaMax = element.attribute("max", "255").toInt();
+        m_Effects.alpha = m_AlphaMax = element.attribute("max", "255").toInt();
 
         if (m_AlphaMax > 255)
-            m_Alpha = m_AlphaMax = 255;
+            m_Effects.alpha = m_AlphaMax = 255;
 
         if (m_AlphaMin < 0)
             m_AlphaMin = 0;
@@ -1146,6 +1197,14 @@ bool MythUIType::ParseElement(
     {
         m_helptext = getFirstText(element);
     }
+    else if (element.tagName() == "animation")
+    {
+        MythAnimation* animation = new MythAnimation(this);
+        if (animation->ParseElement(element))
+            m_animations.push_back(animation);
+        else
+            delete animation;
+    }
     else
         return false;
 
diff --git a/mythtv/libs/libmythui/mythuitype.h b/mythtv/libs/libmythui/mythuitype.h
index 99ce423..f24a982 100644
--- a/mythtv/libs/libmythui/mythuitype.h
+++ b/mythtv/libs/libmythui/mythuitype.h
@@ -9,6 +9,7 @@
 #include <QColor>
 
 #include "xmlparsebase.h"
+#include "mythanimation.h"
 #include "mythrect.h"
 #include "mythgesture.h"
 #include "mythmedia.h"
@@ -98,6 +99,8 @@ class MUI_PUBLIC MythUIType : public QObject, public XMLParseBase
     bool MoveToTop(void);
     bool MoveChildToTop(MythUIType *child);
 
+    void ActivateAnimations(MythAnimation::When when);
+
     // Called each draw pulse.  Will redraw automatically if dirty afterwards
     virtual void Pulse(void);
 
@@ -153,6 +156,12 @@ class MUI_PUBLIC MythUIType : public QObject, public XMLParseBase
     virtual MythPainter *GetPainter(void);
     void SetPainter(MythPainter *painter) { m_Painter = painter; }
 
+    void SetZoom(float zoom);
+    float GetZoom(void) const;
+
+    void SetAngle(float angle);
+    float GetAngle(void) const;
+
   protected:
     virtual void customEvent(QEvent *);
 
@@ -217,7 +226,8 @@ class MUI_PUBLIC MythUIType : public QObject, public XMLParseBase
     QRegion m_DirtyRegion;
     bool m_NeedsRedraw;
 
-    int m_Alpha;
+    Effects m_Effects;
+
     int m_AlphaChangeMode; // 0 - none, 1 - once, 2 - cycle
     int m_AlphaChange;
     int m_AlphaMin;
@@ -232,6 +242,7 @@ class MUI_PUBLIC MythUIType : public QObject, public XMLParseBase
     MythUIType *m_Parent;
     MythPainter *m_Painter;
 
+    QList<MythAnimation*> m_animations;
     QString m_helptext;
 
     bool m_deferload;
