[SCM] kodi-pvr-hts/master: replace the tvhxxx() macros with a separate logger utility

tiber-guest at users.alioth.debian.org tiber-guest at users.alioth.debian.org
Wed Mar 2 23:01:53 UTC 2016


The following commit has been merged in the master branch:
commit e77102f3e628069bea82a1fbfd20f92960d37227
Author: Sam Stenvall <sam.stenvall at nordsoftware.com>
Date:   Sun Oct 25 20:59:29 2015 +0200

    replace the tvhxxx() macros with a separate logger utility

diff --git a/pvr.hts/changelog.txt b/pvr.hts/changelog.txt
index 310d506..4e2bc4e 100644
--- a/pvr.hts/changelog.txt
+++ b/pvr.hts/changelog.txt
@@ -8,6 +8,7 @@
 - fixed: restart subscription after a connection restore
 - fixed: allow to abort active recordings also for timers created by timerec and autorec
 - fixed: enable/disable of timers created by timerec and autorec (HTSP v23 and above)
+- refactored the logging utility from a bunch of macros to a class
 
 2.2.9
 - refactored the code by factoring out lots of things into separate files
diff --git a/src/AutoRecordings.cpp b/src/AutoRecordings.cpp
index ee61cb6..34b9bfc 100644
--- a/src/AutoRecordings.cpp
+++ b/src/AutoRecordings.cpp
@@ -24,10 +24,12 @@
 #include "Tvheadend.h"
 #include "tvheadend/Settings.h"
 #include "tvheadend/utilities/Utilities.h"
+#include "tvheadend/utilities/Logger.h"
 
 using namespace PLATFORM;
 using namespace tvheadend;
 using namespace tvheadend::entity;
+using namespace tvheadend::utilities;
 
 AutoRecordings::AutoRecordings(CHTSPConnection &conn) :
   m_conn(conn)
@@ -132,7 +134,7 @@ const unsigned int AutoRecordings::GetTimerIntIdFromStringId(const std::string &
     if (tit->second.GetStringId() == strId)
       return tit->second.GetId();
   }
-  tvherror("Autorec: Unable to obtain int id for string id %s", strId.c_str());
+  Logger::Log(LogLevel::ERROR, "Autorec: Unable to obtain int id for string id %s", strId.c_str());
   return 0;
 }
 
@@ -238,7 +240,7 @@ PVR_ERROR AutoRecordings::SendAutorecAdd(const PVR_TIMER &timer)
   /* Check for error */
   if (htsmsg_get_u32(m, "success", &u32))
   {
-    tvherror("malformed addAutorecEntry response: 'success' missing");
+    Logger::Log(LogLevel::ERROR, "malformed addAutorecEntry response: 'success' missing");
     u32 = PVR_ERROR_FAILED;
   }
   htsmsg_destroy(m);
@@ -287,7 +289,7 @@ PVR_ERROR AutoRecordings::SendAutorecDelete(const PVR_TIMER &timer)
   /* Check for error */
   if (htsmsg_get_u32(m, "success", &u32))
   {
-    tvherror("malformed deleteAutorecEntry response: 'success' missing");
+    Logger::Log(LogLevel::ERROR, "malformed deleteAutorecEntry response: 'success' missing");
   }
   htsmsg_destroy(m);
 
@@ -304,7 +306,7 @@ bool AutoRecordings::ParseAutorecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   /* Validate/set mandatory fields */
   if ((str = htsmsg_get_str(msg, "id")) == NULL)
   {
-    tvherror("malformed autorecEntryAdd/autorecEntryUpdate: 'id' missing");
+    Logger::Log(LogLevel::ERROR, "malformed autorecEntryAdd/autorecEntryUpdate: 'id' missing");
     return false;
   }
 
@@ -321,7 +323,7 @@ bool AutoRecordings::ParseAutorecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd)
   {
-    tvherror("malformed autorecEntryAdd: 'enabled' missing");
+    Logger::Log(LogLevel::ERROR, "malformed autorecEntryAdd: 'enabled' missing");
     return false;
   }
 
@@ -331,7 +333,7 @@ bool AutoRecordings::ParseAutorecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd)
   {
-    tvherror("malformed autorecEntryAdd: 'retention' missing");
+    Logger::Log(LogLevel::ERROR, "malformed autorecEntryAdd: 'retention' missing");
     return false;
   }
 
@@ -341,7 +343,7 @@ bool AutoRecordings::ParseAutorecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd && (m_conn.GetProtocol() >= 24))
   {
-    tvherror("malformed autorecEntryAdd: 'removal' missing");
+    Logger::Log(LogLevel::ERROR, "malformed autorecEntryAdd: 'removal' missing");
     return false;
   }
 
@@ -351,7 +353,7 @@ bool AutoRecordings::ParseAutorecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd)
   {
-    tvherror("malformed autorecEntryAdd: 'daysOfWeek' missing");
+    Logger::Log(LogLevel::ERROR, "malformed autorecEntryAdd: 'daysOfWeek' missing");
     return false;
   }
 
@@ -361,7 +363,7 @@ bool AutoRecordings::ParseAutorecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd)
   {
-    tvherror("malformed autorecEntryAdd: 'priority' missing");
+    Logger::Log(LogLevel::ERROR, "malformed autorecEntryAdd: 'priority' missing");
     return false;
   }
 
@@ -371,7 +373,7 @@ bool AutoRecordings::ParseAutorecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd)
   {
-    tvherror("malformed autorecEntryAdd: 'start' missing");
+    Logger::Log(LogLevel::ERROR, "malformed autorecEntryAdd: 'start' missing");
     return false;
   }
 
@@ -381,7 +383,7 @@ bool AutoRecordings::ParseAutorecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd)
   {
-    tvherror("malformed autorecEntryAdd: 'startWindow' missing");
+    Logger::Log(LogLevel::ERROR, "malformed autorecEntryAdd: 'startWindow' missing");
     return false;
   }
 
@@ -391,7 +393,7 @@ bool AutoRecordings::ParseAutorecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd)
   {
-    tvherror("malformed autorecEntryAdd: 'startExtra' missing");
+    Logger::Log(LogLevel::ERROR, "malformed autorecEntryAdd: 'startExtra' missing");
     return false;
   }
 
@@ -401,7 +403,7 @@ bool AutoRecordings::ParseAutorecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd)
   {
-    tvherror("malformed autorecEntryAdd: 'stopExtra' missing");
+    Logger::Log(LogLevel::ERROR, "malformed autorecEntryAdd: 'stopExtra' missing");
     return false;
   }
 
@@ -411,7 +413,7 @@ bool AutoRecordings::ParseAutorecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd && (m_conn.GetProtocol() >= 20))
   {
-    tvherror("malformed autorecEntryAdd: 'dupDetect' missing");
+    Logger::Log(LogLevel::ERROR, "malformed autorecEntryAdd: 'dupDetect' missing");
     return false;
   }
 
@@ -461,10 +463,10 @@ bool AutoRecordings::ParseAutorecDelete(htsmsg_t *msg)
   /* Validate/set mandatory fields */
   if ((id = htsmsg_get_str(msg, "id")) == NULL)
   {
-    tvherror("malformed autorecEntryDelete: 'id' missing");
+    Logger::Log(LogLevel::ERROR, "malformed autorecEntryDelete: 'id' missing");
     return false;
   }
-  tvhtrace("delete autorec entry %s", id);
+  Logger::Log(LogLevel::TRACE, "delete autorec entry %s", id);
 
   /* Erase */
   m_autoRecordings.erase(std::string(id));
diff --git a/src/HTSPConnection.cpp b/src/HTSPConnection.cpp
index c2ba412..a22ace6 100644
--- a/src/HTSPConnection.cpp
+++ b/src/HTSPConnection.cpp
@@ -28,12 +28,14 @@ extern "C" {
 #include "libhts/sha1.h"
 }
 
+#include "tvheadend/utilities/Logger.h"
 #include "Tvheadend.h"
 
 using namespace std;
 using namespace ADDON;
 using namespace PLATFORM;
 using namespace tvheadend;
+using namespace tvheadend::utilities;
 
 /*
  * HTSP Response objct
@@ -132,7 +134,7 @@ std::string CHTSPConnection::GetWebURL ( const char *fmt, ... )
 bool CHTSPConnection::WaitForConnection ( void )
 {
   if (!m_ready) {
-    tvhtrace("waiting for registration...");
+    Logger::Log(LogLevel::TRACE, "waiting for registration...");
     m_regCond.Wait(m_mutex, m_ready, Settings::GetInstance().GetConnectTimeout());
   }
   return m_ready;
@@ -169,7 +171,7 @@ void CHTSPConnection::OnSleep ( void )
 {
   CLockObject lock(m_mutex);
 
-  tvhtrace("going to sleep (OnSleep)");
+  Logger::Log(LogLevel::TRACE, "going to sleep (OnSleep)");
 
   /* close connection, prevent reconnect while suspending/suspended */
   m_suspended = true;
@@ -179,7 +181,7 @@ void CHTSPConnection::OnWake ( void )
 {
   CLockObject lock(m_mutex);
 
-  tvhtrace("waking up (OnWake)");
+  Logger::Log(LogLevel::TRACE, "waking up (OnWake)");
 
   /* recreate connection */
   m_suspended = false;
@@ -231,7 +233,7 @@ bool CHTSPConnection::ReadMessage ( void )
     r = m_socket->Read((char*)buf + cnt, len - cnt, Settings::GetInstance().GetResponseTimeout());
     if (r < 0)
     {
-      tvherror("failed to read packet (%s)",
+      Logger::Log(LogLevel::ERROR, "failed to read packet (%s)",
                m_socket->GetError().c_str());
       free(buf);
       return false;
@@ -243,14 +245,14 @@ bool CHTSPConnection::ReadMessage ( void )
   if (!(msg = htsmsg_binary_deserialize(buf, len, buf)))
   {
     /* Do not free buf here. Already done by htsmsg_binary_deserialize. */
-    tvherror("failed to decode message");
+    Logger::Log(LogLevel::ERROR, "failed to decode message");
     return false;
   }
 
   /* Sequence number - response */
   if (htsmsg_get_u32(msg, "seq", &seq) == 0)
   {
-    tvhtrace("received response [%d]", seq);
+    Logger::Log(LogLevel::TRACE, "received response [%d]", seq);
     CLockObject lock(m_mutex);
     CHTSPResponseList::iterator it;
     if ((it = m_messages.find(seq)) != m_messages.end())
@@ -263,11 +265,11 @@ bool CHTSPConnection::ReadMessage ( void )
   /* Get method */
   if (!(method = htsmsg_get_str(msg, "method")))
   {
-    tvherror("message without a method");
+    Logger::Log(LogLevel::ERROR, "message without a method");
     htsmsg_destroy(msg);
     return true;
   }
-  tvhtrace("receive message [%s]", method);
+  Logger::Log(LogLevel::TRACE, "receive message [%s]", method);
 
   /* Pass (if return is true, message is finished) */
   if (tvh->ProcessMessage(method, msg))
@@ -290,11 +292,11 @@ bool CHTSPConnection::SendMessage0 ( const char *method, htsmsg_t *msg )
 
   if (!htsmsg_get_u32(msg, "seq", &seq))
   {
-    tvhtrace("sending message [%s : %d]", method, seq);
+    Logger::Log(LogLevel::TRACE, "sending message [%s : %d]", method, seq);
   }
   else
   {
-    tvhtrace("sending message [%s]", method);
+    Logger::Log(LogLevel::TRACE, "sending message [%s]", method);
   }
   htsmsg_add_str(msg, "method", method);
 
@@ -309,7 +311,7 @@ bool CHTSPConnection::SendMessage0 ( const char *method, htsmsg_t *msg )
   free(buf);
   if (c != (ssize_t)len)
   {
-    tvherror("failed to write (%s)",
+    Logger::Log(LogLevel::ERROR, "failed to write (%s)",
               m_socket->GetError().c_str());
     if (!m_suspended)
       Disconnect();
@@ -339,7 +341,7 @@ htsmsg_t *CHTSPConnection::SendAndWait0 ( const char *method, htsmsg_t *msg, int
   if (!SendMessage0(method, msg))
   {
     m_messages.erase(seq);
-    tvherror("failed to transmit");
+    Logger::Log(LogLevel::ERROR, "failed to transmit");
     return NULL;
   }
 
@@ -349,7 +351,7 @@ htsmsg_t *CHTSPConnection::SendAndWait0 ( const char *method, htsmsg_t *msg, int
   if (!msg)
   {
     //XBMC->QueueNotification(QUEUE_ERROR, "Command %s failed: No response received", method);
-    tvherror("Command %s failed: No response received", method);
+    Logger::Log(LogLevel::ERROR, "Command %s failed: No response received", method);
     if (!m_suspended)
       Disconnect();
     return NULL;
@@ -361,7 +363,7 @@ htsmsg_t *CHTSPConnection::SendAndWait0 ( const char *method, htsmsg_t *msg, int
   {
     // access denied
     //XBMC->QueueNotification(QUEUE_ERROR, "Command %s failed: Access denied", method);
-    tvherror("Command %s failed: Access denied", method);
+    Logger::Log(LogLevel::ERROR, "Command %s failed: Access denied", method);
     htsmsg_destroy(msg);
     return NULL;
   }
@@ -371,7 +373,7 @@ htsmsg_t *CHTSPConnection::SendAndWait0 ( const char *method, htsmsg_t *msg, int
     if((strError = htsmsg_get_str(msg, "error")) != NULL)
     {
       //XBMC->QueueNotification(QUEUE_ERROR, "Command %s failed: %s", method, strError);
-      tvherror("Command %s failed: %s", method, strError);
+      Logger::Log(LogLevel::ERROR, "Command %s failed: %s", method, strError);
       htsmsg_destroy(msg);
       return NULL;
     }
@@ -416,7 +418,7 @@ bool CHTSPConnection::SendHello ( void )
   m_serverVersion = htsmsg_get_str(msg, "serverversion");
   m_htspVersion   = htsmsg_get_u32_or_default(msg, "htspversion", 0);
   m_webRoot       = webroot ? webroot : "";
-  tvhdebug("connected to %s / %s (HTSPv%d)",
+  Logger::Log(LogLevel::DEBUG, "connected to %s / %s (HTSPv%d)",
             m_serverName.c_str(), m_serverVersion.c_str(), m_htspVersion);
 
   /* Capabilities */
@@ -480,16 +482,16 @@ void CHTSPConnection::Register ( void )
     CLockObject lock(m_mutex);
 
     /* Send Greeting */
-    tvhdebug("sending hello");
+    Logger::Log(LogLevel::DEBUG, "sending hello");
     if (!SendHello()) {
-      tvherror("failed to send hello");
+      Logger::Log(LogLevel::ERROR, "failed to send hello");
       goto fail;
     }
 
     /* Check htsp server version against client minimum htsp version */
     if (m_htspVersion < HTSP_MIN_SERVER_VERSION)
     {
-      tvherror("server htsp version (v%d) does not match minimum htsp version required by client (v%d)", m_htspVersion, HTSP_MIN_SERVER_VERSION);
+      Logger::Log(LogLevel::ERROR, "server htsp version (v%d) does not match minimum htsp version required by client (v%d)", m_htspVersion, HTSP_MIN_SERVER_VERSION);
       Disconnect();
       m_ready = false;
       m_regCond.Broadcast();
@@ -497,17 +499,17 @@ void CHTSPConnection::Register ( void )
     }
 
     /* Send Auth */
-    tvhdebug("sending auth");
+    Logger::Log(LogLevel::DEBUG, "sending auth");
     
     if (!SendAuth(user, pass))
       goto fail;
 
     /* Rebuild state */
-    tvhdebug("rebuilding state");
+    Logger::Log(LogLevel::DEBUG, "rebuilding state");
     if (!tvh->Connected())
       goto fail;
 
-    tvhdebug("registered");
+    Logger::Log(LogLevel::DEBUG, "registered");
     m_ready = true;
     m_regCond.Broadcast();
     return;
@@ -529,7 +531,7 @@ void* CHTSPConnection::Process ( void )
 
   while (!IsStopped())
   {
-    tvhdebug("new connection requested");
+    Logger::Log(LogLevel::DEBUG, "new connection requested");
 
     std::string host = settings.GetHostname();
     int port, timeout;
@@ -553,7 +555,7 @@ void* CHTSPConnection::Process ( void )
 
     while (m_suspended)
     {
-      tvhdebug("suspended. Waiting for wakeup...");
+      Logger::Log(LogLevel::DEBUG, "suspended. Waiting for wakeup...");
 
       /* Wait for wakeup */
       Sleep(1000);
@@ -561,20 +563,20 @@ void* CHTSPConnection::Process ( void )
 
     if (!log)
     {
-      tvhdebug("connecting to %s:%d", host.c_str(), port);
+      Logger::Log(LogLevel::DEBUG, "connecting to %s:%d", host.c_str(), port);
       log = true;
     }
     else
     {
-      tvhtrace("connecting to %s:%d", host.c_str(), port);
+      Logger::Log(LogLevel::TRACE, "connecting to %s:%d", host.c_str(), port);
     }
 
     /* Connect */
-    tvhtrace("waiting for connection...");
+    Logger::Log(LogLevel::TRACE, "waiting for connection...");
     if (!m_socket->Open(timeout))
     {
       /* Unable to connect */
-      tvherror("unable to connect to %s:%d", host.c_str(), port);
+      Logger::Log(LogLevel::ERROR, "unable to connect to %s:%d", host.c_str(), port);
       
       // Retry a few times with a short interval, after that with the default timeout
       if (++retryAttempt <= FAST_RECONNECT_ATTEMPTS)
@@ -584,7 +586,7 @@ void* CHTSPConnection::Process ( void )
       
       continue;
     }
-    tvhdebug("connected");
+    Logger::Log(LogLevel::DEBUG, "connected");
     log = false;
     retryAttempt = 0;
 
@@ -596,7 +598,7 @@ void* CHTSPConnection::Process ( void )
     {
       if (!ReadMessage())
       {
-        tvhdebug("attempting reconnect");
+        Logger::Log(LogLevel::DEBUG, "attempting reconnect");
         break;
       }
     }
diff --git a/src/HTSPDemuxer.cpp b/src/HTSPDemuxer.cpp
index 14a6944..c9c2e61 100644
--- a/src/HTSPDemuxer.cpp
+++ b/src/HTSPDemuxer.cpp
@@ -19,6 +19,7 @@
  *
  */
 
+#include "tvheadend/utilities/Logger.h"
 #include "Tvheadend.h"
 #include "xbmc_codec_descriptor.hpp"
 
@@ -28,6 +29,7 @@ using namespace std;
 using namespace ADDON;
 using namespace PLATFORM;
 using namespace tvheadend;
+using namespace tvheadend::utilities;
 
 CHTSPDemuxer::CHTSPDemuxer ( CHTSPConnection &conn )
   : m_conn(conn), m_pktBuffer((size_t)-1),
@@ -46,7 +48,7 @@ void CHTSPDemuxer::Connected ( void )
   /* Re-subscribe */
   if (m_subscription.IsActive())
   {
-    tvhdebug("demux re-starting stream");
+    Logger::Log(LogLevel::DEBUG, "demux re-starting stream");
     m_subscription.SendSubscribe(0, 0, true);
     m_subscription.SendSpeed(0, true);
 
@@ -82,7 +84,7 @@ void CHTSPDemuxer::Abort0 ( void )
 bool CHTSPDemuxer::Open ( uint32_t channelId, enum eSubscriptionWeight weight )
 {
   CLockObject lock(m_conn.Mutex());
-  tvhdebug("demux open");
+  Logger::Log(LogLevel::DEBUG, "demux open");
 
   /* Close current stream */
   Close0();
@@ -107,7 +109,7 @@ void CHTSPDemuxer::Close ( void )
 {
   CLockObject lock(m_conn.Mutex());
   Close0();
-  tvhdebug("demux close");
+  Logger::Log(LogLevel::DEBUG, "demux close");
 }
 
 DemuxPacket *CHTSPDemuxer::Read ( void )
@@ -115,11 +117,11 @@ DemuxPacket *CHTSPDemuxer::Read ( void )
   DemuxPacket *pkt = NULL;
   m_lastUse = time(NULL);
   if (m_pktBuffer.Pop(pkt, 1000)) {
-    tvhtrace("demux read idx :%d pts %lf len %lld",
+    Logger::Log(LogLevel::TRACE, "demux read idx :%d pts %lf len %lld",
              pkt->iStreamId, pkt->pts, (long long)pkt->iSize);
     return pkt;
   }
-  tvhtrace("demux read nothing");
+  Logger::Log(LogLevel::TRACE, "demux read nothing");
   
   return PVR->AllocateDemuxPacket(0);
 }
@@ -127,7 +129,7 @@ DemuxPacket *CHTSPDemuxer::Read ( void )
 void CHTSPDemuxer::Flush ( void )
 {
   DemuxPacket *pkt;
-  tvhtrace("demux flush");
+  Logger::Log(LogLevel::TRACE, "demux flush");
   while (m_pktBuffer.Pop(pkt))
     PVR->FreeDemuxPacket(pkt);
 }
@@ -136,7 +138,7 @@ void CHTSPDemuxer::Trim ( void )
 {
   DemuxPacket *pkt;
 
-  tvhtrace("demux trim");
+  Logger::Log(LogLevel::TRACE, "demux trim");
   /* reduce used buffer space to what is needed for DVDPlayer to resume
    * playback without buffering. This depends on the bitrate, so we don't set
    * this too small. */
@@ -146,7 +148,7 @@ void CHTSPDemuxer::Trim ( void )
 
 void CHTSPDemuxer::Abort ( void )
 {
-  tvhtrace("demux abort");
+  Logger::Log(LogLevel::TRACE, "demux abort");
   CLockObject lock(m_conn.Mutex());
   Abort0();
 }
@@ -163,7 +165,7 @@ bool CHTSPDemuxer::Seek
   /* Wait for time */
   if (!m_seekCond.Wait(m_conn.Mutex(), m_seekTime, Settings::GetInstance().GetResponseTimeout()))
   {
-    tvherror("failed to get subscriptionSeek response");
+    Logger::Log(LogLevel::ERROR, "failed to get subscriptionSeek response");
     return false;
   }
   
@@ -172,7 +174,7 @@ bool CHTSPDemuxer::Seek
 
   /* Store */
   *startpts = TVH_TO_DVD_TIME(m_seekTime);
-  tvhtrace("demux seek startpts = %lf", *startpts);
+  Logger::Log(LogLevel::TRACE, "demux seek startpts = %lf", *startpts);
 
   return true;
 }
@@ -257,7 +259,7 @@ bool CHTSPDemuxer::ProcessMessage ( const char *method, htsmsg_t *m )
   else if (!strcmp("subscriptionSpeed", method))
     ParseSubscriptionSpeed(m);
   else
-    tvhdebug("demux unhandled subscription message [%s]",
+    Logger::Log(LogLevel::DEBUG, "demux unhandled subscription message [%s]",
               method);
 
   return true;
@@ -276,15 +278,15 @@ void CHTSPDemuxer::ParseMuxPacket ( htsmsg_t *m )
   /* Ignore packets while switching channels */
   if (!m_subscription.IsActive())
   {
-    tvhdebug("Ignored mux packet due to channel switch");
+    Logger::Log(LogLevel::DEBUG, "Ignored mux packet due to channel switch");
     return;
   }
   
   /* Validate fields */
   if (htsmsg_get_u32(m, "stream", &idx) ||
       htsmsg_get_bin(m, "payload", &bin, &binlen))
-  { 
-    tvherror("malformed muxpkt: 'stream'/'payload' missing");
+  {
+    Logger::Log(LogLevel::ERROR, "malformed muxpkt: 'stream'/'payload' missing");
     return;
   }
 
@@ -294,7 +296,7 @@ void CHTSPDemuxer::ParseMuxPacket ( htsmsg_t *m )
   /* Drop packets for unknown streams */
   if (-1 == (iStreamId = m_streams.GetStreamId(idx)))
   {
-    tvhdebug("Dropped packet with unknown stream index %i", idx);
+    Logger::Log(LogLevel::DEBUG, "Dropped packet with unknown stream index %i", idx);
     return;
   }
   
@@ -326,7 +328,7 @@ void CHTSPDemuxer::ParseMuxPacket ( htsmsg_t *m )
   if (!type)
     type = '_';
 
-  tvhtrace("demux pkt idx %d:%d type %c pts %lf len %lld",
+  Logger::Log(LogLevel::TRACE, "demux pkt idx %d:%d type %c pts %lf len %lld",
            idx, pkt->iStreamId, type, pkt->pts, (long long)binlen);
 
   /* Store */
@@ -343,7 +345,7 @@ void CHTSPDemuxer::ParseSubscriptionStart ( htsmsg_t *m )
   /* Validate */
   if ((l = htsmsg_get_list(m, "streams")) == NULL)
   {
-    tvherror("malformed subscriptionStart: 'streams' missing");
+    Logger::Log(LogLevel::ERROR, "malformed subscriptionStart: 'streams' missing");
     return;
   }
   m_streamStat.clear();
@@ -365,7 +367,7 @@ void CHTSPDemuxer::ParseSubscriptionStart ( htsmsg_t *m )
     /* Find stream */
     m_streamStat[idx] = 0;
     m_streams.GetStreamData(idx, &stream);
-    tvhdebug("demux subscription start");
+    Logger::Log(LogLevel::DEBUG, "demux subscription start");
     
     CodecDescriptor codecDescriptor = CodecDescriptor::GetCodecByName(type);
     xbmc_codec_t codec = codecDescriptor.Codec();
@@ -417,7 +419,7 @@ void CHTSPDemuxer::ParseSubscriptionStart ( htsmsg_t *m )
            some versions of tvheadend and is here for backward compatibility. */
         if (stream.iWidth == 0 || stream.iHeight == 0)
         {
-          tvhinfo("Ignoring subscriptionStart, stream details missing");
+          Logger::Log(LogLevel::INFO, "Ignoring subscriptionStart, stream details missing");
           return;
         }
         
@@ -432,12 +434,12 @@ void CHTSPDemuxer::ParseSubscriptionStart ( htsmsg_t *m )
       }
         
       streams.push_back(stream);
-      tvhdebug("  id: %d, type %s, codec: %u", idx, type, stream.iCodecId);
+      Logger::Log(LogLevel::DEBUG, "  id: %d, type %s, codec: %u", idx, type, stream.iCodecId);
     }
   }
 
   /* Update streams */
-  tvhdebug("demux stream change");
+  Logger::Log(LogLevel::DEBUG, "demux stream change");
   m_streams.UpdateStreams(streams);
   pkt = PVR->AllocateDemuxPacket(0);
   pkt->iStreamId = DMX_SPECIALID_STREAMCHANGE;
@@ -453,42 +455,42 @@ void CHTSPDemuxer::ParseSourceInfo ( htsmsg_t *m )
   
   /* Ignore */
   if (!m) return;
-  
-  tvhtrace("demux sourceInfo:");
+
+  Logger::Log(LogLevel::TRACE, "demux sourceInfo:");
 
   /* include position in mux name
    * as users might receive multiple satellite positions */
   m_sourceInfo.si_mux.clear();
   if ((str = htsmsg_get_str(m, "satpos")) != NULL)
   {
-    tvhtrace("  satpos : %s", str);
+    Logger::Log(LogLevel::TRACE, "  satpos : %s", str);
     m_sourceInfo.si_mux.append(str);
     m_sourceInfo.si_mux.append(": ");
   }
   if ((str = htsmsg_get_str(m, "mux")) != NULL)
   {
-    tvhtrace("  mux     : %s", str);
+    Logger::Log(LogLevel::TRACE, "  mux     : %s", str);
     m_sourceInfo.si_mux.append(str);
   }
 
   if ((str = htsmsg_get_str(m, "adapter")) != NULL)
   {
-    tvhtrace("  adapter : %s", str);
+    Logger::Log(LogLevel::TRACE, "  adapter : %s", str);
     m_sourceInfo.si_adapter  = str;
   }
   if ((str = htsmsg_get_str(m, "network")) != NULL)
   {
-    tvhtrace("  network : %s", str);
+    Logger::Log(LogLevel::TRACE, "  network : %s", str);
     m_sourceInfo.si_network  = str;
   }
   if ((str = htsmsg_get_str(m, "provider")) != NULL)
   {
-    tvhtrace("  provider : %s", str);
+    Logger::Log(LogLevel::TRACE, "  provider : %s", str);
     m_sourceInfo.si_provider = str;
   }
   if ((str = htsmsg_get_str(m, "service")) != NULL)
   {
-    tvhtrace("  service : %s", str);
+    Logger::Log(LogLevel::TRACE, "  service : %s", str);
     m_sourceInfo.si_service  = str;
   }
 }
@@ -513,30 +515,30 @@ void CHTSPDemuxer::ParseSubscriptionSpeed ( htsmsg_t *m )
 {
   uint32_t u32;
   if (!htsmsg_get_u32(m, "speed", &u32))
-    tvhtrace("recv speed %d", u32);
+    Logger::Log(LogLevel::TRACE, "recv speed %d", u32);
 }
 
 void CHTSPDemuxer::ParseQueueStatus ( htsmsg_t *_unused(m) )
 {
   uint32_t u32;
   map<int,int>::const_iterator it;
-  tvhtrace("stream stats:");
+  Logger::Log(LogLevel::TRACE, "stream stats:");
   for (it = m_streamStat.begin(); it != m_streamStat.end(); ++it)
-    tvhtrace("  idx:%d num:%d", it->first, it->second);
+    Logger::Log(LogLevel::TRACE, "  idx:%d num:%d", it->first, it->second);
 
-  tvhtrace("queue stats:");
+  Logger::Log(LogLevel::TRACE, "queue stats:");
   if (!htsmsg_get_u32(m, "packets", &u32))
-    tvhtrace("  pkts  %d", u32);
+    Logger::Log(LogLevel::TRACE, "  pkts  %d", u32);
   if (!htsmsg_get_u32(m, "bytes", &u32))
-    tvhtrace("  bytes %d", u32);
+    Logger::Log(LogLevel::TRACE, "  bytes %d", u32);
   if (!htsmsg_get_u32(m, "delay", &u32))
-    tvhtrace("  delay %d", u32);
+    Logger::Log(LogLevel::TRACE, "  delay %d", u32);
   if (!htsmsg_get_u32(m, "Idrops", &u32))
-    tvhtrace("  Idrop %d", u32);
+    Logger::Log(LogLevel::TRACE, "  Idrop %d", u32);
   if (!htsmsg_get_u32(m, "Pdrops", &u32))
-    tvhtrace("  Pdrop %d", u32);
+    Logger::Log(LogLevel::TRACE, "  Pdrop %d", u32);
   if (!htsmsg_get_u32(m, "Bdrops", &u32))
-    tvhtrace("  Bdrop %d", u32);
+    Logger::Log(LogLevel::TRACE, "  Bdrop %d", u32);
 }
 
 void CHTSPDemuxer::ParseSignalStatus ( htsmsg_t *m )
@@ -548,34 +550,34 @@ void CHTSPDemuxer::ParseSignalStatus ( htsmsg_t *m )
   m_signalInfo.Clear();
 
   /* Parse */
-  tvhtrace("signalStatus:");
+  Logger::Log(LogLevel::TRACE, "signalStatus:");
   if ((str = htsmsg_get_str(m, "feStatus")) != NULL)
   {
-    tvhtrace("  status : %s", str);
+    Logger::Log(LogLevel::TRACE, "  status : %s", str);
     m_signalInfo.fe_status = str;
   }
   else
   {
-    tvherror("malformed signalStatus: 'feStatus' missing, ignoring");
+    Logger::Log(LogLevel::ERROR, "malformed signalStatus: 'feStatus' missing, ignoring");
   }
   if (!htsmsg_get_u32(m, "feSNR", &u32))
   {
-    tvhtrace("  snr    : %d", u32);
+    Logger::Log(LogLevel::TRACE, "  snr    : %d", u32);
     m_signalInfo.fe_snr    = u32;
   }
   if (!htsmsg_get_u32(m, "feBER", &u32))
   {
-    tvhtrace("  ber    : %d", u32);
+    Logger::Log(LogLevel::TRACE, "  ber    : %d", u32);
     m_signalInfo.fe_ber    = u32;
   }
   if (!htsmsg_get_u32(m, "feUNC", &u32))
   {
-    tvhtrace("  unc    : %d", u32);
+    Logger::Log(LogLevel::TRACE, "  unc    : %d", u32);
     m_signalInfo.fe_unc    = u32;
   }
   if (!htsmsg_get_u32(m, "feSignal", &u32))
   {
-    tvhtrace("  signal    : %d", u32);
+    Logger::Log(LogLevel::TRACE, "  signal    : %d", u32);
     m_signalInfo.fe_signal = u32;
   }
 }
@@ -586,33 +588,33 @@ void CHTSPDemuxer::ParseTimeshiftStatus ( htsmsg_t *m )
   int64_t s64;
 
   /* Parse */
-  tvhtrace("timeshiftStatus:");
+  Logger::Log(LogLevel::TRACE, "timeshiftStatus:");
   if (!htsmsg_get_u32(m, "full", &u32))
   {
-    tvhtrace("  full  : %d", u32);
+    Logger::Log(LogLevel::TRACE, "  full  : %d", u32);
     m_timeshiftStatus.full = (bool)u32;
   }
   else
   {
-    tvherror("malformed timeshiftStatus: 'full' missing, ignoring");
+    Logger::Log(LogLevel::ERROR, "malformed timeshiftStatus: 'full' missing, ignoring");
   }
   if (!htsmsg_get_s64(m, "shift", &s64))
   {
-    tvhtrace("  shift : %lld", s64);
+    Logger::Log(LogLevel::TRACE, "  shift : %lld", s64);
     m_timeshiftStatus.shift = s64;
   }
   else
   {
-    tvherror("malformed timeshiftStatus: 'shift' missing, ignoring");
+    Logger::Log(LogLevel::ERROR, "malformed timeshiftStatus: 'shift' missing, ignoring");
   }
   if (!htsmsg_get_s64(m, "start", &s64))
   {
-    tvhtrace("  start : %lld", s64);
+    Logger::Log(LogLevel::TRACE, "  start : %lld", s64);
     m_timeshiftStatus.start = s64;
   }
   if (!htsmsg_get_s64(m, "end", &s64))
   {
-    tvhtrace("  end   : %lld", s64);
+    Logger::Log(LogLevel::TRACE, "  end   : %lld", s64);
     m_timeshiftStatus.end = s64;
   }
 }
diff --git a/src/HTSPVFS.cpp b/src/HTSPVFS.cpp
index 2cc1590..0c482f8 100644
--- a/src/HTSPVFS.cpp
+++ b/src/HTSPVFS.cpp
@@ -21,6 +21,7 @@
 
 #include "platform/threads/mutex.h"
 #include "platform/util/StringUtils.h"
+#include "tvheadend/utilities/Logger.h"
 
 extern "C" {
 #include "libhts/htsmsg_binary.h"
@@ -30,6 +31,7 @@ extern "C" {
 
 using namespace std;
 using namespace PLATFORM;
+using namespace tvheadend::utilities;
 
 /*
 * VFS handler
@@ -47,11 +49,11 @@ void CHTSPVFS::Connected ( void )
 {
   /* Re-open */
   if (m_fileId != 0)
-  { 
-    tvhdebug("vfs re-open file");
+  {
+    Logger::Log(LogLevel::DEBUG, "vfs re-open file");
     if (!SendFileOpen(true) || !SendFileSeek(m_offset, SEEK_SET, true))
     {
-      tvherror("vfs failed to re-open file");
+      Logger::Log(LogLevel::ERROR, "vfs failed to re-open file");
       Close();
     }
   }
@@ -72,7 +74,7 @@ bool CHTSPVFS::Open ( const PVR_RECORDING &rec )
   /* Send open */
   if (!SendFileOpen())
   {
-    tvherror("vfs failed to open file");
+    Logger::Log(LogLevel::ERROR, "vfs failed to open file");
     return false;
   }
 
@@ -131,7 +133,7 @@ long long CHTSPVFS::Size ( void )
   m = htsmsg_create_map();
   htsmsg_add_u32(m, "id", m_fileId);
 
-  tvhtrace("vfs stat id=%d", m_fileId);
+  Logger::Log(LogLevel::TRACE, "vfs stat id=%d", m_fileId);
   
   /* Send */
   {
@@ -146,7 +148,7 @@ long long CHTSPVFS::Size ( void )
   if (htsmsg_get_s64(m, "size", &ret))
     ret = -1;
   else
-    tvhtrace("vfs stat size=%lld", (long long)ret);
+    Logger::Log(LogLevel::TRACE, "vfs stat size=%lld", (long long)ret);
 
   htsmsg_destroy(m);
 
@@ -165,7 +167,7 @@ bool CHTSPVFS::SendFileOpen ( bool force )
   m = htsmsg_create_map();
   htsmsg_add_str(m, "file", m_path.c_str());
 
-  tvhdebug("vfs open file=%s", m_path.c_str());
+  Logger::Log(LogLevel::DEBUG, "vfs open file=%s", m_path.c_str());
 
   /* Send */
   {
@@ -183,11 +185,11 @@ bool CHTSPVFS::SendFileOpen ( bool force )
   /* Get ID */
   if (htsmsg_get_u32(m, "id", &m_fileId))
   {
-    tvherror("malformed fileOpen response: 'id' missing");
+    Logger::Log(LogLevel::ERROR, "malformed fileOpen response: 'id' missing");
     m_fileId = 0;
   }
   else
-    tvhtrace("vfs opened id=%d", m_fileId);
+    Logger::Log(LogLevel::TRACE, "vfs opened id=%d", m_fileId);
 
   htsmsg_destroy(m);
   return m_fileId > 0;
@@ -201,7 +203,7 @@ void CHTSPVFS::SendFileClose ( void )
   m = htsmsg_create_map();
   htsmsg_add_u32(m, "id", m_fileId);
 
-  tvhdebug("vfs close id=%d", m_fileId);
+  Logger::Log(LogLevel::DEBUG, "vfs close id=%d", m_fileId);
   
   /* Send */
   {
@@ -227,7 +229,7 @@ long long CHTSPVFS::SendFileSeek ( int64_t pos, int whence, bool force )
   else if (whence == SEEK_END)
     htsmsg_add_str(m, "whence", "SEEK_END");
 
-  tvhtrace("vfs seek id=%d whence=%d pos=%lld",
+  Logger::Log(LogLevel::TRACE, "vfs seek id=%d whence=%d pos=%lld",
            m_fileId, whence, (long long)pos);
 
   /* Send */
@@ -242,7 +244,7 @@ long long CHTSPVFS::SendFileSeek ( int64_t pos, int whence, bool force )
 
   if (m == NULL)
   {
-    tvherror("vfs fileSeek failed");
+    Logger::Log(LogLevel::ERROR, "vfs fileSeek failed");
     return -1;
   }
 
@@ -250,13 +252,13 @@ long long CHTSPVFS::SendFileSeek ( int64_t pos, int whence, bool force )
   if (htsmsg_get_s64(m, "offset", &ret))
   {
     ret = -1;
-    tvherror("vfs fileSeek response: 'offset' missing'");
+    Logger::Log(LogLevel::ERROR, "vfs fileSeek response: 'offset' missing'");
 
   /* Update */
   }
   else
   {
-    tvhtrace("vfs seek offset=%lld", (long long)ret);
+    Logger::Log(LogLevel::TRACE, "vfs seek offset=%lld", (long long)ret);
     m_offset = ret;
   }
 
@@ -277,7 +279,7 @@ ssize_t CHTSPVFS::SendFileRead(unsigned char *buf, unsigned int len)
   htsmsg_add_u32(m, "id", m_fileId);
   htsmsg_add_s64(m, "size", len);
 
-  tvhtrace("vfs read id=%d size=%d",
+  Logger::Log(LogLevel::TRACE, "vfs read id=%d size=%d",
     m_fileId, len);
 
   /* Send */
@@ -288,14 +290,14 @@ ssize_t CHTSPVFS::SendFileRead(unsigned char *buf, unsigned int len)
 
   if (m == NULL)
   {
-    tvherror("vfs fileRead failed");
+    Logger::Log(LogLevel::ERROR, "vfs fileRead failed");
     return -1;
   }
 
   /* Get Data */
   if (htsmsg_get_bin(m, "data", &buffer, reinterpret_cast<size_t *>(&read)))
   {
-    tvherror("malformed fileRead response: 'data' missing");
+    Logger::Log(LogLevel::ERROR, "malformed fileRead response: 'data' missing");
     read = -1;
 
   /* Store */
diff --git a/src/TimeRecordings.cpp b/src/TimeRecordings.cpp
index 025ca3c..ded8ba4 100644
--- a/src/TimeRecordings.cpp
+++ b/src/TimeRecordings.cpp
@@ -23,10 +23,12 @@
 
 #include "Tvheadend.h"
 #include "tvheadend/utilities/Utilities.h"
+#include "tvheadend/utilities/Logger.h"
 
 using namespace PLATFORM;
 using namespace tvheadend;
 using namespace tvheadend::entity;
+using namespace tvheadend::utilities;
 
 TimeRecordings::TimeRecordings(CHTSPConnection &conn) :
   m_conn(conn)
@@ -107,7 +109,7 @@ const unsigned int TimeRecordings::GetTimerIntIdFromStringId(const std::string &
     if (tit->second.GetStringId() == strId)
       return tit->second.GetId();
   }
-  tvherror("Timerec: Unable to obtain int id for string id %s", strId.c_str());
+  Logger::Log(LogLevel::ERROR, "Timerec: Unable to obtain int id for string id %s", strId.c_str());
   return 0;
 }
 
@@ -155,7 +157,7 @@ PVR_ERROR TimeRecordings::SendTimerecAdd(const PVR_TIMER &timer)
   /* Check for error */
   if (htsmsg_get_u32(m, "success", &u32))
   {
-    tvherror("malformed addTimerecEntry response: 'success' missing");
+    Logger::Log(LogLevel::ERROR, "malformed addTimerecEntry response: 'success' missing");
     u32 = PVR_ERROR_FAILED;
   }
   htsmsg_destroy(m);
@@ -204,7 +206,7 @@ PVR_ERROR TimeRecordings::SendTimerecDelete(const PVR_TIMER &timer)
   /* Check for error */
   if (htsmsg_get_u32(m, "success", &u32))
   {
-    tvherror("malformed deleteTimerecEntry response: 'success' missing");
+    Logger::Log(LogLevel::ERROR, "malformed deleteTimerecEntry response: 'success' missing");
   }
   htsmsg_destroy(m);
 
@@ -220,7 +222,7 @@ bool TimeRecordings::ParseTimerecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   /* Validate/set mandatory fields */
   if ((str = htsmsg_get_str(msg, "id")) == NULL)
   {
-    tvherror("malformed timerecEntryAdd/timerecEntryUpdate: 'id' missing");
+    Logger::Log(LogLevel::ERROR, "malformed timerecEntryAdd/timerecEntryUpdate: 'id' missing");
     return false;
   }
 
@@ -237,7 +239,7 @@ bool TimeRecordings::ParseTimerecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd)
   {
-    tvherror("malformed timerecEntryAdd: 'enabled' missing");
+    Logger::Log(LogLevel::ERROR, "malformed timerecEntryAdd: 'enabled' missing");
     return false;
   }
 
@@ -247,7 +249,7 @@ bool TimeRecordings::ParseTimerecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd)
   {
-    tvherror("malformed timerecEntryAdd: 'daysOfWeek' missing");
+    Logger::Log(LogLevel::ERROR, "malformed timerecEntryAdd: 'daysOfWeek' missing");
     return false;
   }
 
@@ -257,7 +259,7 @@ bool TimeRecordings::ParseTimerecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd)
   {
-    tvherror("malformed timerecEntryAdd: 'retention' missing");
+    Logger::Log(LogLevel::ERROR, "malformed timerecEntryAdd: 'retention' missing");
     return false;
   }
 
@@ -267,7 +269,7 @@ bool TimeRecordings::ParseTimerecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd && (m_conn.GetProtocol() >= 24))
   {
-    tvherror("malformed timerecEntryAdd: 'removal' missing");
+    Logger::Log(LogLevel::ERROR, "malformed timerecEntryAdd: 'removal' missing");
     return false;
   }
 
@@ -277,7 +279,7 @@ bool TimeRecordings::ParseTimerecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd)
   {
-    tvherror("malformed timerecEntryAdd: 'priority' missing");
+    Logger::Log(LogLevel::ERROR, "malformed timerecEntryAdd: 'priority' missing");
     return false;
   }
 
@@ -287,7 +289,7 @@ bool TimeRecordings::ParseTimerecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd)
   {
-    tvherror("malformed timerecEntryAdd: 'start' missing");
+    Logger::Log(LogLevel::ERROR, "malformed timerecEntryAdd: 'start' missing");
     return false;
   }
 
@@ -297,7 +299,7 @@ bool TimeRecordings::ParseTimerecAddOrUpdate(htsmsg_t *msg, bool bAdd)
   }
   else if (bAdd)
   {
-    tvherror("malformed timerecEntryAdd: 'stop' missing");
+    Logger::Log(LogLevel::ERROR, "malformed timerecEntryAdd: 'stop' missing");
     return false;
   }
 
@@ -342,10 +344,10 @@ bool TimeRecordings::ParseTimerecDelete(htsmsg_t *msg)
   /* Validate/set mandatory fields */
   if ((id = htsmsg_get_str(msg, "id")) == NULL)
   {
-    tvherror("malformed timerecEntryDelete: 'id' missing");
+    Logger::Log(LogLevel::ERROR, "malformed timerecEntryDelete: 'id' missing");
     return false;
   }
-  tvhtrace("delete timerec entry %s", id);
+  Logger::Log(LogLevel::TRACE, "delete timerec entry %s", id);
 
   /* Erase */
   m_timeRecordings.erase(std::string(id));
diff --git a/src/Tvheadend.cpp b/src/Tvheadend.cpp
index 6aeff98..346f86a 100644
--- a/src/Tvheadend.cpp
+++ b/src/Tvheadend.cpp
@@ -27,12 +27,14 @@
 
 #include "Tvheadend.h"
 #include "tvheadend/utilities/Utilities.h"
+#include "tvheadend/utilities/Logger.h"
 
 using namespace std;
 using namespace ADDON;
 using namespace PLATFORM;
 using namespace tvheadend;
 using namespace tvheadend::entity;
+using namespace tvheadend::utilities;
 
 CTvheadend::CTvheadend()
   : m_streamchange(false), m_vfs(m_conn),
@@ -90,7 +92,7 @@ PVR_ERROR CTvheadend::GetDriveSpace ( long long *total, long long *used )
 
 error:
   htsmsg_destroy(m);
-  tvherror("malformed getDiskSpace response: 'totaldiskspace'/'freediskspace' missing");
+  Logger::Log(LogLevel::ERROR, "malformed getDiskSpace response: 'totaldiskspace'/'freediskspace' missing");
   return PVR_ERROR_SERVER_ERROR;
 }
 
@@ -129,7 +131,7 @@ void CTvheadend::QueryAvailableProfiles()
 
   if ((l = htsmsg_get_list(m, "profiles")) == NULL)
   {
-    tvherror("malformed getProfiles: 'profiles' missing");
+    Logger::Log(LogLevel::ERROR, "malformed getProfiles: 'profiles' missing");
     htsmsg_destroy(m);
     return;
   }
@@ -147,7 +149,7 @@ void CTvheadend::QueryAvailableProfiles()
     if ((str = htsmsg_get_str(&f->hmf_msg, "comment")) != NULL)
       profile.SetComment(str);
 
-    tvhdebug("profile name: %s, comment: %s added",
+    Logger::Log(LogLevel::DEBUG, "profile name: %s, comment: %s added",
              profile.GetName().c_str(), profile.GetComment().c_str());
 
     m_profiles.push_back(profile);
@@ -357,7 +359,7 @@ PVR_ERROR CTvheadend::SendDvrDelete ( uint32_t id, const char *method )
   /* Check for error */
   if (htsmsg_get_u32(m, "success", &u32))
   {
-    tvherror("malformed deleteDvrEntry/cancelDvrEntry response: 'success' missing");
+    Logger::Log(LogLevel::ERROR, "malformed deleteDvrEntry/cancelDvrEntry response: 'success' missing");
     u32 = PVR_ERROR_FAILED;
   }
   htsmsg_destroy(m);
@@ -381,7 +383,7 @@ PVR_ERROR CTvheadend::SendDvrUpdate( htsmsg_t* m )
   /* Check for error */
   if (htsmsg_get_u32(m, "success", &u32))
   {
-    tvherror("malformed updateDvrEntry response: 'success' missing");
+    Logger::Log(LogLevel::ERROR, "malformed updateDvrEntry response: 'success' missing");
     u32 = PVR_ERROR_FAILED;
   }
   htsmsg_destroy(m);
@@ -503,8 +505,8 @@ PVR_ERROR CTvheadend::GetRecordingEdl
   /* Build request */
   htsmsg_t *m = htsmsg_create_map();
   htsmsg_add_u32(m, "id", atoi(rec.strRecordingId));
-  
-  tvhdebug("dvr get cutpoints id=%s", rec.strRecordingId);
+
+  Logger::Log(LogLevel::DEBUG, "dvr get cutpoints id=%s", rec.strRecordingId);
 
   /* Send and Wait */
   {
@@ -540,7 +542,7 @@ PVR_ERROR CTvheadend::GetRecordingEdl
         htsmsg_get_u32(&f->hmf_msg, "end",   &end)   ||
         htsmsg_get_u32(&f->hmf_msg, "type",  &type))
     {
-      tvherror("malformed getDvrCutpoints response: invalid EDL entry, will ignore");
+      Logger::Log(LogLevel::ERROR, "malformed getDvrCutpoints response: invalid EDL entry, will ignore");
       continue;
     }
 
@@ -564,8 +566,8 @@ PVR_ERROR CTvheadend::GetRecordingEdl
         break;
     }
     idx++;
-      
-    tvhdebug("edl start:%d end:%d action:%d", start, end, type);
+
+    Logger::Log(LogLevel::DEBUG, "edl start:%d end:%d action:%d", start, end, type);
   }
   
   *num = idx;
@@ -1016,7 +1018,7 @@ PVR_ERROR CTvheadend::AddTimer ( const PVR_TIMER &timer )
     /* Check for error */
     if (htsmsg_get_u32(m, "success", &u32))
     {
-      tvherror("malformed addDvrEntry response: 'success' missing");
+      Logger::Log(LogLevel::ERROR, "malformed addDvrEntry response: 'success' missing");
       u32 = PVR_ERROR_FAILED;
     }
     htsmsg_destroy(m);
@@ -1036,7 +1038,7 @@ PVR_ERROR CTvheadend::AddTimer ( const PVR_TIMER &timer )
   else
   {
     /* unknown timer */
-    tvherror("unknown timer type");
+    Logger::Log(LogLevel::ERROR, "unknown timer type");
     return PVR_ERROR_INVALID_PARAMETERS;
   }
 }
@@ -1072,14 +1074,14 @@ PVR_ERROR CTvheadend::DeleteTimer
     }
     else
     {
-      tvherror("timer is read-only");
+      Logger::Log(LogLevel::ERROR, "timer is read-only");
       return PVR_ERROR_INVALID_PARAMETERS;
     }
   }
   else
   {
     /* unknown timer */
-    tvherror("unknown timer type");
+    Logger::Log(LogLevel::ERROR, "unknown timer type");
     return PVR_ERROR_INVALID_PARAMETERS;
   }
 }
@@ -1105,13 +1107,13 @@ PVR_ERROR CTvheadend::UpdateTimer ( const PVR_TIMER &timer )
       const auto &it = m_recordings.find(timer.iClientIndex);
       if (it == m_recordings.end())
       {
-        tvherror("cannot find the timer to update");
+        Logger::Log(LogLevel::ERROR, "cannot find the timer to update");
         return PVR_ERROR_INVALID_PARAMETERS;
       }
 
       if (it->second.GetChannel() != static_cast<uint32_t>(timer.iClientChannelUid))
       {
-        tvherror("updating channels of one-shot timers not supported by HTSP v%d", m_conn.GetProtocol());
+        Logger::Log(LogLevel::ERROR, "updating channels of one-shot timers not supported by HTSP v%d", m_conn.GetProtocol());
         return PVR_ERROR_NOT_IMPLEMENTED;
       }
     }
@@ -1170,13 +1172,13 @@ PVR_ERROR CTvheadend::UpdateTimer ( const PVR_TIMER &timer )
       }
     }
 
-    tvherror("timer is read-only");
+    Logger::Log(LogLevel::ERROR, "timer is read-only");
     return PVR_ERROR_INVALID_PARAMETERS;
   }
   else
   {
     /* unknown timer */
-    tvherror("unknown timer type");
+    Logger::Log(LogLevel::ERROR, "unknown timer type");
     return PVR_ERROR_INVALID_PARAMETERS;
   }
 }
@@ -1229,7 +1231,7 @@ PVR_ERROR CTvheadend::GetEpg
   htsmsg_field_t *f;
   int n = 0;
 
-  tvhtrace("get epg channel %d start %ld stop %ld", chn.iUniqueId,
+  Logger::Log(LogLevel::TRACE, "get epg channel %d start %ld stop %ld", chn.iUniqueId,
            (long long)start, (long long)end);
 
   /* Async transfer */
@@ -1275,7 +1277,7 @@ PVR_ERROR CTvheadend::GetEpg
     if (!(l = htsmsg_get_list(msg, "events")))
     {
       htsmsg_destroy(msg);
-      tvherror("malformed getEvents response: 'events' missing");
+      Logger::Log(LogLevel::ERROR, "malformed getEvents response: 'events' missing");
       return PVR_ERROR_SERVER_ERROR;
     }
     HTSMSG_FOREACH(f, l)
@@ -1294,7 +1296,7 @@ PVR_ERROR CTvheadend::GetEpg
     htsmsg_destroy(msg);
   }
 
-  tvhtrace("get epg channel %d events %d", chn.iUniqueId, n);
+  Logger::Log(LogLevel::TRACE, "get epg channel %d events %d", chn.iUniqueId, n);
 
   return PVR_ERROR_NO_ERROR;
 }
@@ -1342,7 +1344,7 @@ bool CTvheadend::Connected ( void )
     return false;
 
   htsmsg_destroy(msg);
-  tvhdebug("async updates requested");
+  Logger::Log(LogLevel::DEBUG, "async updates requested");
 
   return true;
 }
@@ -1462,8 +1464,8 @@ void* CTvheadend::Process ( void )
         SyncCompleted();
 
       /* Unknown */
-      else  
-        tvhdebug("unhandled message [%s]", method);
+      else
+        Logger::Log(LogLevel::DEBUG, "unhandled message [%s]", method);
 
       /* make a copy of events list to process it without lock. */
       eventsCopy = m_events;
@@ -1620,7 +1622,7 @@ void CTvheadend::ParseTagAddOrUpdate ( htsmsg_t *msg, bool bAdd )
   /* Validate */
   if (htsmsg_get_u32(msg, "tagId", &u32))
   {
-    tvherror("malformed tagAdd/tagUpdate: 'tagId' missing");
+    Logger::Log(LogLevel::ERROR, "malformed tagAdd/tagUpdate: 'tagId' missing");
     return;
   }
 
@@ -1641,7 +1643,7 @@ void CTvheadend::ParseTagAddOrUpdate ( htsmsg_t *msg, bool bAdd )
     tag.SetName(str);
   else if (bAdd)
   {
-    tvherror("malformed tagAdd: 'tagName' missing");
+    Logger::Log(LogLevel::ERROR, "malformed tagAdd: 'tagName' missing");
     return;
   }
 
@@ -1664,7 +1666,8 @@ void CTvheadend::ParseTagAddOrUpdate ( htsmsg_t *msg, bool bAdd )
   if (existingTag != tag)
   {
     existingTag = tag;
-    tvhdebug("tag updated id:%u, name:%s",
+
+    Logger::Log(LogLevel::DEBUG, "tag updated id:%u, name:%s",
               existingTag.GetId(), existingTag.GetName().c_str());
     if (m_asyncState.GetState() > ASYNC_CHN)
       TriggerChannelGroupsUpdate();
@@ -1678,10 +1681,10 @@ void CTvheadend::ParseTagDelete ( htsmsg_t *msg )
   /* Validate */
   if (htsmsg_get_u32(msg, "tagId", &u32))
   {
-    tvherror("malformed tagDelete: 'tagId' missing");
+    Logger::Log(LogLevel::ERROR, "malformed tagDelete: 'tagId' missing");
     return;
   }
-  tvhdebug("delete tag %u", u32);
+  Logger::Log(LogLevel::DEBUG, "delete tag %u", u32);
   
   /* Erase */
   m_tags.erase(u32);
@@ -1697,7 +1700,7 @@ void CTvheadend::ParseChannelAddOrUpdate ( htsmsg_t *msg, bool bAdd )
   /* Validate */
   if (htsmsg_get_u32(msg, "channelId", &u32))
   {
-    tvherror("malformed channelAdd/channelUpdate: 'channelId' missing");
+    Logger::Log(LogLevel::ERROR, "malformed channelAdd/channelUpdate: 'channelId' missing");
     return;
   }
 
@@ -1712,7 +1715,7 @@ void CTvheadend::ParseChannelAddOrUpdate ( htsmsg_t *msg, bool bAdd )
     channel.SetName(str);
   else if (bAdd)
   {
-    tvherror("malformed channelAdd: 'channelName' missing");
+    Logger::Log(LogLevel::ERROR, "malformed channelAdd: 'channelName' missing");
     return;
   }
 
@@ -1725,7 +1728,7 @@ void CTvheadend::ParseChannelAddOrUpdate ( htsmsg_t *msg, bool bAdd )
   }
   else if (bAdd)
   {
-    tvherror("malformed channelAdd: 'channelNumber' missing");
+    Logger::Log(LogLevel::ERROR, "malformed channelAdd: 'channelNumber' missing");
     return;
   }
   else if (!channel.GetNum())
@@ -1769,7 +1772,7 @@ void CTvheadend::ParseChannelAddOrUpdate ( htsmsg_t *msg, bool bAdd )
   /* Update Kodi */
   if (channel != comparison)
   {
-    tvhdebug("channel %s id:%u, name:%s",
+    Logger::Log(LogLevel::DEBUG, "channel %s id:%u, name:%s",
              (bAdd ? "added" : "updated"), channel.GetId(), channel.GetName().c_str());
 
     if (bAdd)
@@ -1789,10 +1792,10 @@ void CTvheadend::ParseChannelDelete ( htsmsg_t *msg )
   /* Validate */
   if (htsmsg_get_u32(msg, "channelId", &u32))
   {
-    tvherror("malformed channelDelete: 'channelId' missing");
+    Logger::Log(LogLevel::ERROR, "malformed channelDelete: 'channelId' missing");
     return;
   }
-  tvhdebug("delete channel %u", u32);
+  Logger::Log(LogLevel::DEBUG, "delete channel %u", u32);
   
   /* Erase */
   m_channels.erase(u32);
@@ -1812,25 +1815,25 @@ void CTvheadend::ParseRecordingAddOrUpdate ( htsmsg_t *msg, bool bAdd )
   /* Validate */
   if (htsmsg_get_u32(msg, "id", &id))
   {
-    tvherror("malformed dvrEntryAdd/dvrEntryUpdate: 'id' missing");
+    Logger::Log(LogLevel::ERROR, "malformed dvrEntryAdd/dvrEntryUpdate: 'id' missing");
     return;
   }
 
   if (htsmsg_get_s64(msg, "start", &start) && bAdd)
   {
-    tvherror("malformed dvrEntryAdd: 'start' missing");
+    Logger::Log(LogLevel::ERROR, "malformed dvrEntryAdd: 'start' missing");
     return;
   }
 
   if (htsmsg_get_s64(msg, "stop", &stop) && bAdd)
   {
-    tvherror("malformed dvrEntryAdd: 'stop' missing");
+    Logger::Log(LogLevel::ERROR, "malformed dvrEntryAdd: 'stop' missing");
     return;
   }
 
   if (((state = htsmsg_get_str(msg, "state")) == NULL) && bAdd)
   {
-    tvherror("malformed dvrEntryAdd: 'state' missing");
+    Logger::Log(LogLevel::ERROR, "malformed dvrEntryAdd: 'state' missing");
     return;
   }
 
@@ -1850,7 +1853,7 @@ void CTvheadend::ParseRecordingAddOrUpdate ( htsmsg_t *msg, bool bAdd )
     rec.SetStartExtra(startExtra);
   else if (bAdd)
   {
-    tvherror("malformed dvrEntryAdd: 'startExtra' missing");
+    Logger::Log(LogLevel::ERROR, "malformed dvrEntryAdd: 'startExtra' missing");
     return;
   }
 
@@ -1858,7 +1861,7 @@ void CTvheadend::ParseRecordingAddOrUpdate ( htsmsg_t *msg, bool bAdd )
     rec.SetStopExtra(stopExtra);
   else if (bAdd)
   {
-    tvherror("malformed dvrEntryAdd: 'stopExtra' missing");
+    Logger::Log(LogLevel::ERROR, "malformed dvrEntryAdd: 'stopExtra' missing");
     return;
   }
 
@@ -1866,7 +1869,7 @@ void CTvheadend::ParseRecordingAddOrUpdate ( htsmsg_t *msg, bool bAdd )
     rec.SetRetention(retention);
   else if (bAdd)
   {
-    tvherror("malformed dvrEntryAdd: 'retention' missing");
+    Logger::Log(LogLevel::ERROR, "malformed dvrEntryAdd: 'retention' missing");
     return;
   }
 
@@ -1874,7 +1877,7 @@ void CTvheadend::ParseRecordingAddOrUpdate ( htsmsg_t *msg, bool bAdd )
     rec.SetRemoval(removal);
   else if (bAdd && (m_conn.GetProtocol() >= 24))
   {
-    tvherror("malformed dvrEntryAdd: 'removal' missing");
+    Logger::Log(LogLevel::ERROR, "malformed dvrEntryAdd: 'removal' missing");
     return;
   }
 
@@ -1890,13 +1893,13 @@ void CTvheadend::ParseRecordingAddOrUpdate ( htsmsg_t *msg, bool bAdd )
         rec.SetPriority(priority);
         break;
       default:
-        tvherror("malformed dvrEntryAdd/dvrEntryUpdate: unknown priority value %d", priority);
+        Logger::Log(LogLevel::ERROR, "malformed dvrEntryAdd/dvrEntryUpdate: unknown priority value %d", priority);
         return;
     }
   }
   else if (bAdd)
   {
-    tvherror("malformed dvrEntryAdd: 'priority' missing");
+    Logger::Log(LogLevel::ERROR, "malformed dvrEntryAdd: 'priority' missing");
     return;
   }
 
@@ -1964,8 +1967,8 @@ void CTvheadend::ParseRecordingAddOrUpdate ( htsmsg_t *msg, bool bAdd )
   if (rec != comparison)
   {
     std::string error = rec.GetError().empty() ? "none" : rec.GetError();
-    
-    tvhdebug("recording id:%d, state:%s, title:%s, desc:%s, error:%s",
+
+    Logger::Log(LogLevel::DEBUG, "recording id:%d, state:%s, title:%s, desc:%s, error:%s",
              rec.GetId(), state, rec.GetTitle().c_str(), rec.GetDescription().c_str(),
              error.c_str());
 
@@ -1984,10 +1987,10 @@ void CTvheadend::ParseRecordingDelete ( htsmsg_t *msg )
   /* Validate */
   if (htsmsg_get_u32(msg, "id", &u32))
   {
-    tvherror("malformed dvrEntryDelete: 'id' missing");
+    Logger::Log(LogLevel::ERROR, "malformed dvrEntryDelete: 'id' missing");
     return;
   }
-  tvhdebug("delete recording %u", u32);
+  Logger::Log(LogLevel::DEBUG, "delete recording %u", u32);
   
   /* Erase */
   m_recordings.erase(u32);
@@ -2009,25 +2012,25 @@ bool CTvheadend::ParseEvent ( htsmsg_t *msg, bool bAdd, Event &evt )
   /* Validate */
   if (htsmsg_get_u32(msg, "eventId", &id))
   {
-    tvherror("malformed eventAdd/eventUpdate: 'eventId' missing");
+    Logger::Log(LogLevel::ERROR, "malformed eventAdd/eventUpdate: 'eventId' missing");
     return false;
   }
 
   if (htsmsg_get_u32(msg, "channelId", &channel) && bAdd)
   {
-    tvherror("malformed eventAdd: 'channelId' missing");
+    Logger::Log(LogLevel::ERROR, "malformed eventAdd: 'channelId' missing");
     return false;
   }
 
   if (htsmsg_get_s64(msg, "start", &start) && bAdd)
   {
-    tvherror("malformed eventAdd: 'start' missing");
+    Logger::Log(LogLevel::ERROR, "malformed eventAdd: 'start' missing");
     return false;
   }
 
   if (htsmsg_get_s64(msg, "stop", &stop) && bAdd)
   {
-    tvherror("malformed eventAdd: 'stop' missing");
+    Logger::Log(LogLevel::ERROR, "malformed eventAdd: 'stop' missing");
     return false;
   }
 
@@ -2102,7 +2105,7 @@ void CTvheadend::ParseEventAddOrUpdate ( htsmsg_t *msg, bool bAdd )
   /* Update */
   if (evt != comparison)
   {
-    tvhtrace("event id:%d channel:%d start:%d stop:%d title:%s desc:%s",
+    Logger::Log(LogLevel::TRACE, "event id:%d channel:%d start:%d stop:%d title:%s desc:%s",
              evt.GetId(), evt.GetChannel(), (int)evt.GetStart(), (int)evt.GetStop(),
              evt.GetTitle().c_str(), evt.GetDesc().c_str());
 
@@ -2118,10 +2121,10 @@ void CTvheadend::ParseEventDelete ( htsmsg_t *msg )
   /* Validate */
   if (htsmsg_get_u32(msg, "eventId", &u32))
   {
-    tvherror("malformed eventDelete: 'eventId' missing");
+    Logger::Log(LogLevel::ERROR, "malformed eventDelete: 'eventId' missing");
     return;
   }
-  tvhtrace("delete event %u", u32);
+  Logger::Log(LogLevel::TRACE, "delete event %u", u32);
   
   /* Erase */
   for (auto &entry : m_schedules)
@@ -2134,7 +2137,7 @@ void CTvheadend::ParseEventDelete ( htsmsg_t *msg )
 
     if (eit != events.end())
     {
-      tvhtrace("deleted event %d from channel %d", u32, schedule.GetId());
+      Logger::Log(LogLevel::TRACE, "deleted event %d from channel %d", u32, schedule.GetId());
       events.erase(eit);
       TriggerEpgUpdate(schedule.GetId());
       return;
@@ -2166,7 +2169,7 @@ void CTvheadend::TuneOnOldest( uint32_t channelId )
   }
   if (oldest)
   {
-    tvhtrace("pretuning channel %u on subscription %u",
+    Logger::Log(LogLevel::TRACE, "pretuning channel %u on subscription %u",
              m_channels[channelId].GetNum(), oldest->GetSubscriptionId());
     oldest->Open(channelId, SUBSCRIPTION_WEIGHT_PRETUNING);
   }
@@ -2206,7 +2209,7 @@ bool CTvheadend::DemuxOpen( const PVR_CHANNEL &chn )
   {
     if (dmx != m_dmx_active && dmx->GetChannelId() == chn.iUniqueId)
     {
-      tvhtrace("retuning channel %u on subscription %u",
+      Logger::Log(LogLevel::TRACE, "retuning channel %u on subscription %u",
                m_channels[chn.iUniqueId].GetNum(), dmx->GetSubscriptionId());
 
       /* Lower the priority on the current subscrption */
@@ -2227,7 +2230,7 @@ bool CTvheadend::DemuxOpen( const PVR_CHANNEL &chn )
 
   /* If we don't have an existing subscription for the channel we create one
    * on the oldest demuxer */
-  tvhtrace("tuning channel %u on subscription %u",
+  Logger::Log(LogLevel::TRACE, "tuning channel %u on subscription %u",
            m_channels[chn.iUniqueId].GetNum(), oldest->GetSubscriptionId());
 
   prevId = m_dmx_active->GetChannelId();
@@ -2266,7 +2269,7 @@ DemuxPacket* CTvheadend::DemuxRead ( void )
       if (dmx->GetChannelId() && Settings::GetInstance().GetPreTunerCloseDelay() &&
           dmx->GetLastUse() + Settings::GetInstance().GetPreTunerCloseDelay() < time(NULL))
       {
-        tvhtrace("untuning channel %u on subscription %u",
+        Logger::Log(LogLevel::TRACE, "untuning channel %u on subscription %u",
                  m_channels[dmx->GetChannelId()].GetNum(), dmx->GetSubscriptionId());
         dmx->Close();
       }
diff --git a/src/Tvheadend.h b/src/Tvheadend.h
index 9587b61..a73a7fc 100644
--- a/src/Tvheadend.h
+++ b/src/Tvheadend.h
@@ -78,24 +78,6 @@ extern "C" {
 #define INVALID_SEEKTIME           (-1)
 
 /*
- * Log wrappers
- */
-#define tvhdebug(...) tvhlog(ADDON::LOG_DEBUG, ##__VA_ARGS__)
-#define tvhinfo(...)  tvhlog(ADDON::LOG_INFO,  ##__VA_ARGS__)
-#define tvherror(...) tvhlog(ADDON::LOG_ERROR, ##__VA_ARGS__)
-#define tvhtrace(...) if (tvheadend::Settings::GetInstance().GetTraceDebug()) tvhlog(ADDON::LOG_DEBUG, ##__VA_ARGS__)
-static inline void tvhlog ( ADDON::addon_log_t lvl, const char *fmt, ... )
-{
-  char buf[16384];
-  int c = sprintf(buf, "pvr.hts - ");
-  va_list va;
-  va_start(va, fmt);
-  vsnprintf(buf + c, sizeof(buf) - c, fmt, va);
-  va_end(va);
-  XBMC->Log(lvl, "%s", buf);
-}
-
-/*
  * Forward decleration of classes
  */
 class CHTSPConnection;
diff --git a/src/client.cpp b/src/client.cpp
index 8af1b45..0fee62c 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -25,11 +25,13 @@
 #include "platform/util/util.h"
 #include "Tvheadend.h"
 #include "tvheadend/Settings.h"
+#include "tvheadend/utilities/Logger.h"
 
 using namespace std;
 using namespace ADDON;
 using namespace PLATFORM;
 using namespace tvheadend;
+using namespace tvheadend::utilities;
 
 /* **************************************************************************
  * Global variables
@@ -81,7 +83,32 @@ ADDON_STATUS ADDON_Create(void* hdl, void* _unused(props))
     return ADDON_STATUS_PERMANENT_FAILURE;
   }
 
-  tvhinfo("starting PVR client");
+  /* Configure the logger */
+  Logger::SetImplementation([](LogLevel level, const char *message)
+  {
+    /* Convert the log level */
+    addon_log_t addonLevel;
+
+    switch (level)
+    {
+      case LogLevel::ERROR:
+        addonLevel = addon_log_t::LOG_ERROR;
+        break;
+      case LogLevel::INFO:
+        addonLevel = addon_log_t::LOG_INFO;
+        break;
+      default:
+        addonLevel = addon_log_t::LOG_DEBUG;
+    }
+
+    /* Don't log trace messages unless told so */
+    if (level == LogLevel::TRACE && !Settings::GetInstance().GetTraceDebug())
+      return;
+
+    XBMC->Log(addonLevel, message);
+  });
+
+  Logger::Log(LogLevel::INFO, "starting PVR client");
 
   ADDON_ReadSettings();
 
@@ -166,7 +193,7 @@ void ADDON_Announce
   (const char *flag, const char *sender, const char *message, 
    const void *_unused(data))
 {
-  tvhdebug("Announce(flag=%s, sender=%s, message=%s)", flag, sender, message);
+  Logger::Log(LogLevel::DEBUG, "Announce(flag=%s, sender=%s, message=%s)", flag, sender, message);
 
   /* XBMC/System */
   if (!strcmp(sender, "xbmc") && !strcmp(flag, "System"))
diff --git a/src/tvheadend/Settings.cpp b/src/tvheadend/Settings.cpp
index 848816b..579aa47 100644
--- a/src/tvheadend/Settings.cpp
+++ b/src/tvheadend/Settings.cpp
@@ -19,11 +19,12 @@
  *
  */
 
-#include "../Tvheadend.h"
-
+#include "utilities/Logger.h"
+#include "../client.h"
 #include "Settings.h"
 
-namespace tvheadend {
+using namespace tvheadend;
+using namespace tvheadend::utilities;
 
 const std::string Settings::DEFAULT_HOST                = "127.0.0.1";
 const int         Settings::DEFAULT_HTTP_PORT           = 9981;
@@ -148,7 +149,7 @@ ADDON_STATUS Settings::SetSetting(const std::string &key, const void *value)
     return SetIntSetting(GetDvrDupdetect(), value);
   else
   {
-    tvherror("Settings::SetSetting - unknown setting '%s'", key.c_str());
+    Logger::Log(LogLevel::ERROR, "Settings::SetSetting - unknown setting '%s'", key.c_str());
     return ADDON_STATUS_UNKNOWN;
   }
 }
@@ -245,5 +246,3 @@ int Settings::GetDvrLifetime(bool asEnum) const
     }
   }
 }
-
-} // namespace tvheadend
diff --git a/src/tvheadend/Subscription.cpp b/src/tvheadend/Subscription.cpp
index 89b1127..e377751 100644
--- a/src/tvheadend/Subscription.cpp
+++ b/src/tvheadend/Subscription.cpp
@@ -20,10 +20,12 @@
  */
 
 #include "Subscription.h"
+#include "utilities/Logger.h"
 #include "../Tvheadend.h"
 
 using namespace PLATFORM;
 using namespace tvheadend;
+using namespace tvheadend::utilities;
 
 Subscription::Subscription(CHTSPConnection &conn) :
   m_id(0),
@@ -137,7 +139,7 @@ void Subscription::SendSubscribe(uint32_t channelId, uint32_t weight, bool resta
   if (!GetProfile().empty())
     htsmsg_add_str(m, "profile", GetProfile().c_str());
 
-  tvhdebug("demux subscribe to %d",    GetChannelId());
+  Logger::Log(LogLevel::DEBUG, "demux subscribe to %d",    GetChannelId());
 
   /* Send and Wait for response */
   if (restart)
@@ -150,7 +152,7 @@ void Subscription::SendSubscribe(uint32_t channelId, uint32_t weight, bool resta
   htsmsg_destroy(m);
 
   SetState(SUBSCRIPTION_STARTING);
-  tvhdebug("demux successfully subscribed to channel id %d, subscription id %d", GetChannelId(), GetId());
+  Logger::Log(LogLevel::DEBUG, "demux successfully subscribed to channel id %d, subscription id %d", GetChannelId(), GetId());
 }
 
 void Subscription::SendUnsubscribe(void)
@@ -158,7 +160,7 @@ void Subscription::SendUnsubscribe(void)
   /* Build message */
   htsmsg_t *m = htsmsg_create_map();
   htsmsg_add_u32(m, "subscriptionId",   GetId());
-  tvhdebug("demux unsubscribe from %d", GetChannelId());
+  Logger::Log(LogLevel::DEBUG, "demux unsubscribe from %d", GetChannelId());
 
   /* Mark subscription as inactive immediately in case this command fails */
   SetState(SUBSCRIPTION_STOPPED);
@@ -168,7 +170,7 @@ void Subscription::SendUnsubscribe(void)
     return;
 
   htsmsg_destroy(m);
-  tvhdebug("demux successfully unsubscribed from channel id %d, subscription id %d", GetChannelId(), GetId());
+  Logger::Log(LogLevel::DEBUG, "demux successfully unsubscribed from channel id %d, subscription id %d", GetChannelId(), GetId());
 }
 
 bool Subscription::SendSeek(int time)
@@ -178,7 +180,7 @@ bool Subscription::SendSeek(int time)
   htsmsg_add_u32(m, "subscriptionId", GetId());
   htsmsg_add_s64(m, "time",           static_cast<int64_t>(time * 1000LL));
   htsmsg_add_u32(m, "absolute",       1);
-  tvhdebug("demux send seek %d",      time);
+  Logger::Log(LogLevel::DEBUG, "demux send seek %d",      time);
 
   /* Send and Wait */
   {
@@ -204,7 +206,7 @@ void Subscription::SendSpeed(int32_t speed, bool restart)
   htsmsg_t *m = htsmsg_create_map();
   htsmsg_add_u32(m, "subscriptionId", GetId());
   htsmsg_add_s32(m, "speed",          GetSpeed() / 10); // Kodi uses values an order of magnitude larger than tvheadend
-  tvhdebug("demux send speed %d",     GetSpeed() / 10);
+  Logger::Log(LogLevel::DEBUG, "demux send speed %d",     GetSpeed() / 10);
 
   if (restart)
     m = m_conn.SendAndWait0("subscriptionSpeed", m);
@@ -223,7 +225,7 @@ void Subscription::SendWeight(uint32_t weight)
   htsmsg_t *m = htsmsg_create_map();
   htsmsg_add_u32(m, "subscriptionId", GetId());
   htsmsg_add_s32(m, "weight",         GetWeight());
-  tvhdebug("demux send weight %u",    GetWeight());
+  Logger::Log(LogLevel::DEBUG, "demux send weight %u",    GetWeight());
 
   /* Send and Wait */
   {
@@ -247,7 +249,7 @@ void Subscription::ParseSubscriptionStatus ( htsmsg_t *m )
   const char *status = htsmsg_get_str(m, "status");
 
   if (status != NULL)
-    tvhinfo("Bad subscription status: %s", status);
+    Logger::Log(LogLevel::INFO, "Bad subscription status: %s", status);
 
   /* 'subscriptionErrors' was added in htsp v20, use 'status' for older backends */
   if (m_conn.GetProtocol() >= 20)
diff --git a/src/tvheadend/utilities/Logger.h b/src/tvheadend/utilities/Logger.h
new file mode 100644
index 0000000..40f5f54
--- /dev/null
+++ b/src/tvheadend/utilities/Logger.h
@@ -0,0 +1,106 @@
+#pragma once
+/*
+ *      Copyright (C) 2005-2015 Team Kodi
+ *      http://kodi.tv
+ *
+ *  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, 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 XBMC; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include <string>
+#include <memory>
+#include <cstdarg>
+
+namespace tvheadend
+{
+  namespace utilities
+  {
+    /**
+     * Represents the log level
+     */
+    enum LogLevel
+    {
+      ERROR,
+      INFO,
+      DEBUG,
+      TRACE
+    };
+
+    /**
+     * Short-hand for a function that acts as the logger implementation
+     */
+    typedef std::function<void(LogLevel level, const char *message)> LogImplementation;
+
+    /**
+     * The logger class. It is a singleton that by default comes with no
+     * underlying implementation. It is up to the user to supply a suitable
+     * implementation as a lambda using SetImplementation().
+     */
+    class Logger
+    {
+    public:
+
+      /**
+       * Logs the specified message using the specified log level
+       * @param level the log level
+       * @param message the log message
+       * @param ... parameters for the log message
+       */
+      static void Log(LogLevel level, const std::string &message, ...)
+      {
+        char buffer[MESSAGE_BUFFER_SIZE];
+        std::string logMessage = "pvr.hts - " + message;
+
+        va_list arguments;
+        va_start(arguments, message);
+        vsprintf(buffer, logMessage.c_str(), arguments);
+        va_end(arguments);
+
+        GetInstance().m_implementation(level, buffer);
+      }
+
+      /**
+       * Configures the logger to use the specified implementation
+       * @þaram implementation lambda
+       */
+      static void SetImplementation(LogImplementation implementation)
+      {
+        GetInstance().m_implementation = implementation;
+      }
+
+    private:
+      static const unsigned int MESSAGE_BUFFER_SIZE = 16384;
+
+      Logger()
+      { };
+
+      /**
+       * @return the instance
+       */
+      static Logger &GetInstance()
+      {
+        static Logger instance;
+        return instance;
+      }
+
+      /**
+       * The logger implementation
+       */
+      LogImplementation m_implementation;
+
+    };
+  }
+}

-- 
kodi-pvr-hts packaging



More information about the pkg-multimedia-commits mailing list