Index: libs/libmythtv/tv_play.h
===================================================================
--- libs/libmythtv/tv_play.h	(revision 15495)
+++ libs/libmythtv/tv_play.h	(working copy)
@@ -444,10 +444,11 @@
 
     bool    smartForward;
     int     stickykeys;
-    float   ff_rew_repos;
     bool    ff_rew_reverse;
     bool    jumped_back; ///< Used by PromptDeleteRecording 
     vector<int> ff_rew_speeds;
+    vector<int> slowmo_speeds;
+    vector<float> ff_rew_repos;
 
     uint    vbimode;
 
@@ -524,6 +525,7 @@
      */
     float normal_speed; 
     float prev_speed;
+    float current_speed;
 
     float frameRate;     ///< Estimated framerate from recorder
 
Index: libs/libmythtv/tv_play.cpp
===================================================================
--- libs/libmythtv/tv_play.cpp	(revision 15495)
+++ libs/libmythtv/tv_play.cpp	(working copy)
@@ -497,7 +497,7 @@
       osd_general_timeout(2), osd_prog_info_timeout(3),
       autoCommercialSkip(CommSkipOff), tryUnflaggedSkip(false),
       smartForward(false), stickykeys(0),
-      ff_rew_repos(1.0f), ff_rew_reverse(false),
+      ff_rew_reverse(false),
       jumped_back(false),
       vbimode(VBIMode::None),
       // State variables
@@ -528,7 +528,7 @@
       // Fast forward state
       doing_ff_rew(0), ff_rew_index(0), speed_index(0),
       // Time Stretch state
-      normal_speed(1.0f), prev_speed(1.5f), 
+      normal_speed(1.0f), prev_speed(1.5f), current_speed(1.0f),
       // Estimated framerate from recorder
       frameRate(30.0f),
       // CC/Teletext input state variables
@@ -627,13 +627,36 @@
     tryUnflaggedSkip     = gContext->GetNumSetting("TryUnflaggedSkip", 0);
     smartForward         = gContext->GetNumSetting("SmartForward", 0);
     stickykeys           = gContext->GetNumSetting("StickyKeys");
-    ff_rew_repos         = gContext->GetNumSetting("FFRewReposTime", 100)/100.0;
     ff_rew_reverse       = gContext->GetNumSetting("FFRewReverse", 1);
-    int def[8] = { 3, 5, 10, 20, 30, 60, 120, 180 };
-    for (uint i = 0; i < sizeof(def)/sizeof(def[0]); i++)
-        ff_rew_speeds.push_back(
-            gContext->GetNumSetting(QString("FFRewSpeed%1").arg(i), def[i]));
 
+    int def1[8] = {3, 5, 10, 20, 30, 60, 120, 180};
+    int def_repos = gContext->GetNumSetting("FFRewReposTime", 100);
+    for (uint i = 0; i < sizeof(def1)/sizeof(def1[0]); i++)
+    {
+        int speed = gContext->GetNumSetting(QString("FFRewSpeed%1").arg(i),
+                                            def1[i]);
+        if (speed > 0)
+        {
+            ff_rew_speeds.push_back(speed);
+            int repos = gContext->GetNumSetting(QString("FFRewReposTime%1").
+                                                arg(i), def_repos);
+            if (repos < 0) repos = def_repos;
+            ff_rew_repos.push_back(repos / 100.0);
+        };
+    };
+
+    int def2[4] = {3, 8, 16, 0};
+    for (uint i = 0; i < sizeof(def2)/sizeof(def2[0]); i++)
+    {
+        int speed = gContext->GetNumSetting(QString("SlowMotionSpeed%1").
+                                            arg(i), def2[i]);
+        if (speed > 0)
+            slowmo_speeds.push_back(speed);
+    };
+
+
+
+
     vbimode = VBIMode::Parse(gContext->GetSetting("VbiFormat"));
 
     if (createWindow)
@@ -1946,6 +1969,7 @@
     speed_index = 0;
     sleep_index = 0;
     normal_speed = 1.0f;
+    current_speed = normal_speed;
 
     pbinfoLock.lock();
     if (playbackinfo)
@@ -2030,6 +2054,7 @@
     ff_rew_index = kInitFFRWSpeed;
     speed_index = 0;
     normal_speed = 1.0f;
+    current_speed = 1.0f;
     sleep_index = 0;
 
     int updatecheck = 0;
@@ -2279,6 +2304,7 @@
             speed_index = 0;
             doing_ff_rew = 0;
             ff_rew_index = kInitFFRWSpeed;
+            current_speed = normal_speed;
             UpdateOSDSeekMessage(PlayMesg(), osd_general_timeout);
         }
 
@@ -2288,6 +2314,8 @@
         {
             // got changed in nvp due to close to end of file
             normal_speed = 1.0f;
+            current_speed = 1.0f;
+
             UpdateOSDSeekMessage(PlayMesg(), osd_general_timeout);
         }
 
@@ -3552,6 +3580,7 @@
             {
                 StopFFRew();
                 normal_speed = 1.0f;
+                current_speed = 1.0f;
                 ChangeTimeStretch(0, false);
 
                 return;
@@ -3602,6 +3631,7 @@
                 stretch >= 0.48)
             {
                 normal_speed = stretch;   // alter speed before display
+                current_speed = normal_speed;
                 ChangeTimeStretch(0, false);
             }
         }
@@ -3613,28 +3643,14 @@
             if (paused)
                 DoPause();
 
-            if (tokens[2] == "16x")
-                ChangeSpeed(5 - speed_index);
-            else if (tokens[2] == "8x")
-                ChangeSpeed(4 - speed_index);
-            else if (tokens[2] == "4x")
-                ChangeSpeed(3 - speed_index);
-            else if (tokens[2] == "3x")
-                ChangeSpeed(2 - speed_index);
-            else if (tokens[2] == "2x")
-                ChangeSpeed(1 - speed_index);
-            else if (tokens[2] == "1x")
-                ChangeSpeed(0 - speed_index);
-            else if (tokens[2] == "1/2x")
-                ChangeSpeed(-1 - speed_index);
-            else if (tokens[2] == "1/3x")
-                ChangeSpeed(-2 - speed_index);
-            else if (tokens[2] == "1/4x")
-                ChangeSpeed(-3 - speed_index);
-            else if (tokens[2] == "1/8x")
-                ChangeSpeed(-4 - speed_index);
-            else if (tokens[2] == "1/16x")
-                ChangeSpeed(-5 - speed_index);
+            for (uint i = 0; i < slowmo_speeds.size(); i++)
+            {
+                if (tokens[2] == QString("1/%1x").arg(slowmo_speeds[i]))
+                {
+                    ChangeSpeed(-i - 1 - speed_index);
+                    break;
+                };
+            };
         }
         else
             VERBOSE(VB_IMPORTANT,
@@ -3671,25 +3687,12 @@
         {
             QString speedStr;
 
-            switch (speed_index)
+            speedStr = QString("%1X").arg(current_speed);
+            if ((current_speed > 0.0f) && (current_speed < 1.0f) && (speed_index != 0))
             {
-                case  4: speedStr = "16x"; break;
-                case  3: speedStr = "8x";  break;
-                case  2: speedStr = "3x";  break;
-                case  1: speedStr = "2x";  break;
-                case  0: speedStr = "1x";  break;
-                case -1: speedStr = "1/3x"; break;
-                case -2: speedStr = "1/8x"; break;
-                case -3: speedStr = "1/16x"; break;
-                case -4: speedStr = "0x"; break;
-                default: speedStr = "1x"; break;
-            }
+                speedStr = QString("1/%1X").arg(slowmo_speeds[-speed_index - 1]);
+            };
 
-            if (doing_ff_rew == -1)
-                speedStr = QString("-%1").arg(speedStr);
-            else if (normal_speed != 1.0)
-                speedStr = QString("%1X").arg(normal_speed);
-
             struct StatusPosInfo posInfo;
             nvp->calcSliderPos(posInfo, true);
 
@@ -3966,12 +3969,14 @@
         time = StopFFRew();
         activenvp->Play(normal_speed, true);
         speed_index = 0;
+        current_speed = normal_speed;
     }
     else if (paused || (speed_index != 0))
     {
         activenvp->Play(normal_speed, true);
         paused = false;
         speed_index = 0;
+        current_speed = normal_speed;
     }
 
 
@@ -4017,6 +4022,7 @@
     if (paused)
     {
         activenvp->Play(normal_speed, true);
+        current_speed = normal_speed;
     }
     else 
     {
@@ -4028,6 +4034,7 @@
         }
         
         activenvp->Pause();
+        current_speed = 0;
     }
 
     paused = !paused;
@@ -4130,6 +4137,7 @@
         return;
 
     speed_index = 0;
+    current_speed = normal_speed;
     activenvp->Play(normal_speed, true);
 }
 
@@ -4138,7 +4146,7 @@
     int old_speed = speed_index;
 
     if (paused)
-        speed_index = -4;
+        speed_index = -slowmo_speeds.size() - 1;
 
     speed_index += direction;
 
@@ -4146,25 +4154,35 @@
     float speed;
     QString mesg;
 
-    switch (speed_index)
+    if (speed_index == 0)
     {
-        case  4: speed = 16.0;     mesg = QString(tr("Speed 16X"));    break;
-        case  3: speed = 8.0;      mesg = QString(tr("Speed 8X"));    break;
-        case  2: speed = 3.0;      mesg = QString(tr("Speed 3X"));    break;
-        case  1: speed = 2.0;      mesg = QString(tr("Speed 2X"));    break;
-        case  0: speed = 1.0;      mesg = PlayMesg();                 break;
-        case -1: speed = 1.0 / 3;  mesg = QString(tr("Speed 1/3X"));  break;
-        case -2: speed = 1.0 / 8;  mesg = QString(tr("Speed 1/8X"));  break;
-        case -3: speed = 1.0 / 16; mesg = QString(tr("Speed 1/16X")); break;
-        case -4: DoPause(); return; break;
-        default: speed_index = old_speed; return; break;
+        speed = normal_speed;
+        mesg = PlayMesg();
     }
+    else if (speed_index > 0)
+    {
+        speed_index = min(speed_index, (int)ff_rew_speeds.size());
+        speed = ff_rew_speeds[speed_index - 1];
+        mesg = QString(tr("Speed")+(" %1X")).arg(speed);
+    }
+    else if (speed_index >= (int)-slowmo_speeds.size())
+    {
+        int divisor = slowmo_speeds[-speed_index - 1];
+        speed = 1.0f / divisor;
+        mesg = QString(tr("Speed")+(" 1/%1X")).arg(divisor);
+    }
+    else
+    {
+        DoPause();
+        return;
+    };
 
-    if (!activenvp->Play((speed_index==0)?normal_speed:speed, speed_index==0))
+    if (!activenvp->Play(speed, speed_index==0))
     {
         speed_index = old_speed;
         return;
     }
+    current_speed = speed;
 
     paused = false;
     DoNVPSeek(time);
@@ -4179,12 +4197,13 @@
         return time;
 
     if (doing_ff_rew > 0)
-        time = -ff_rew_speeds[ff_rew_index] * ff_rew_repos;
+        time = -ff_rew_speeds[ff_rew_index] * ff_rew_repos[ff_rew_index];
     else
-        time = ff_rew_speeds[ff_rew_index] * ff_rew_repos;
+        time = ff_rew_speeds[ff_rew_index] * ff_rew_repos[ff_rew_index];
 
     doing_ff_rew = 0;
     ff_rew_index = kInitFFRWSpeed;
+    current_speed = normal_speed;
 
     activenvp->Play(normal_speed, true);
 
@@ -4248,6 +4267,7 @@
         speed = -ff_rew_speeds[ff_rew_index];
     }
 
+    current_speed = (float)speed;
     activenvp->Play((float)speed, (speed == 1) && (doing_ff_rew > 0));
     UpdateOSDSeekMessage(mesg, -1);
 }
@@ -5897,7 +5917,10 @@
     normal_speed = new_normal_speed;
 
     if (!paused)
+    {
         activenvp->Play(normal_speed, true);
+        current_speed = normal_speed;
+    };
 
     QString text = QString(tr("Time Stretch %1X")).arg(normal_speed);
 
@@ -7311,7 +7334,7 @@
         int i = ((kAspect_14_9 == j) ? kAspect_16_9 :
                  ((kAspect_16_9 == j) ? kAspect_14_9 : j));
 
- 	bool sel = (i != kAspect_Off) ? (aspectoverride == i) :
+        bool sel = (i != kAspect_Off) ? (aspectoverride == i) :
             (aspectoverride <= kAspect_Off) || (aspectoverride >= kAspect_END);
         subitem = new OSDGenericTree(item, toString((AspectOverrideMode) i),
                                      QString("TOGGLEASPECT%1").arg(i),
@@ -7322,7 +7345,7 @@
     item = new OSDGenericTree(treeMenu, tr("Adjust Fill"));
     for (int i = kAdjustFill_Off; i < kAdjustFill_END; i++)
     {
- 	bool sel = (i != kAdjustFill_Off) ? (adjustfill == i) :
+        bool sel = (i != kAdjustFill_Off) ? (adjustfill == i) :
             (adjustfill <= kAdjustFill_Off) || (adjustfill >= kAdjustFill_END);
         subitem = new OSDGenericTree(item, toString((AdjustFillMode) i),
                                      QString("TOGGLEFILL%1").arg(i),
@@ -8042,6 +8065,7 @@
         chain->JumpTo(-1, 1);
 
         activenvp->Play(normal_speed, true, false);
+        current_speed = normal_speed;
         activerbuffer->IgnoreLiveEOF(false);
     }
 

