Backporting services API to myth 0.27 (aka getting recording watched status now)
#1
After discovering that myth 0.27.4 doesn't support the necessary API features to allow pvr.mythv to use the backend's watched status flag fully (my initial hopes, the reality and other examples) I decided to do something about it.

I don't want to run myth 0.28 development as I've finally found a version of mythbackend that runs without crashing (mythtv-0.27.4_p20141018), recovers reasonably gracefully after power cuts (although I occasionally have to run db repair) and generally continues to record things reliably. Also, I want to use pvr.mythv on Helix as lots of other things now just work 'better' than they used to on Gotham with the cmyth client (not perfect yet, but we're working on that ;-).

Turns out it is relatively easy to patch 0.27.4 (or any 0.27 version) to add the missing 'UpdateRecordedWatchedStatus' provided you settle for the Dvr API version 4.5 flavour and are running a source based distribution on your mythtv server like I am (gentoo).
A nasty hack to janbar's pvr.mythtv (the helix branch in my case) to enable this is also relatively easy to accomplish. I've now got this up and running on OE 5.0.8 on three RPi B/B+s, but I can see obvious problems:
  1. the myth services API is in active development with several obvious features missing (e.g. the ability to set resume points). When these are incorporated and Janbar enables them in his addon, I can tell I will want to back-port them as well, assuming 0.28 still hasn't gone 'stable' by then. Maybe even if it has given my experiences with 0.25....
  2. the services API is being revised regularly to add new parameters to existing functions / alternative ways of calling them (that's what development means after all). This is good as the new methods seem easier to use, but it means API users need to keep track of them all or miscellaneous breakage will result. Hats off to Janbar for attempting (and I believe succeeding) at this.
  3. the services API identifies versions per group (e.g. Dvr/Capture/Channel etc...) rather than per function. This makes cherry picking individual functions in a particular API group to back-port (as I did for my nasty hack) problematic if it is to be catered for in an 'official' or distributed add-on. Sure you can roll the API version to identify your new hybrid, but who defines what that version is called?
  4. I doubt that the mythv devs will want to maintain a 0.27 backports branch with selected 'features' like this implemented, effectively to support one particular user of the API (especially a replacement for mythfrontend). They seem to be focusing on the future and 0.28 (which looks encouraging from what I can see). Obviously, if there are any myth devs reading this who disagree, I would happily stand corrected...
  5. I can see tweaks to pvr.mythv which would make selective backports of services API functions to a particular 0.28 development version easier to accommodate (i.e. making pCapabilities->bSupportsRecordingPlayCount depend on the Dvr services API version rather than the myth protocol version), but unless janbar thinks this has merit I'd be reluctant to give it a try (he's obviously been pushing development of the services API, so should have a feel if this would be practical or not).

My conclusion is I should post the patches I used to get my setup working (see post below). Any like minded (and skilled?) individuals can then apply them to their set-up if they so choose. That's the power of open source Smile!

PS: Janbar, if you think backports of individual services APIs would be practical and could be supported by your official add-on in future, I'd be willing to try and produce a patch to bring myth 0.27 up to full DVR Service version 4.5 standard where UpdateRecordedWatchedStatus was introduced (I can't give any guarantees I will be successful of course Blush).
Reply
#2
Patch to mythtv 0.27 to implement the 'UpdateRecordedWatchedStatus' version contained in Dvr API version 4.5

Code:
diff --git a/mythtv/libs/libmythservicecontracts/services/dvrServices.h b/mythtv/libs/libmythservicecontracts/services/dvrServices.h
index 2233205..b03917a 100644
--- a/mythtv/libs/libmythservicecontracts/services/dvrServices.h
+++ b/mythtv/libs/libmythservicecontracts/services/dvrServices.h
@@ -39,13 +39,14 @@
class SERVICE_PUBLIC DvrServices : public Service  //, public QScriptable ???
{
     Q_OBJECT
-    Q_CLASSINFO( "version"    , "1.9" );
+    Q_CLASSINFO( "version"    , "1.9" ); //This is where any hybrid should be identified (Q: but how?)
     Q_CLASSINFO( "RemoveRecordedItem_Method",                   "POST" )
     Q_CLASSINFO( "AddRecordSchedule_Method",                    "POST" )
     Q_CLASSINFO( "RemoveRecordSchedule_Method",                 "POST" )
     Q_CLASSINFO( "EnableRecordSchedule_Method",                 "POST" )
     Q_CLASSINFO( "DisableRecordSchedule_Method",                "POST" )
     Q_CLASSINFO( "UpdateRecordSchedule_Method",                 "POST" )
+    Q_CLASSINFO( "UpdateRecordedWatchedStatus_Method",          "POST" ) //Added as backport of API 4.5 version

     public:

@@ -75,6 +76,11 @@ class SERVICE_PUBLIC DvrServices : public Service  //, public QScriptable ???
         virtual DTC::Program*      GetRecorded           ( int              ChanId,
                                                             const QDateTime &StartTime  ) = 0;

+        //Backport of UpdateRecordedWatchedStatus (API 4.5 version)
+        virtual bool               UpdateRecordedWatchedStatus (int   ChanId,
+                                                               const QDateTime &StartTime,
+                                                               bool  Watched) = 0;
+
         virtual bool               RemoveRecorded        ( int              ChanId,
                                                            const QDateTime &StartTime  ) = 0;

diff --git a/mythtv/programs/mythbackend/services/dvr.cpp b/mythtv/programs/mythbackend/services/dvr.cpp
index 6e0122b..bf870d8 100644
--- a/mythtv/programs/mythbackend/services/dvr.cpp
+++ b/mythtv/programs/mythbackend/services/dvr.cpp
@@ -142,6 +142,22 @@ DTC::Program* Dvr::GetRecorded(int chanid, const QDateTime &recstarttsRaw)
     return pProgram;
}

+// Backport of UpdateRecordedWatchedStatus (API 4.5 version)
+bool Dvr::UpdateRecordedWatchedStatus ( int   chanid,
+                                        const QDateTime &recstarttsRaw,
+                                        bool  watched)
+{
+     if  (chanid <= 0 || !recstarttsRaw.isValid())
+       throw QString("Channel ID and StartTime appears invalid.");
+
+     // TODO Should use RecordingInfo
+     ProgramInfo pi;
+     pi = ProgramInfo(chanid, recstarttsRaw.toUTC());
+     pi.SaveWatched(watched);
+                                                                                                                                       //
+    return true;
+}
+
/////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////
diff --git a/mythtv/programs/mythbackend/services/dvr.h b/mythtv/programs/mythbackend/services/dvr.h
index e2510ab..6376742 100644
--- a/mythtv/programs/mythbackend/services/dvr.h
+++ b/mythtv/programs/mythbackend/services/dvr.h
@@ -53,6 +53,11 @@ class Dvr : public DvrServices
         DTC::Program*     GetRecorded         ( int              ChanId,
                                                 const QDateTime &StartTime  );

+// Backport of  UpdateRecordedWatchedStatus (API 4.5 version)
+       bool              UpdateRecordedWatchedStatus ( int   ChanId,
+                                                       const QDateTime &StartTime,
+                                                       bool  Watched);
+
         bool              RemoveRecorded      ( int              ChanId,
                                                 const QDateTime &StartTime  );

Example instructions for application on gentoo (adjust filenames and paths to suit). If it breaks you get to keep both pieces:
  1. make sure you have your myth database backed up!
  2. emerge gentoolkit (if you don't have it already)
  3. emerge git (if you don't have it already)
  4. equery which mythtv (find out the path to the ebuild you currently have installed)
  5. ebuild /usr/portage/media-tv/mythtv/mythtv-0.27.4_p20141018.ebuild configure (unpack your e-build and run configure)
  6. cd /var/tmp/portage/media-tv/mythtv-0.27.4_p20141018/work/mythtv-0.27.4 (go to the working directory)
  7. copy the patch above into a file called 'mythtv-0.27-metaron-UpdateRecordedWatchedStatus.patch' (or similar)
  8. git apply mythtv-0.27-metaron-UpdateRecordedWatchedStatus.patch (apply the patch)
  9. cat mythtv/libs/libmythservicecontracts/services/dvrServices.h (check you have updated at least one of the files)
  10. ebuild /usr/portage/media-tv/mythtv/mythtv-0.27.4_p20141018.ebuild compile (build your patched version of mythtv - this takes a while...)
  11. ebuild /usr/portage/media-tv/mythtv/mythtv-0.27.4_p20141018.ebuild install (prepare for installation)
  12. check that mythbackend isn't currently recording anything vital and you have time to put things right if something goes wrong (see below)
  13. ebuild /usr/portage/media-tv/mythtv/mythtv-0.27.4_p20141018.ebuild qmerge (install your updated version on the live system)
  14. /etc/init.d/mythbackend restart (run the updated version of the server)

if something goes wrong the following should put back your standard gentoo mythtv installation although compilation will take a while.
If you really can't afford the downtime, investigate quickpkg.
  • emerge mythtv
  • /etc/init.d/mythbackend restart
You might also be glad you followed step 1 and did a database backup...

Janbar's official addon should work fine with this hacked version of myth, it just won't use the backend's watched flag.
Reply
#3
Patch to make use of the recording watched flag added to your patched 0.27 based mythbackend server as per the previous post

Code:
diff --git a/lib/cppmyth/src/mythwsapi.h b/lib/cppmyth/src/mythwsapi.h
index 3faf7aa..c1f147c 100644
--- a/lib/cppmyth/src/mythwsapi.h
+++ b/lib/cppmyth/src/mythwsapi.h
@@ -187,7 +187,8 @@ namespace Myth
     bool UpdateRecordedWatchedStatus(uint32_t chanid, time_t recstartts, bool watched)
     {
       WSServiceVersion_t wsv = CheckService(WS_Dvr);
-      if (wsv.ranking >= 0x00040005) return UpdateRecordedWatchedStatus4_5(chanid, recstartts, watched);
+      //Hack to try using the 4.5 version of UpdateRecordedWatchedStatus if the version reported is 1.9
+      if (wsv.ranking >= 0x00040005 || wsv.ranking == 0x00010009 ) return UpdateRecordedWatchedStatus4_5(chanid, recstartts, watched);
       return false;
     }

diff --git a/src/client.cpp b/src/client.cpp
index cb78cba..85ab2a3 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -691,6 +691,11 @@ PVR_ERROR GetAddonCapabilities(PVR_ADDON_CAPABILITIES *pCapabilities)

     pCapabilities->bSupportsRecordings            = true;
     pCapabilities->bSupportsRecordingPlayCount    = (version < 80 ? false : true);
+    if (version == 77) {
+        XBMC->Log(LOG_INFO, "Patched mythtv 0.27 with UpdateRecordedWatchedStatus backport assumed. Using backend watched status.");
+        XBMC->Log(LOG_INFO, "See http://forum.kodi.tv/showthread.php?tid=228044 for more details.");
+        pCapabilities->bSupportsRecordingPlayCount = true;
+    }
     pCapabilities->bSupportsLastPlayedPosition    = false;
     pCapabilities->bSupportsRecordingEdl          = true;
     return PVR_ERROR_NO_ERROR;

Health warning: This is fairly fairly benign hack. If it finds a 0.27 server which hasn't been patched you end up with "(CPPMyth)UpdateRecordedWatchedStatus4_5: invalid response" errors in kodi.log when watched status changes and the backend doesn't store changes to watched status (you can see watched status from the backend and changes to the 'watched' ticks still appear in kodi, but they are gone when you restart).
If are running mythbackend 0.26 or 0.28 (i.e. not protocol 77) it won't do anything different from an un-patched addon.

Instructions for building an OpenElec 5.0.8 compatible addon for RPi (again, if it breaks you get to keep both pieces)
  1. Follow the Build Into Openelec Instructions up until the instruction to 'make'
  2. save the patch above to a file called 'pvr.mythtv-metaron-UpdateRecordedWatchedStatus.patch' in the build directory
  3. cd ../pvr.mythtv (change to the working directory)
  4. git apply ../build/pvr.mythtv-metaron-UpdateRecordedWatchedStatus.patch
  5. git status (check you have the two files listed as modified)
  6. cd ../build
  7. make (build your updated addon)
  8. follow the remaining 'Build into OpenElec' instructions to create a zip file
  9. upload the zip file to your OpenElec installation and install in the usual way
  10. To confirm it is installed, turn debugging on, restart openelec, ssh into the box and type: cat .kodi/temp/kodi.log | grep UpdateRecorded. You should see something like this:
    14:27:44 T:1777333312 INFO: AddOnLog: MythTV PVR Client: Patched mythtv 0.27 with UpdateRecordedWatchedStatus backport assumed. Using backend watched status.

This configuration is now rolled out on my server and kodi frontends and seems to be working.

Obviously you don't need this at all if you are running a 0.28 based mythbackend.

This patch was written against the 1.12.18 helix addon, but I can't see any reason why it wouldn't work on the 2.2.0 isenguard version from the doityourself branch.

I'd be interested to know if anyone else finds it useful.
Reply
#4
Nice backport
Reply
#5
Thanks Smile
Reply
#6
Here below a patch using "Dvr" WS-API version instead backend protocol version. Hope it help.

Code:
diff --git a/lib/cppmyth/src/mythcontrol.h b/lib/cppmyth/src/mythcontrol.h
index e63e367..9853f13 100644
--- a/lib/cppmyth/src/mythcontrol.h
+++ b/lib/cppmyth/src/mythcontrol.h
@@ -52,6 +52,17 @@ namespace Myth
     }

     /**
+     * @brief Check availability of WS-API services
+     * @param id WS service ID
+     * @return If unavailable then 0 else the major/minor version number
+     */
+    unsigned CheckWSService(WSServiceId_t id)
+    {
+      WSServiceVersion_t wsv = m_wsapi.CheckService(id);
+      return wsv.ranking;
+    }
+
+    /**
      * @brief Query server host name
      * @return string
      */
diff --git a/src/client.cpp b/src/client.cpp
index b2cc343..7147e00 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -678,7 +678,7 @@ PVR_ERROR GetAddonCapabilities(PVR_ADDON_CAPABILITIES *pCapabilities)
{
   if (g_client != NULL)
   {
-    unsigned version = g_client->GetBackendAPIVersion();
+    unsigned versionWSDvr = g_client->GetBackendWSAPIVersion(Myth::WS_Dvr);
     pCapabilities->bSupportsTV                    = g_bLiveTV;
     pCapabilities->bSupportsRadio                 = g_bLiveTV;
     pCapabilities->bSupportsChannelGroups         = true;
@@ -691,7 +691,7 @@ PVR_ERROR GetAddonCapabilities(PVR_ADDON_CAPABILITIES *pCapabilities)

     pCapabilities->bSupportsRecordings            = true;
     pCapabilities->bSupportsRecordingsUndelete    = true;
-    pCapabilities->bSupportsRecordingPlayCount    = (version < 80 ? false : true);
+    pCapabilities->bSupportsRecordingPlayCount    = (versionWSDvr < 0x00040005 ? false : true);
     pCapabilities->bSupportsLastPlayedPosition    = false;
     pCapabilities->bSupportsRecordingEdl          = true;
     return PVR_ERROR_NO_ERROR;
diff --git a/src/pvrclient-mythtv.cpp b/src/pvrclient-mythtv.cpp
index 031b3da..6035c6d 100644
--- a/src/pvrclient-mythtv.cpp
+++ b/src/pvrclient-mythtv.cpp
@@ -145,6 +145,13 @@ unsigned PVRClientMythTV::GetBackendAPIVersion()
   return 0;
}

+unsigned PVRClientMythTV::GetBackendWSAPIVersion(Myth::WSServiceId_t id)
+{
+  if (m_control)
+    return m_control->CheckWSService(id);
+  return 0;
+}
+
const char *PVRClientMythTV::GetBackendName()
{
   static std::string myName;
diff --git a/src/pvrclient-mythtv.h b/src/pvrclient-mythtv.h
index 0b8b63a..434dbb5 100644
--- a/src/pvrclient-mythtv.h
+++ b/src/pvrclient-mythtv.h
@@ -49,6 +49,7 @@ public:
   void SetDebug();
   bool Connect();
   unsigned GetBackendAPIVersion();
+  unsigned GetBackendWSAPIVersion(Myth::WSServiceId_t id);
   const char *GetBackendName();
   const char *GetBackendVersion();
   const char *GetConnectionString();
Reply
#7
thx guys,

will give this a try too
Reply
#8
there are some leading spaces missing in the mythtv patch.

but with the spaces it works great for me. thx
Reply

Logout Mark Read Team Forum Stats Members Help
Backporting services API to myth 0.27 (aka getting recording watched status now)0