diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/README xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/README --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/README 2013-01-19 10:06:31.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/README 2013-03-12 10:51:22.000000000 +0000 @@ -39,9 +39,10 @@ Prepare: 1) Install Visual C++ Express 2010 (follow the instructions on the wiki for XBMC itself) Compile: -2) Open this solution from project\VS2010Express\xbmc-pvr-addons.sln -3) Select the wanted configuration "Debug" or "Release" -4) Press F7 to build the solution +2) Run project\BuildDependencies\DownloadBuildDeps.bat +3) Open this solution from project\VS2010Express\xbmc-pvr-addons.sln +4) Select the wanted configuration "Debug" or "Release" +5) Press F7 to build the solution Install: Still a TODO. The buildsystem does not yet generate .zip archives Workaround: copy the wanted pvr addons to your XBMC installation by hand. diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.argustv/addon/addon.xml.in xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.argustv/addon/addon.xml.in --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.argustv/addon/addon.xml.in 2013-01-19 10:06:31.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.argustv/addon/addon.xml.in 2013-03-12 10:51:22.000000000 +0000 @@ -1,7 +1,7 @@ diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.argustv/addon/changelog.txt xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.argustv/addon/changelog.txt --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.argustv/addon/changelog.txt 2013-01-19 10:06:31.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.argustv/addon/changelog.txt 2013-03-12 10:51:22.000000000 +0000 @@ -1,3 +1,5 @@ +v1.6.165 (19-01-2013) +- Do not disable the add-on when it can not connect to the ARGUS-TV server. v1.6.164 (18-01-2013) - EPG genre will contain the ARGUS TV "Category" string. v1.6.163 (01-01-2013) diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.argustv/src/client.cpp xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.argustv/src/client.cpp --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.argustv/src/client.cpp 2012-11-27 01:00:30.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.argustv/src/client.cpp 2013-03-12 10:51:22.000000000 +0000 @@ -160,7 +160,7 @@ SAFE_DELETE(g_client); SAFE_DELETE(PVR); SAFE_DELETE(XBMC); - m_CurStatus = ADDON_STATUS_PERMANENT_FAILURE; + m_CurStatus = ADDON_STATUS_LOST_CONNECTION; } else { @@ -186,14 +186,8 @@ g_bCreated = false; } - if (PVR) - { - SAFE_DELETE(PVR); - } - if (XBMC) - { - SAFE_DELETE(XBMC); - } + SAFE_DELETE(PVR); + SAFE_DELETE(XBMC); m_CurStatus = ADDON_STATUS_UNKNOWN; } diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.argustv/src/pvrclient-argustv.cpp xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.argustv/src/pvrclient-argustv.cpp --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.argustv/src/pvrclient-argustv.cpp 2013-01-19 10:06:31.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.argustv/src/pvrclient-argustv.cpp 2013-03-12 10:51:22.000000000 +0000 @@ -116,9 +116,9 @@ default: XBMC->Log(LOG_ERROR, "Ping failed... No connection to Argus TV.\n"); usleep(1000000); - if (attemps > 30) + if (attemps > 3) { - XBMC->QueueNotification(QUEUE_ERROR, "No connection to Argus TV"); + XBMC->QueueNotification(QUEUE_ERROR, "No connection to Argus TV server"); return false; } } diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.hts/addon/addon.xml.in xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.hts/addon/addon.xml.in --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.hts/addon/addon.xml.in 2013-01-19 10:06:31.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.hts/addon/addon.xml.in 2013-03-12 10:51:22.000000000 +0000 @@ -1,7 +1,7 @@ diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.hts/addon/changelog.txt xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.hts/addon/changelog.txt --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.hts/addon/changelog.txt 2013-01-19 10:06:31.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.hts/addon/changelog.txt 2013-03-12 10:51:22.000000000 +0000 @@ -1,3 +1,8 @@ +1.6.19 + +- add timeshift skip support (FF/RW still not working) +- fix bug in tvh webroot processing + 1.6.18 - ensure channel count is not cleared after succesful sub diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.hts/src/HTSPConnection.cpp xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.hts/src/HTSPConnection.cpp --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.hts/src/HTSPConnection.cpp 2013-01-19 10:06:31.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.hts/src/HTSPConnection.cpp 2013-03-12 10:51:22.000000000 +0000 @@ -495,9 +495,10 @@ if (f->hmf_type == HMF_STR) { if (!strcmp("timeshift", f->hmf_str)) + { m_bTimeshiftSupport = true; - else if (!strcmp("timeshiftseek", f->hmf_str)) m_bTimeshiftSeekSupport = true; + } else if (!strcmp("transcoding", f->hmf_str)) m_bTranscodingSupport = true; } @@ -507,7 +508,7 @@ m_strServerName = server; m_strVersion = version; m_iProtocol = proto; - m_strWebroot = webroot ? webroot : "/"; + m_strWebroot = webroot ? webroot : ""; if(chall && chall_len) { diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.hts/src/HTSPData.cpp xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.hts/src/HTSPData.cpp --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.hts/src/HTSPData.cpp 2013-01-19 10:06:31.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.hts/src/HTSPData.cpp 2013-03-12 10:51:22.000000000 +0000 @@ -324,7 +324,7 @@ /* HTSPv6- - use HTTP */ else - strStreamURL = m_session->GetWebURL("dvrfile/%i", recording.id); + strStreamURL = m_session->GetWebURL("/dvrfile/%i", recording.id); } strRecordingId.Format("%i", recording.id); diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.hts/src/HTSPDemux.cpp xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.hts/src/HTSPDemux.cpp --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.hts/src/HTSPDemux.cpp 2013-01-19 10:06:31.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.hts/src/HTSPDemux.cpp 2013-03-12 10:51:22.000000000 +0000 @@ -27,6 +27,7 @@ #define READ_TIMEOUT 20000 using namespace ADDON; +using namespace PLATFORM; CHTSPDemux::CHTSPDemux(CHTSPConnection* connection) : m_session(connection), @@ -36,6 +37,8 @@ m_tag(0), m_bIsOpen(false) { + m_seekEvent = new CEvent; + m_seekTime = -1; for (unsigned int i = 0; i < PVR_STREAM_MAX_STREAMS; i++) m_Streams.stream[i].iCodecType = AVMEDIA_TYPE_UNKNOWN; m_Streams.iStreamCount = 0; @@ -148,10 +151,16 @@ ParseSubscriptionStop(msg); else if(strcmp("subscriptionStatus", method) == 0) ParseSubscriptionStatus(msg); + else if(strcmp("subscriptionSkip" , method) == 0) + ParseSubscriptionSkip(msg); + else if(strcmp("subscriptionSpeed" , method) == 0) + ParseSubscriptionSpeed(msg); else if(strcmp("queueStatus" , method) == 0) ParseQueueStatus(msg); else if(strcmp("signalStatus" , method) == 0) ParseSignalStatus(msg); + else if(strcmp("timeshiftStatus" , method) == 0) + ParseTimeshiftStatus(msg); else if(strcmp("muxpkt" , method) == 0) ParseMuxPacket(msg); else @@ -576,6 +585,30 @@ } } +void CHTSPDemux::ParseSubscriptionSkip(htsmsg_t *m) +{ + int64_t s64; + uint32_t u32; + if (!htsmsg_get_u32(m, "error", &u32) || + htsmsg_get_u32(m, "absolute", &u32) || + htsmsg_get_s64(m, "time", &s64)) { + m_seekTime = -1; + } else { + m_seekTime = (double)s64; + } + XBMC->Log(LOG_DEBUG, "HTSP::ParseSubscriptionSkip - skip = %lf\n", m_seekTime); + m_seekEvent->Broadcast(); +} + +void CHTSPDemux::ParseSubscriptionSpeed(htsmsg_t *m) +{ + uint32_t u32; + if (!htsmsg_get_u32(m, "speed", &u32)) { + XBMC->Log(LOG_INFO, "%s - speed = %u", __FUNCTION__, u32); + // TODO: need a way to pass this to player core + } +} + bool CHTSPDemux::SendUnsubscribe(int subscription) { XBMC->Log(LOG_INFO, "%s - unsubscribe from subscription %d", __FUNCTION__, subscription); @@ -680,15 +713,31 @@ bool CHTSPDemux::SendSeek(int subscription, int time, bool backward, double *startpts) { - XBMC->Log(LOG_DEBUG, "%s(%d, %d, %d)", __FUNCTION__, subscription, time, backward ? 1:0); htsmsg_t *m = htsmsg_create_map(); - htsmsg_add_str(m, "method" , "subscriptionSeek"); + int64_t seek; + + // Note: time is in MSEC not DVD_TIME_BASE, TVH requires 1MHz (us) input + seek = time * 1000; + XBMC->Log(LOG_DEBUG, "%s(time=%d, seek=%ld)", __FUNCTION__, time, seek); + + htsmsg_add_str(m, "method" , "subscriptionSkip"); htsmsg_add_s32(m, "subscriptionId", subscription); - htsmsg_add_s32(m, "time" , time); - htsmsg_add_u32(m, "backward" , backward); - htsmsg_add_float(m, "startpts" , *startpts); + htsmsg_add_s64(m, "time" , seek); + htsmsg_add_u32(m, "absolute" , 1); + + if (!m_session->ReadSuccess(m, "seek subscription")) + return false; - return m_session->ReadSuccess(m, "seek subscription"); + if (!m_seekEvent->Wait(g_iResponseTimeout * 1000)) + return false; + + if (m_seekTime < 0) + return false; + + // Note: return value is in DVD_TIME_BASE not MSEC + *startpts = m_seekTime * DVD_TIME_BASE / 1000000; + XBMC->Log(LOG_DEBUG, "%s(%ld) = %lf", __FUNCTION__, seek, *startpts); + return true; } bool CHTSPDemux::ParseQueueStatus(htsmsg_t* msg) @@ -734,6 +783,16 @@ return true; } +bool CHTSPDemux::ParseTimeshiftStatus(htsmsg_t *msg) +{ + // TODO: placeholder for processing timeshiftStatus message when + // we're ready to use the information. + // + // For now this just ensures we don't spam logs with unecessary + // info about unhandled messages. + return true; +} + bool CHTSPDemux::ParseSourceInfo(htsmsg_t* msg) { htsmsg_t *sourceinfo; diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.hts/src/HTSPDemux.h xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.hts/src/HTSPDemux.h --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.hts/src/HTSPDemux.h 2012-12-30 01:00:27.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.hts/src/HTSPDemux.h 2013-03-12 10:51:22.000000000 +0000 @@ -24,6 +24,7 @@ #include "client.h" #include "HTSPConnection.h" #include "platform/util/buffer.h" +#include "platform/threads/mutex.h" class CHTSPDemux : public CHTSPConnectionCallback { @@ -49,6 +50,8 @@ void ParseSubscriptionStart (htsmsg_t *m); void ParseSubscriptionStop (htsmsg_t *m); void ParseSubscriptionStatus(htsmsg_t *m); + void ParseSubscriptionSkip (htsmsg_t *m); + void ParseSubscriptionSpeed (htsmsg_t *m); bool SendSubscribe (int subscription, int channel); bool SendUnsubscribe(int subscription); bool SendSpeed (int subscription, int speed); @@ -56,6 +59,7 @@ void ParseMuxPacket(htsmsg_t *m); bool ParseQueueStatus(htsmsg_t* msg); bool ParseSignalStatus(htsmsg_t* msg); + bool ParseTimeshiftStatus(htsmsg_t* msg); bool ParseSourceInfo(htsmsg_t* msg); CHTSPConnection* m_session; @@ -72,4 +76,6 @@ std::map m_StreamIndex; PLATFORM::SyncedBuffer m_demuxPacketBuffer; bool m_bIsOpen; + PLATFORM::CEvent* m_seekEvent; + double m_seekTime; }; diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/addon/addon.xml.in xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/addon/addon.xml.in --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/addon/addon.xml.in 2013-01-04 01:00:25.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/addon/addon.xml.in 2013-03-12 10:51:22.000000000 +0000 @@ -1,7 +1,7 @@ diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/addon/changelog.txt xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/addon/changelog.txt --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/addon/changelog.txt 2013-01-04 01:00:25.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/addon/changelog.txt 2013-03-12 10:51:22.000000000 +0000 @@ -1,3 +1,9 @@ +v1.6.8 +- Channels: Use MediaPortal VisibleInGuide property as inverted IsHidden flag in XBMC. (requires TVServerXBMC build 120) +- Channelgroups: Don't import other channel groups when the user selected to import channels from a single group. +- TSReader: non-Windows: start playback as soon as the buffer file has a non-zero length +- Genre translation: seach also for the genre_translation.xml file in the profile folder. + v1.6.7 - Updated language files from Transifex @@ -12,7 +18,6 @@ - Updated language files from Transifex v1.6.4 - -New version number by Team XBMC v1.2.3.117 diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/src/channels.cpp xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/src/channels.cpp --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/src/channels.cpp 2012-11-15 21:18:19.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/src/channels.cpp 2013-03-12 10:51:22.000000000 +0000 @@ -29,6 +29,7 @@ external_id = 0; iswebstream = false; encrypted = false; + visibleinguide = true; } cChannel::~cChannel() @@ -52,6 +53,7 @@ // ListRadioChannels only: (TVServerXBMC >= v1.1.0.100) // 4 = iswebstream // 5 = webstream url + // 6 = visibleinguide (TVServerXBMC >= v1.2.3.120) uid = atoi(fields[0].c_str()); external_id = atoi(fields[1].c_str()); @@ -62,6 +64,11 @@ { iswebstream = (strncmp(fields[4].c_str(), "1", 1) == 0); url = fields[5].c_str(); + + if (fields.size() >= 7) + { + visibleinguide = (strncmp(fields[6].c_str(), "1", 1) == 0); + } } return true; diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/src/channels.h xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/src/channels.h --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/src/channels.h 2012-11-15 21:18:19.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/src/channels.h 2013-03-12 10:51:22.000000000 +0000 @@ -31,6 +31,7 @@ int external_id; bool encrypted; bool iswebstream; + bool visibleinguide; std::string url; public: @@ -43,6 +44,7 @@ int ExternalID(void) const { return external_id; } bool Encrypted(void) const { return encrypted; } bool IsWebstream(void) const { return iswebstream; } + bool VisibleInGuide(void) const { return visibleinguide; } const char* URL(void) const { return url.c_str(); } }; diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/src/client.cpp xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/src/client.cpp --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/src/client.cpp 2012-12-29 04:00:29.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/src/client.cpp 2013-03-12 10:51:22.000000000 +0000 @@ -450,7 +450,7 @@ pCapabilities->bHandlesInputStream = true; pCapabilities->bHandlesDemuxing = false; pCapabilities->bSupportsChannelScan = false; - pCapabilities->bSupportsRecordingPlayCount = true; + pCapabilities->bSupportsRecordingPlayCount = (g_iTVServerXBMCBuild < 117) ? false : true; pCapabilities->bSupportsLastPlayedPosition = false; pCapabilities->bSupportsRecordingFolders = false; // Don't show the timer directory field. This does not influence the displaying directories in the recordings list. diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/src/lib/tsreader/MultiFileReader.cpp xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/src/lib/tsreader/MultiFileReader.cpp --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/src/lib/tsreader/MultiFileReader.cpp 2012-12-29 04:00:29.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/src/lib/tsreader/MultiFileReader.cpp 2013-03-12 10:51:22.000000000 +0000 @@ -86,21 +86,17 @@ XBMC->Log(LOG_DEBUG, "MultiFileReader: buffer file opened return code %d.", hr); m_lastZapPosition = 0; - int64_t fileLength = m_TSBufferFile.GetFileSize(); int retryCount = 0; - if (fileLength == 0) do + while ((m_TSBufferFile.GetFileSize() == 0) && (retryCount < 50)) { retryCount++; - XBMC->Log(LOG_DEBUG, "MultiFileReader: buffer file has zero length, closing, waiting 100 ms and re-opening. Try %d.", retryCount); - (void) m_TSBufferFile.CloseFile(); + XBMC->Log(LOG_DEBUG, "MultiFileReader: buffer file has zero length, closing, waiting 100 ms and re-opening. Attempt: %d.", retryCount); + m_TSBufferFile.CloseFile(); usleep(100000); hr = m_TSBufferFile.OpenFile(); XBMC->Log(LOG_DEBUG, "MultiFileReader: buffer file opened return code %d.", hr); - - fileLength = m_TSBufferFile.GetFileSize(); - } while (retryCount < 50); - + } if (RefreshTSBufferFile() == S_FALSE) { @@ -324,7 +320,7 @@ int64_t fileLength = m_TSBufferFile.GetFileSize(); // Min file length is Header ( int64_t + int32_t + int32_t ) + filelist ( > 0 ) + Footer ( int32_t + int32_t ) - int64_t minimumlength = (int64_t)(sizeof(currentPosition) + sizeof(filesAdded) + sizeof(filesRemoved) + sizeof(wchar_t) + sizeof(filesAdded2) + sizeof(filesRemoved2)); + int64_t minimumlength = (int64_t)(sizeof(currentPosition) + sizeof(filesAdded) + sizeof(filesRemoved) + sizeof(Wchar_t) + sizeof(filesAdded2) + sizeof(filesRemoved2)); if (fileLength <= minimumlength) { if (m_bDebugOutput) diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/src/pvrclient-mediaportal.cpp xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/src/pvrclient-mediaportal.cpp --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/src/pvrclient-mediaportal.cpp 2012-12-29 04:00:29.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/src/pvrclient-mediaportal.cpp 2013-03-12 10:51:22.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2011 Team XBMC + * Copyright (C) 2005-2012 Team XBMC * http://www.xbmc.org * * This program is free software: you can redistribute it and/or modify @@ -42,13 +42,13 @@ int g_iTVServerXBMCBuild = 0; /* PVR client version (don't forget to update also the addon.xml and the Changelog.txt files) */ -#define PVRCLIENT_MEDIAPORTAL_VERSION_STRING "1.2.3.118" +#define PVRCLIENT_MEDIAPORTAL_VERSION_STRING "1.6.8" /* TVServerXBMC plugin supported versions */ #define TVSERVERXBMC_MIN_VERSION_STRING "1.1.0.90" #define TVSERVERXBMC_MIN_VERSION_BUILD 90 -#define TVSERVERXBMC_RECOMMENDED_VERSION_STRING "1.2.3.118" -#define TVSERVERXBMC_RECOMMENDED_VERSION_BUILD 118 +#define TVSERVERXBMC_RECOMMENDED_VERSION_STRING "1.2.3.120" +#define TVSERVERXBMC_RECOMMENDED_VERSION_BUILD 120 /************************************************************/ /** Class interface */ @@ -63,10 +63,6 @@ m_bTimeShiftStarted = false; m_BackendUTCoffset = 0; m_BackendTime = 0; - m_noSignalStreamSize = 0; - m_noSignalStreamData[0] = '\0'; - m_noSignalStreamReadPos = 0; - m_bPlayingNoSignal = false; m_tsreader = NULL; m_genretable = NULL; m_iLastRecordingUpdate = 0; @@ -135,7 +131,7 @@ if (!m_tcpclient->ReadResponse(code, lines)) { - XBMC->Log(LOG_ERROR, "SendCommand - Failed with code: %d (%s)", code, lines[lines.size()-1].c_str()); + XBMC->Log(LOG_ERROR, "SendCommand2 - Failed with code: %d (%s)", code, lines[lines.size()-1].c_str()); return false; } else @@ -164,7 +160,7 @@ if (!m_tcpclient->connect(g_szHostname, (unsigned short) g_iPort)) { - XBMC->Log(LOG_ERROR, "Could not connect to MPTV backend"); + XBMC->Log(LOG_ERROR, "Could not connect to MediaPortal TV Server backend"); return false; } @@ -229,26 +225,11 @@ snprintf(buffer, 512, "%s:%i", g_szHostname.c_str(), g_iPort); m_ConnectionString = buffer; - /* Retrieve card settings (needed for Live TV and recordings folders) */ - if ( g_iTVServerXBMCBuild >= 106 ) - { - int code; - vector lines; - - if ( SendCommand2("GetCardSettings\n", code, lines) ) - { - m_cCards.ParseLines(lines); - } - } - m_bConnected = true; - // Read the genre string to type/subtype translation file: - if(g_bReadGenre) - { - string sGenreFile = g_szClientPath + PATH_SEPARATOR_CHAR + "resources" + PATH_SEPARATOR_CHAR + "genre_translation.xml"; - m_genretable = new CGenreTable(sGenreFile); - } + /* Load additional settings */ + LoadGenreTable(); + LoadCardSettings(); return true; } @@ -292,6 +273,7 @@ { if(!Connect()) { + XBMC->Log(LOG_DEBUG, "Backend not connected!"); return false; } } @@ -311,7 +293,7 @@ // Used among others for the server name string in the "Recordings" view const char* cPVRClientMediaPortal::GetBackendName(void) { - if (!m_tcpclient->is_valid()) + if (!IsUp()) { return g_szHostname.c_str(); } @@ -579,28 +561,28 @@ return PVR_ERROR_NO_ERROR; } - if (g_szRadioGroup.length() > 0) + if (g_szRadioGroup.empty()) { - XBMC->Log(LOG_DEBUG, "GetChannels(radio) for radio group: '%s'", g_szRadioGroup.c_str()); - command.Format("ListRadioChannels:%s\n", uri::encode(uri::PATH_TRAITS, g_szRadioGroup).c_str()); + XBMC->Log(LOG_DEBUG, "GetChannels(radio) all channels"); + command = "ListRadioChannels\n"; } else { - XBMC->Log(LOG_DEBUG, "GetChannels(radio) all channels"); - command = "ListRadioChannels\n"; + XBMC->Log(LOG_DEBUG, "GetChannels(radio) for radio group: '%s'", g_szRadioGroup.c_str()); + command.Format("ListRadioChannels:%s\n", uri::encode(uri::PATH_TRAITS, g_szRadioGroup).c_str()); } } else { - if (g_szTVGroup.length() > 0) + if (g_szTVGroup.empty()) { - XBMC->Log(LOG_DEBUG, "GetChannels(tv) for TV group: '%s'", g_szTVGroup.c_str()); - command.Format("ListTVChannels:%s\n", uri::encode(uri::PATH_TRAITS, g_szTVGroup).c_str()); + XBMC->Log(LOG_DEBUG, "GetChannels(tv) all channels"); + command = "ListTVChannels\n"; } else { - XBMC->Log(LOG_DEBUG, "GetChannels(tv) all channels"); - command = "ListTVChannels\n"; + XBMC->Log(LOG_DEBUG, "GetChannels(tv) for TV group: '%s'", g_szTVGroup.c_str()); + command.Format("ListTVChannels:%s\n", uri::encode(uri::PATH_TRAITS, g_szTVGroup).c_str()); } } @@ -611,7 +593,6 @@ bool bCheckForThumbs = false; /* Check if we can find the MediaPortal channel logo folders on this machine */ - std::string strIconName; std::string strThumbPath; std::string strProgramData; @@ -665,25 +646,31 @@ tag.iUniqueId = channel.UID(); tag.iChannelNumber = g_iTVServerXBMCBuild >= 102 ? channel.ExternalID() : channel.UID(); PVR_STRCPY(tag.strChannelName, channel.Name()); + PVR_STRCLR(tag.strIconPath); #ifdef TARGET_WINDOWS if (bCheckForThumbs) { - strIconName = strThumbPath + ToThumbFileName(channel.Name()) + ".png"; - if ( OS::CFile::Exists(strIconName) ) - { - PVR_STRCPY(tag.strIconPath, strIconName.c_str()); - } - else + const int ciExtCount = 5; + string strIconExt [ciExtCount] = { ".png", ".jpg", ".jpeg", ".bmp", ".gif" }; + string strIconName; + string strIconBaseName; + + strIconBaseName = strThumbPath + ToThumbFileName(channel.Name()); + + for (int i=0; i < ciExtCount; i++) { - PVR_STRCLR(tag.strIconPath); + strIconName = strIconBaseName + strIconExt[i]; + if ( OS::CFile::Exists(strIconName) ) + { + PVR_STRCPY(tag.strIconPath, strIconName.c_str()); + break; + } } } -#else - PVR_STRCLR(tag.strIconPath); #endif tag.iEncryptionSystem = channel.Encrypted(); tag.bIsRadio = bRadio; - tag.bIsHidden = false; + tag.bIsHidden = !channel.VisibleInGuide(); if(channel.IsWebstream()) { @@ -762,9 +749,21 @@ XBMC->Log(LOG_DEBUG, "Skipping GetChannelGroups for radio. Radio support is disabled."); return PVR_ERROR_NO_ERROR; } + + if (!g_szRadioGroup.empty()) + { + XBMC->Log(LOG_DEBUG, "Skipping GetChannelGroups for radio due to setting: Import only Radio channels from group '%s'.", g_szRadioGroup.c_str()); + return PVR_ERROR_NO_ERROR; + } } else { + if (!g_szTVGroup.empty()) + { + XBMC->Log(LOG_DEBUG, "Skipping GetChannelGroups for TV due to setting: Import only TV channels from group '%s'.", g_szTVGroup.c_str()); + return PVR_ERROR_NO_ERROR; + } + XBMC->Log(LOG_DEBUG, "GetChannelGroups for TV"); if (!SendCommand2("ListGroups\n", code, lines)) return PVR_ERROR_SERVER_ERROR; @@ -1012,8 +1011,10 @@ if(result.find("True") == string::npos) { + XBMC->Log(LOG_ERROR, "Deleting recording %s [failed]", recording.strRecordingId); return PVR_ERROR_FAILED; } + XBMC->Log(LOG_DEBUG, "Deleting recording %s [done]", recording.strRecordingId); // Although XBMC initiates the deletion of this recording, we still have to trigger XBMC to update its // recordings list to remove the recording at the XBMC side @@ -1038,7 +1039,7 @@ if(result.find("True") == string::npos) { - XBMC->Log(LOG_DEBUG, "RenameRecording(%s) to %s [failed]", recording.strRecordingId, recording.strTitle); + XBMC->Log(LOG_ERROR, "RenameRecording(%s) to %s [failed]", recording.strRecordingId, recording.strTitle); return PVR_ERROR_FAILED; } XBMC->Log(LOG_DEBUG, "RenameRecording(%s) to %s [done]", recording.strRecordingId, recording.strTitle); @@ -1067,7 +1068,7 @@ if(result.find("True") == string::npos) { - XBMC->Log(LOG_DEBUG, "%s: id=%s to %i [failed]", __FUNCTION__, recording.strRecordingId, count); + XBMC->Log(LOG_ERROR, "%s: id=%s to %i [failed]", __FUNCTION__, recording.strRecordingId, count); return PVR_ERROR_FAILED; } @@ -1485,7 +1486,7 @@ { usleep(400000); read_timeouts++; - return read_wanted; //writeNoSignalStream(buf, (buf_size - read_done)); + return read_wanted; } read_done += read_wanted; @@ -1495,8 +1496,7 @@ { XBMC->Log(LOG_INFO, "No data in 2 seconds"); read_timeouts = 0; - m_bPlayingNoSignal = true; - return read_done; //writeNoSignalStream(bufptr, read_wanted); + return read_done; } bufptr += read_wanted; read_timeouts++; @@ -1504,8 +1504,8 @@ } } read_timeouts = 0; - m_bPlayingNoSignal = false; - return read_done;//TSReadDone*TS_SIZE; + + return read_done; } void cPVRClientMediaPortal::CloseLiveStream(void) @@ -1638,8 +1638,14 @@ bool cPVRClientMediaPortal::OpenRecordedStream(const PVR_RECORDING &recording) { XBMC->Log(LOG_DEBUG, "->OpenRecordedStream(index=%s)", recording.strRecordingId); - if (!IsUp() || g_eStreamingMethod == ffmpeg) - return false; + if (!IsUp()) + return false; + + if (g_eStreamingMethod == ffmpeg) + { + XBMC->Log(LOG_ERROR, "Addon is in 'ffmpeg' mode. XBMC should play the RTSP url directly. Please reset your XBMC PVR database!"); + return false; + } std::string recfile = ""; @@ -1671,6 +1677,10 @@ } } } + else + { + XBMC->Log(LOG_ERROR, "Backend command '%s' returned a zero-length answer", command); + } if (recfile.length() > 0) { @@ -1725,7 +1735,7 @@ if (m_tsreader->Read(bufptr, read_wanted, &read_wanted) > 0) { usleep(20000); - return read_wanted; //writeNoSignalStream(buf, (buf_size - read_done)); + return read_wanted; } read_done += read_wanted; @@ -1735,9 +1745,8 @@ usleep(20000); } } - //read_timeouts = 0; - m_bPlayingNoSignal = false; - return read_done;//TSReadDone*TS_SIZE; + + return read_done; } long long cPVRClientMediaPortal::SeekRecordedStream(long long iPosition, int iWhence) @@ -1803,3 +1812,38 @@ else return false; } + +void cPVRClientMediaPortal::LoadGenreTable() +{ + // Read the genre string to type/subtype translation file: + if(g_bReadGenre) + { + string sGenreFile = g_szUserPath + PATH_SEPARATOR_CHAR + "resources" + PATH_SEPARATOR_CHAR + "genre_translation.xml"; + + if (!XBMC->FileExists(sGenreFile.c_str(), false)) + { + sGenreFile = g_szUserPath + PATH_SEPARATOR_CHAR + "genre_translation.xml"; + if (!XBMC->FileExists(sGenreFile.c_str(), false)) + { + sGenreFile = g_szClientPath + PATH_SEPARATOR_CHAR + "resources" + PATH_SEPARATOR_CHAR + "genre_translation.xml"; + } + } + + m_genretable = new CGenreTable(sGenreFile); + } +} + +void cPVRClientMediaPortal::LoadCardSettings() +{ + /* Retrieve card settings (needed for Live TV and recordings folders) */ + if ( g_iTVServerXBMCBuild >= 106 ) + { + int code; + vector lines; + + if ( SendCommand2("GetCardSettings\n", code, lines) ) + { + m_cCards.ParseLines(lines); + } + } +} diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/src/pvrclient-mediaportal.h xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/src/pvrclient-mediaportal.h --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mediaportal.tvserver/src/pvrclient-mediaportal.h 2012-12-29 04:00:29.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mediaportal.tvserver/src/pvrclient-mediaportal.h 2013-03-12 10:51:22.000000000 +0000 @@ -32,7 +32,7 @@ /* Use a forward declaration here. Including RTSPClient.h via TSReader.h at this point gives compile errors */ class CTsReader; -class cPVRClientMediaPortal +class cPVRClientMediaPortal: public PLATFORM::PreventCopy { public: /* Class interface */ @@ -108,7 +108,8 @@ private: bool GetChannel(unsigned int number, PVR_CHANNEL &channeldata); - bool LoadGenreXML(const std::string &filename); + void LoadGenreTable(void); + void LoadCardSettings(void); int m_iCurrentChannel; int m_iCurrentCard; @@ -127,11 +128,6 @@ int64_t m_iLastRecordingUpdate; CTsReader* m_tsreader; - char m_noSignalStreamData[ 6 + 0xffff ]; - long m_noSignalStreamSize; - long m_noSignalStreamReadPos; - bool m_bPlayingNoSignal; - void Close(); //Used for TV Server communication: diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/Makefile.am xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/Makefile.am --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/Makefile.am 2012-12-01 01:00:27.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/Makefile.am 2013-03-12 10:51:22.000000000 +0000 @@ -30,6 +30,6 @@ src/cppmyth/MythRecorder.cpp \ src/cppmyth/MythStorageGroupFile.cpp \ src/cppmyth/MythSignal.cpp \ - src/cppmyth/MythTimer.cpp \ + src/cppmyth/MythRecordingRule.cpp \ src/cppmyth/MythTimestamp.cpp diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/addon/addon.xml.in xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/addon/addon.xml.in --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/addon/addon.xml.in 2013-01-04 01:00:25.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/addon/addon.xml.in 2013-03-12 10:51:22.000000000 +0000 @@ -1,7 +1,7 @@ diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/addon/changelog.txt xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/addon/changelog.txt --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/addon/changelog.txt 2013-01-04 01:00:25.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/addon/changelog.txt 2013-03-12 10:51:22.000000000 +0000 @@ -1,3 +1,33 @@ +v1.6.9 +- Added Live TV vs. recording conflict handling +- Fixed recovering from backend connection loss on Windows +- Fixed error when trying to set watched flag for recordings that already have been marked as watched + +v1.6.8 +- Performance improvements + - Reduced startup time (Faster loading of EPG, channels, recordings and images) + - Reduced resource usage for image caching + - Cache recording data (event triggered updates from backend) + - Fixed lock when stopping recording playback + - Improved general response time +- Live TV improvements + - Better handling of connection problems + - Playback does not stop anymore between program breaks + - Fixed seek problems +- Timer improvements + - Add optional internal recording rule template + - Correctly apply backend recording rule settings + - Properly add title and subtitle + - Fixed Timer deletion +- Added advanced option for specifying database host/port +- Fixed crash when loading invisibile recordings +- Improved Art-work loading +- Combine channels with same channum and callsign +- Fixed IPv6 support +- Fixed Windows XP support +- Improved logging, notifications and system labels +- Refactored & cleaned up libcmyth (inttypes, names, docs) + v1.6.7 - Updated language files from Transifex diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/addon/resources/language/English/strings.po xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/addon/resources/language/English/strings.po --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/addon/resources/language/English/strings.po 2013-01-04 01:00:25.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/addon/resources/language/English/strings.po 2013-03-12 10:51:22.000000000 +0000 @@ -49,3 +49,121 @@ msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "" + +msgctxt "#30008" +msgid "Conflict handling" +msgstr "" + +msgctxt "#30009" +msgid "Prefer Live TV when recording has later slot" +msgstr "" + +msgctxt "#30010" +msgid "Prefer recording and stop Live TV" +msgstr "" + +msgctxt "#30011" +msgid "Prefer Live TV and cancel conflicting recording" +msgstr "" + +msgctxt "#30019" +msgid "General" +msgstr "" + +msgctxt "#30020" +msgid "Template provider" +msgstr "" + +msgctxt "#30021" +msgid "Internal" +msgstr "" + +msgctxt "#30022" +msgid "MythTV" +msgstr "" + +msgctxt "#30025" +msgid "Internal template" +msgstr "" + +msgctxt "#30026" +msgid "Automatically Look Up Metadata" +msgstr "" + +msgctxt "#30027" +msgid "Commercial Flag new recordings" +msgstr "" + +msgctxt "#30028" +msgid "Transcode new recordings" +msgstr "" + +msgctxt "#30029" +msgid "Run User Job #1" +msgstr "" + +msgctxt "#30030" +msgid "Run User Job #2" +msgstr "" + +msgctxt "#30031" +msgid "Run User Job #3" +msgstr "" + +msgctxt "#30032" +msgid "Run User Job #4" +msgstr "" + +msgctxt "#30033" +msgid "Transcoder" +msgstr "" + +msgctxt "#30034" +msgid "Allow recordings to expire?" +msgstr "" + +msgctxt "#30049" +msgid "Recording template" +msgstr "" + +# Systeminformation labels +msgctxt "#30100" +msgid "Protocol version: %i - Database version: %i" +msgstr "" + +# Notifications +msgctxt "#30300" +msgid "Failed to connect to MythTV backend" +msgstr "" + +msgctxt "#30301" +msgid "Failed to connect to MythTV database" +msgstr "" + +msgctxt "#30302" +msgid "Connection to MythTV backend lost" +msgstr "" + +msgctxt "#30303" +msgid "Connection to MythTV restored" +msgstr "" + +msgctxt "#30304" +msgid "No response from MythTV backend" +msgstr "" + +msgctxt "#30305" +msgid "Channel unavailable" +msgstr "" + +msgctxt "#30306" +msgid "Recorder unavailable" +msgstr "" + +msgctxt "#30307" +msgid "Canceling conflicting recording: %s" +msgstr "" + +msgctxt "#30308" +msgid "Stopping Live TV due to conflicting recording: %s" +msgstr "" diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/addon/resources/settings.xml xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/addon/resources/settings.xml --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/addon/resources/settings.xml 2012-11-15 21:18:19.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/addon/resources/settings.xml 2013-03-12 10:51:22.000000000 +0000 @@ -1,11 +1,29 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/project/VS2010Express/pvr.mythtv.cmyth.vcxproj xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/project/VS2010Express/pvr.mythtv.cmyth.vcxproj --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/project/VS2010Express/pvr.mythtv.cmyth.vcxproj 2012-12-01 08:34:33.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/project/VS2010Express/pvr.mythtv.cmyth.vcxproj 2013-03-12 10:51:22.000000000 +0000 @@ -20,9 +20,9 @@ + - @@ -39,9 +39,9 @@ + - @@ -56,8 +56,10 @@ - + + + {A55ACC6B-837D-4784-8E41-66947B1D9B8C} diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/project/VS2010Express/pvr.mythtv.cmyth.vcxproj.filters xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/project/VS2010Express/pvr.mythtv.cmyth.vcxproj.filters --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/project/VS2010Express/pvr.mythtv.cmyth.vcxproj.filters 2012-11-15 21:18:19.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/project/VS2010Express/pvr.mythtv.cmyth.vcxproj.filters 2013-03-12 10:51:22.000000000 +0000 @@ -28,9 +28,6 @@ cppmyth - - cppmyth - cppmyth @@ -38,6 +35,9 @@ cppmyth + + cppmyth + @@ -75,13 +75,13 @@ cppmyth - - cppmyth - cppmyth + + cppmyth + @@ -90,13 +90,28 @@ {a9c2652d-c1dd-4836-a42d-bc5e6db7b5a0} + + {e4b481fe-5c99-4cea-a4f4-5301e96a480a} + + + {f0aada70-0bcb-4b23-b953-1ca297413a9e} + + + {3ba85d2f-45bc-4080-8895-55949f7f52a7} + - + addon - + addon + + addon\resources + + + addon\resources\language\English + \ No newline at end of file diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/client.cpp xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/client.cpp --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/client.cpp 2012-11-15 21:18:19.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/client.cpp 2013-03-12 10:51:22.000000000 +0000 @@ -27,28 +27,33 @@ using namespace std; using namespace ADDON; -#define SEEK_POSSIBLE 0x10 // Flag used to check if protocol allows seeks - /* User adjustable settings are saved here. * Default values are defined inside client.h * and exported to the other source files. */ -CStdString g_szHostname = DEFAULT_HOST; ///< The Host name or IP of the mythtv server -int g_iMythPort = DEFAULT_PORT; ///< The mythtv Port (default is 6543) -CStdString g_szMythDBuser = DEFAULT_DB_USER; ///< The mythtv sql username (default is mythtv) -CStdString g_szMythDBpassword = DEFAULT_DB_PASSWORD; ///< The mythtv sql password (default is mythtv) -CStdString g_szMythDBname = DEFAULT_DB_NAME; ///< The mythtv sql database name (default is mythconverg) -bool g_bExtraDebug = DEFAULT_EXTRA_DEBUG; ///< Output extensive debug information to the log -bool g_bLiveTV = DEFAULT_LIVETV; ///< LiveTV support (or recordings only) -bool g_bLiveTVPriority = DEFAULT_LIVETV_PRIORITY; ///< MythTV Backend setting to allow live TV to move scheduled shows +CStdString g_szMythHostname = DEFAULT_HOST; ///< The Host name or IP of the mythtv server +int g_iMythPort = DEFAULT_PORT; ///< The mythtv Port (default is 6543) +CStdString g_szDBUser = DEFAULT_DB_USER; ///< The mythtv sql username (default is mythtv) +CStdString g_szDBPassword = DEFAULT_DB_PASSWORD; ///< The mythtv sql password (default is mythtv) +CStdString g_szDBName = DEFAULT_DB_NAME; ///< The mythtv sql database name (default is mythconverg) +CStdString g_szDBHostname = DEFAULT_HOST; ///< The mythtv sql database host name or IP of the database server (default is same as mythtv backend hostname) +int g_iDBPort = DEFAULT_DB_PORT; ///< The mythtv sql database port (default is 3306) +bool g_bExtraDebug = DEFAULT_EXTRA_DEBUG; ///< Output extensive debug information to the log +bool g_bLiveTV = DEFAULT_LIVETV; ///< LiveTV support (or recordings only) +bool g_bLiveTVPriority = DEFAULT_LIVETV_PRIORITY; ///< MythTV Backend setting to allow live TV to move scheduled shows +int g_iLiveTVConflictStrategy = DEFAULT_LIVETV_CONFLICT_STRATEGY; ///< Conflict resolving strategy (0= +int g_iRecTemplateType = DEFAULT_RECORD_TEMPLATE; ///< Template type for new record (0=Internal, 1=MythTV) +bool g_bRecAutoMetadata = true; +bool g_bRecAutoCommFlag = false; +bool g_bRecAutoTranscode = false; +bool g_bRecAutoRunJob1 = false; +bool g_bRecAutoRunJob2 = false; +bool g_bRecAutoRunJob3 = false; +bool g_bRecAutoRunJob4 = false; +bool g_bRecAutoExpire = false; +int g_iRecTranscoder = 0; ///* Client member variables */ -bool m_recordingFirstRead; -char m_noSignalStreamData[6 + 0xffff]; -long m_noSignalStreamSize = 0; -long m_noSignalStreamReadPos = 0; -bool m_bPlayingNoSignal = false; -int m_iCurrentChannel = 1; ADDON_STATUS m_CurStatus = ADDON_STATUS_UNKNOWN; bool g_bCreated = false; int g_iClientID = -1; @@ -80,8 +85,10 @@ XBMC->Log(LOG_DEBUG, "Creating MythTV cmyth PVR-Client"); + XBMC->Log(LOG_DEBUG, "Addon compiled with XBMC_PVR_API_VERSION: %s and XBMC_PVR_MIN_API_VERSION: %s", GetPVRAPIVersion(), GetMininumPVRAPIVersion()); + XBMC->Log(LOG_DEBUG, "Register handle @ libXBMC_addon...done"); - + XBMC->Log(LOG_DEBUG, "Checking props..."); if (!props) { @@ -121,12 +128,12 @@ /* Read setting "host" from settings.xml */ if (XBMC->GetSetting("host", buffer)) - g_szHostname = buffer; + g_szMythHostname = buffer; else { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'host' setting, falling back to '%s' as default", DEFAULT_HOST); - g_szHostname = DEFAULT_HOST; + g_szMythHostname = DEFAULT_HOST; } buffer[0] = 0; @@ -134,7 +141,7 @@ if (!XBMC->GetSetting("port", &g_iMythPort)) { /* If setting is unknown fallback to defaults */ - XBMC->Log(LOG_ERROR, "Couldn't get 'port' setting, falling back to '%i' as default", DEFAULT_PORT); + XBMC->Log(LOG_ERROR, "Couldn't get 'port' setting, falling back to '%d' as default", DEFAULT_PORT); g_iMythPort = DEFAULT_PORT; } @@ -148,37 +155,58 @@ /* Read setting "db_username" from settings.xml */ if (XBMC->GetSetting("db_user", buffer)) - g_szMythDBuser = buffer; + g_szDBUser = buffer; else { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'db_user' setting, falling back to '%s' as default", DEFAULT_DB_USER); - g_szMythDBuser = DEFAULT_DB_USER; + g_szDBUser = DEFAULT_DB_USER; } buffer[0] = 0; /* Read setting "db_password" from settings.xml */ if (XBMC->GetSetting("db_password", buffer)) - g_szMythDBpassword = buffer; + g_szDBPassword = buffer; else { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'db_password' setting, falling back to '%s' as default", DEFAULT_DB_PASSWORD); - g_szMythDBpassword = DEFAULT_DB_PASSWORD; + g_szDBPassword = DEFAULT_DB_PASSWORD; } buffer[0] = 0; - + /* Read setting "db_name" from settings.xml */ if (XBMC->GetSetting("db_name", buffer)) - g_szMythDBname = buffer; + g_szDBName = buffer; else { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'db_name' setting, falling back to '%s' as default", DEFAULT_DB_NAME); - g_szMythDBname = DEFAULT_DB_NAME; + g_szDBName = DEFAULT_DB_NAME; + } + buffer[0] = 0; + + /* Read hidden setting "db_host" from settings.xml */ + if (XBMC->GetSetting("db_host", buffer)) + if (strlen(buffer) > 0) + g_szDBHostname = buffer; + else + g_szDBHostname = g_szMythHostname; + else + { + /* If setting is unknown fallback to defaults */ + XBMC->Log(LOG_ERROR, "Couldn't get 'db_host' setting, falling back to '%s' as default", g_szMythHostname.c_str()); + g_szDBHostname = g_szMythHostname; } buffer[0] = 0; + /* Read hidden setting "db_port" from settings.xml */ + if (!XBMC->GetSetting("db_port", &g_iDBPort) || g_iDBPort == 0) + { + /* If setting is unknown fallback to defaults */ + g_iDBPort = DEFAULT_DB_PORT; + } + /* Read setting "LiveTV" from settings.xml */ if (!XBMC->GetSetting("livetv", &g_bLiveTV)) { @@ -187,6 +215,44 @@ g_bLiveTV = DEFAULT_LIVETV; } + /* Read settings "Record livetv_conflict_method" from settings.xml */ + if (!XBMC->GetSetting("livetv_conflict_strategy", &g_iLiveTVConflictStrategy)) + { + /* If setting is unknown fallback to defaults */ + XBMC->Log(LOG_ERROR, "Couldn't get 'livetv_conflict_method' setting, falling back to '%i' as default", DEFAULT_RECORD_TEMPLATE); + g_iLiveTVConflictStrategy = DEFAULT_LIVETV_CONFLICT_STRATEGY; + } + + /* Read settings "Record template" from settings.xml */ + if (!XBMC->GetSetting("rec_template_provider", &g_iRecTemplateType)) + { + /* If setting is unknown fallback to defaults */ + XBMC->Log(LOG_ERROR, "Couldn't get 'rec_template_provider' setting, falling back to '%i' as default", DEFAULT_RECORD_TEMPLATE); + g_iRecTemplateType = DEFAULT_RECORD_TEMPLATE; + } + /* Get internal template settings when selected (0) */ + if (g_iRecTemplateType == 0) + { + if (!XBMC->GetSetting("rec_autometadata", &g_bRecAutoMetadata)) + g_bRecAutoMetadata = true; + if (!XBMC->GetSetting("rec_autocommflag", &g_bRecAutoCommFlag)) + g_bRecAutoCommFlag = false; + if (!XBMC->GetSetting("rec_autotranscode", &g_bRecAutoTranscode)) + g_bRecAutoTranscode = false; + if (!XBMC->GetSetting("rec_autorunjob1", &g_bRecAutoRunJob1)) + g_bRecAutoRunJob1 = false; + if (!XBMC->GetSetting("rec_autorunjob2", &g_bRecAutoRunJob2)) + g_bRecAutoRunJob2 = false; + if (!XBMC->GetSetting("rec_autorunjob3", &g_bRecAutoRunJob3)) + g_bRecAutoRunJob3 = false; + if (!XBMC->GetSetting("rec_autorunjob4", &g_bRecAutoRunJob4)) + g_bRecAutoRunJob4 = false; + if (!XBMC->GetSetting("rec_autoexpire", &g_bRecAutoExpire)) + g_bRecAutoExpire = false; + if (!XBMC->GetSetting("rec_transcoder", &g_iRecTranscoder)) + g_iRecTranscoder = 0; + } + free (buffer); // Create our addon @@ -271,14 +337,14 @@ string str = settingName; if (!g_bCreated) return ADDON_STATUS_OK; - + if (str == "host") { string tmp_sHostname; - XBMC->Log(LOG_INFO, "Changed Setting 'host' from %s to %s", g_szHostname.c_str(), (const char*)settingValue); - tmp_sHostname = g_szHostname; - g_szHostname = (const char*)settingValue; - if (tmp_sHostname != g_szHostname) + XBMC->Log(LOG_INFO, "Changed Setting 'host' from %s to %s", g_szMythHostname.c_str(), (const char*)settingValue); + tmp_sHostname = g_szMythHostname; + g_szMythHostname = (const char*)settingValue; + if (tmp_sHostname != g_szMythHostname) return ADDON_STATUS_NEED_RESTART; } else if (str == "port") @@ -292,29 +358,29 @@ } else if (str == "db_user") { - string tmp_sMythDBuser; - XBMC->Log(LOG_INFO, "Changed Setting 'db_user' from %s to %s", g_szMythDBuser.c_str(), (const char*)settingValue); - tmp_sMythDBuser = g_szMythDBuser; - g_szMythDBuser = (const char*)settingValue; - if (tmp_sMythDBuser != g_szMythDBuser) + string tmp_sDBUser; + XBMC->Log(LOG_INFO, "Changed Setting 'db_user' from %s to %s", g_szDBUser.c_str(), (const char*)settingValue); + tmp_sDBUser = g_szDBUser; + g_szDBUser = (const char*)settingValue; + if (tmp_sDBUser != g_szDBUser) return ADDON_STATUS_NEED_RESTART; } else if (str == "db_password") { - string tmp_sMythDBpassword; - XBMC->Log(LOG_INFO, "Changed Setting 'db_password' from %s to %s", g_szMythDBpassword.c_str(), (const char*)settingValue); - tmp_sMythDBpassword = g_szMythDBpassword; - g_szMythDBpassword = (const char*)settingValue; - if (tmp_sMythDBpassword != g_szMythDBpassword) + string tmp_sDBPassword; + XBMC->Log(LOG_INFO, "Changed Setting 'db_password' from %s to %s", g_szDBPassword.c_str(), (const char*)settingValue); + tmp_sDBPassword = g_szDBPassword; + g_szDBPassword = (const char*)settingValue; + if (tmp_sDBPassword != g_szDBPassword) return ADDON_STATUS_NEED_RESTART; } else if (str == "db_name") { - string tmp_sMythDBname; - XBMC->Log(LOG_INFO, "Changed Setting 'db_name' from %s to %s", g_szMythDBname.c_str(), (const char*)settingValue); - tmp_sMythDBname = g_szMythDBname; - g_szMythDBname = (const char*)settingValue; - if (tmp_sMythDBname != g_szMythDBname) + string tmp_sDBName; + XBMC->Log(LOG_INFO, "Changed Setting 'db_name' from %s to %s", g_szDBName.c_str(), (const char*)settingValue); + tmp_sDBName = g_szDBName; + g_szDBName = (const char*)settingValue; + if (tmp_sDBName != g_szDBName) return ADDON_STATUS_NEED_RESTART; } else if (str == "extradebug") @@ -659,7 +725,7 @@ int dataread = g_client->ReadLiveStream(pBuffer, iBufferSize); if (dataread < 0) { - XBMC->Log(LOG_ERROR,"%s: Failed to read liveStream. Errorcode: %i!", __FUNCTION__, dataread); + XBMC->Log(LOG_ERROR,"%s: Failed to read liveStream. Errorcode: %d!", __FUNCTION__, dataread); } return dataread; } @@ -677,12 +743,7 @@ if (g_client == NULL) return false; - if (g_client->SwitchChannel(channelinfo)) - return true; - else - XBMC->QueueNotification(QUEUE_WARNING, "Failed to change channel. No free tuners?"); - - return false; + return g_client->SwitchChannel(channelinfo); } PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS &signalStatus) @@ -708,7 +769,7 @@ return true; } -long long SeekLiveStream(long long iPosition, int iWhence) +long long SeekLiveStream(long long iPosition, int iWhence) { if (g_client == NULL) return -1; @@ -716,7 +777,7 @@ return g_client->SeekLiveStream(iPosition,iWhence); } -long long PositionLiveStream(void) +long long PositionLiveStream(void) { if (g_client == NULL) return -1; @@ -724,7 +785,7 @@ return g_client->SeekLiveStream(0,SEEK_CUR); } -long long LengthLiveStream(void) +long long LengthLiveStream(void) { if (g_client == NULL) return -1; diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/client.h xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/client.h --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/client.h 2012-11-15 21:18:19.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/client.h 2013-03-12 10:51:22.000000000 +0000 @@ -36,14 +36,23 @@ #define strdup _strdup // # strdup is POSIX, _strdup should be used instead #endif -#define DEFAULT_HOST "127.0.0.1" -#define DEFAULT_EXTRA_DEBUG false -#define DEFAULT_LIVETV_PRIORITY false -#define DEFAULT_LIVETV true -#define DEFAULT_PORT 6543 -#define DEFAULT_DB_USER "mythtv" -#define DEFAULT_DB_PASSWORD "mythtv" -#define DEFAULT_DB_NAME "mythconverg" +#define LIVETV_CONFLICT_STRATEGY_HASLATER 0 +#define LIVETV_CONFLICT_STRATEGY_STOPTV 1 +#define LIVETV_CONFLICT_STRATEGY_CANCELREC 2 + +#define DEFAULT_HOST "127.0.0.1" +#define DEFAULT_EXTRA_DEBUG false +#define DEFAULT_LIVETV_PRIORITY true +#define DEFAULT_LIVETV_CONFLICT_STRATEGY LIVETV_CONFLICT_STRATEGY_HASLATER +#define DEFAULT_LIVETV true +#define DEFAULT_PORT 6543 +#define DEFAULT_DB_USER "mythtv" +#define DEFAULT_DB_PASSWORD "mythtv" +#define DEFAULT_DB_NAME "mythconverg" +#define DEFAULT_DB_PORT 3306 +#define DEFAULT_RECORD_TEMPLATE 1 + +#define SUBTITLE_SEPARATOR " - " /*! * @brief PVR macros for string exchange @@ -55,20 +64,34 @@ #define SAFE_DELETE(p) do { delete (p); (p)=NULL; } while (0) #define SAFE_DELETE_ARRAY(p) do { delete[] (p); (p)=NULL; } while (0) -extern bool g_bCreated; ///< Shows that the Create function was successfully called -extern int g_iClientID; ///< The PVR client ID used by XBMC for this driver -extern CStdString g_szUserPath; ///< The Path to the user directory inside user profile -extern CStdString g_szClientPath; ///< The Path where this driver is located +extern bool g_bCreated; ///< Shows that the Create function was successfully called +extern int g_iClientID; ///< The PVR client ID used by XBMC for this driver +extern CStdString g_szUserPath; ///< The Path to the user directory inside user profile +extern CStdString g_szClientPath; ///< The Path where this driver is located /* Client Settings */ -extern CStdString g_szHostname; ///< The Host name or IP of the mythtv server -extern int g_iMythPort; ///< The mythtv Port (default is 6543) -extern CStdString g_szMythDBuser; ///< The mythtv sql username (default is mythtv) -extern CStdString g_szMythDBpassword; ///< The mythtv sql password (default is mythtv) -extern CStdString g_szMythDBname; ///< The mythtv sql database name (default is mythconverg) -extern bool g_bExtraDebug; ///< Debug logging -extern bool g_bLiveTV; ///< LiveTV support (or recordings only) -extern bool g_bLiveTVPriority; ///< MythTV Backend setting to allow live TV to move scheduled shows +extern CStdString g_szMythHostname; ///< The Host name or IP of the mythtv server +extern int g_iMythPort; ///< The mythtv Port (default is 6543) +extern CStdString g_szDBUser; ///< The mythtv sql username (default is mythtv) +extern CStdString g_szDBPassword; ///< The mythtv sql password (default is mythtv) +extern CStdString g_szDBName; ///< The mythtv sql database name (default is mythconverg) +extern CStdString g_szDBHostname; ///< The mythtv sql database host name or IP of the database server +extern int g_iDBPort; ///< The mythtv sql database port (default is 3306) +extern bool g_bExtraDebug; ///< Debug logging +extern bool g_bLiveTV; ///< LiveTV support (or recordings only) +extern bool g_bLiveTVPriority; ///< MythTV Backend setting to allow live TV to move scheduled shows +extern int g_iLiveTVConflictStrategy; ///< Live TV conflict resolving strategy (0=Has later, 1=Stop TV, 2=Cancel recording) +extern int g_iRecTemplateType; ///< Template type for new record (0=Internal, 1=MythTV) +///* Internal Record template */ +extern bool g_bRecAutoMetadata; +extern bool g_bRecAutoCommFlag; +extern bool g_bRecAutoTranscode; +extern bool g_bRecAutoRunJob1; +extern bool g_bRecAutoRunJob2; +extern bool g_bRecAutoRunJob3; +extern bool g_bRecAutoRunJob4; +extern bool g_bRecAutoExpire; +extern int g_iRecTranscoder; extern ADDON::CHelper_libXBMC_addon *XBMC; extern CHelper_libXBMC_pvr *PVR; diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/cppmyth/MythChannel.cpp xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/cppmyth/MythChannel.cpp --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/cppmyth/MythChannel.cpp 2012-11-15 21:18:19.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/cppmyth/MythChannel.cpp 2013-03-12 10:51:22.000000000 +0000 @@ -41,7 +41,7 @@ return *m_channel_t == NULL; } -int MythChannel::ID() +unsigned int MythChannel::ID() { return cmyth_channel_chanid(*m_channel_t); } @@ -54,7 +54,7 @@ return retval; } -int MythChannel::NumberInt() +unsigned int MythChannel::NumberInt() { return cmyth_channel_channum(*m_channel_t); } @@ -91,12 +91,12 @@ return m_radio; } -int MythChannel::SourceID() +unsigned int MythChannel::SourceID() { return cmyth_channel_sourceid(*m_channel_t); } -int MythChannel::MultiplexID() +unsigned int MythChannel::MultiplexID() { return cmyth_channel_multiplex(*m_channel_t); } diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/cppmyth/MythChannel.h xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/cppmyth/MythChannel.h --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/cppmyth/MythChannel.h 2012-11-15 21:18:19.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/cppmyth/MythChannel.h 2013-03-12 10:51:22.000000000 +0000 @@ -37,16 +37,16 @@ bool IsNull() const; - int ID(); + unsigned int ID(); CStdString Name(); - int NumberInt(); + unsigned int NumberInt(); CStdString Number(); CStdString Callsign(); CStdString Icon(); bool Visible(); bool IsRadio() const; - int SourceID(); - int MultiplexID(); + unsigned int SourceID(); + unsigned int MultiplexID(); private: boost::shared_ptr > m_channel_t; diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/cppmyth/MythConnection.cpp xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/cppmyth/MythConnection.cpp --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/cppmyth/MythConnection.cpp 2012-11-15 21:18:19.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/cppmyth/MythConnection.cpp 2013-03-12 10:51:22.000000000 +0000 @@ -24,7 +24,7 @@ #include "MythStorageGroupFile.h" #include "MythProgramInfo.h" #include "MythEventHandler.h" -#include "MythTimer.h" +#include "MythRecordingRule.h" #include "MythPointer.h" #include "../client.h" @@ -102,16 +102,16 @@ void MythConnection::Lock() { if (g_bExtraDebug) - XBMC->Log(LOG_DEBUG, "Lock %i", m_conn_t.get()); + XBMC->Log(LOG_DEBUG, "Lock %u", m_conn_t.get()); m_conn_t->Lock(); if (g_bExtraDebug) - XBMC->Log(LOG_DEBUG, "Lock acquired %i", m_conn_t.get()); + XBMC->Log(LOG_DEBUG, "Lock acquired %u", m_conn_t.get()); } void MythConnection::Unlock() { if (g_bExtraDebug) - XBMC->Log(LOG_DEBUG, "Unlock %i", m_conn_t.get()); + XBMC->Log(LOG_DEBUG, "Unlock %u", m_conn_t.get()); m_conn_t->Unlock(); } @@ -121,13 +121,13 @@ bool connected = *m_conn_t != 0 && !cmyth_conn_hung(*m_conn_t); Unlock(); if (g_bExtraDebug) - XBMC->Log(LOG_DEBUG, "%s - %i", __FUNCTION__, connected); + XBMC->Log(LOG_DEBUG, "%s - %s", __FUNCTION__, (connected ? "true" : "false")); return connected; } bool MythConnection::TryReconnect() { - int retval = false; + int retval; Lock(); retval = cmyth_conn_reconnect_ctrl(*m_conn_t); Unlock(); @@ -169,11 +169,11 @@ bool MythConnection::GetDriveSpace(long long &total, long long &used) { int retval = 0; - CMYTH_CONN_CALL(retval, retval != 0, cmyth_conn_get_freespace(*m_conn_t, &total, &used)); - return retval == 0; + CMYTH_CONN_CALL(retval, retval < 0, cmyth_conn_get_freespace(*m_conn_t, (int64_t*)&total, (int64_t*)&used)); + return retval >= 0; } -CStdString MythConnection::GetSetting(const CStdString &hostname, const CStdString &setting) +CStdString MythConnection::GetSettingOnHost(const CStdString &setting, const CStdString &hostname) { char *value = NULL; CMYTH_CONN_CALL_REF(value, value == NULL, cmyth_conn_get_setting(*m_conn_t, const_cast(hostname.c_str()), const_cast(setting.c_str()))); @@ -208,8 +208,8 @@ bool MythConnection::DeleteRecording(MythProgramInfo &recording) { int retval = 0; - CMYTH_CONN_CALL(retval, retval != 0, cmyth_proginfo_delete_recording(*m_conn_t, *recording.m_proginfo_t)); - return retval == 0; + CMYTH_CONN_CALL(retval, retval < 0, cmyth_proginfo_delete_recording(*m_conn_t, *recording.m_proginfo_t)); + return retval >= 0; } ProgramInfoMap MythConnection::GetRecordedPrograms() @@ -222,10 +222,9 @@ int len = cmyth_proglist_get_count(proglist); for (int i = 0; i < len; i++) { - cmyth_proginfo_t cmprog = cmyth_proglist_get_item(proglist, i); - MythProgramInfo prog = cmyth_proginfo_get_detail(*m_conn_t, cmprog); + MythProgramInfo prog = cmyth_proglist_get_item(proglist, i); if (!prog.IsNull()) { - retval.insert(std::pair(prog.StrUID().c_str(), prog)); + retval.insert(std::pair(prog.UID().c_str(), prog)); } } ref_release(proglist); @@ -235,6 +234,36 @@ return retval; } +MythProgramInfo MythConnection::GetRecordedProgram(const CStdString &basename) +{ + MythProgramInfo retval; + cmyth_proginfo_t prog = NULL; + if (!basename.IsEmpty()) + { + CMYTH_CONN_CALL_REF(prog, prog == NULL, cmyth_proginfo_get_from_basename(*m_conn_t, const_cast(basename.c_str()))); + if (prog) { + retval = MythProgramInfo(prog); + } + } + + return retval; +} + +MythProgramInfo MythConnection::GetRecordedProgram(int chanid, time_t recstartts) +{ + MythProgramInfo retval; + cmyth_proginfo_t prog = NULL; + if (chanid > 0 && recstartts > 0) + { + CMYTH_CONN_CALL_REF(prog, prog == NULL, cmyth_proginfo_get_from_timeslot(*m_conn_t, chanid, recstartts)); + if (prog) { + retval = MythProgramInfo(prog); + } + } + + return retval; +} + ProgramInfoMap MythConnection::GetPendingPrograms() { Lock(); @@ -247,7 +276,7 @@ { MythProgramInfo prog = cmyth_proglist_get_item(proglist, i); if (!prog.IsNull()) { - retval.insert(std::pair(prog.StrUID().c_str(), prog)); + retval.insert(std::pair(prog.UID().c_str(), prog)); } } ref_release(proglist); @@ -267,10 +296,9 @@ int len = cmyth_proglist_get_count(proglist); for (int i = 0; i < len; i++) { - cmyth_proginfo_t cmprog = cmyth_proglist_get_item(proglist, i); - MythProgramInfo prog = cmyth_proginfo_get_detail(*m_conn_t, cmprog); + MythProgramInfo prog = cmyth_proglist_get_item(proglist, i); if (!prog.IsNull()) { - retval.insert(std::pair(prog.StrUID().c_str(), prog)); + retval.insert(std::pair(prog.UID().c_str(), prog)); } } ref_release(proglist); @@ -287,40 +315,18 @@ return retval >= 0; } -void MythConnection::DefaultTimer(MythTimer &timer) +bool MythConnection::StopRecording(const MythProgramInfo &recording) { - timer.SetAutoTranscode(atoi(GetSetting("NULL", "AutoTranscode").c_str()) > 0); - timer.SetUserJob(1, atoi(GetSetting("NULL", "AutoRunUserJob1").c_str()) > 0); - timer.SetUserJob(2, atoi(GetSetting("NULL", "AutoRunUserJob2").c_str()) > 0); - timer.SetUserJob(3, atoi(GetSetting("NULL", "AutoRunUserJob3").c_str()) > 0); - timer.SetUserJob(4, atoi(GetSetting("NULL", "AutoRunUserJob4").c_str()) > 0); - timer.SetAutoCommFlag(atoi(GetSetting("NULL", "AutoCommercialFlag").c_str()) > 0); - timer.SetAutoExpire(atoi(GetSetting("NULL", "AutoExpireDefault").c_str()) > 0); - timer.SetTranscoder(atoi(GetSetting("NULL", "DefaultTranscoder").c_str())); - timer.SetStartOffset(atoi(GetSetting("NULL", "DefaultStartOffset").c_str())); - timer.SetStartOffset(atoi(GetSetting("NULL", "DefaultEndOffset").c_str())); + int retval; + CMYTH_CONN_CALL(retval, retval < 0, cmyth_proginfo_stop_recording(*m_conn_t, *recording.m_proginfo_t)); + return (retval >= 0); } -StorageGroupFileList MythConnection::GetStorageGroupFileList(const CStdString &storageGroup) +MythStorageGroupFile MythConnection::GetStorageGroupFile(const CStdString &storageGroup, const CStdString &filename) { - cmyth_storagegroup_filelist_t filelist = NULL; - CMYTH_CONN_CALL_REF(filelist, filelist == NULL, cmyth_storagegroup_get_filelist(*m_conn_t, const_cast(storageGroup.c_str()), const_cast(GetBackendHostname().c_str()))); - - Lock(); - - int len = cmyth_storagegroup_filelist_count(filelist); - StorageGroupFileList retval; - retval.reserve(len); - for (int i = 0; i < len; i++) - { - cmyth_storagegroup_file_t file = cmyth_storagegroup_filelist_get_item(filelist, i); - retval.push_back(MythStorageGroupFile(file)); - } - ref_release(filelist); - - Unlock(); - - return retval; + cmyth_storagegroup_file_t file = NULL; + CMYTH_CONN_CALL_REF(file, file == NULL, cmyth_storagegroup_get_fileinfo(*m_conn_t, const_cast(storageGroup.c_str()), const_cast(GetBackendHostname().c_str()), const_cast(filename.c_str()))); + return MythStorageGroupFile(file); } MythFile MythConnection::ConnectFile(MythProgramInfo &recording) diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/cppmyth/MythConnection.h xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/cppmyth/MythConnection.h --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/cppmyth/MythConnection.h 2012-11-15 21:18:19.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/cppmyth/MythConnection.h 2013-03-12 10:51:22.000000000 +0000 @@ -33,16 +33,15 @@ class MythFile; class MythProgramInfo; class MythEventHandler; -class MythTimer; +class MythRecordingRule; class MythStorageGroupFile; template class MythPointer; template class MythPointerThreadSafe; typedef std::map ProgramInfoMap; -typedef std::vector StorageGroupFileList; -class MythConnection +class MythConnection { public: MythConnection(); @@ -62,7 +61,7 @@ CStdString GetBackendHostname(); int GetProtocolVersion(); bool GetDriveSpace(long long &total, long long &used); - CStdString GetSetting(const CStdString &hostname, const CStdString &setting); + CStdString GetSettingOnHost(const CStdString &setting, const CStdString &hostname); bool SetSetting(const CStdString &hostname, const CStdString &setting, const CStdString &value); // Recorders @@ -72,17 +71,19 @@ // Recordings bool DeleteRecording(MythProgramInfo &recording); ProgramInfoMap GetRecordedPrograms(); + MythProgramInfo GetRecordedProgram(const CStdString &basename); + MythProgramInfo GetRecordedProgram(int chanid, time_t recstartts); // Timers ProgramInfoMap GetPendingPrograms(); ProgramInfoMap GetScheduledPrograms(); bool UpdateSchedules(int id); - void DefaultTimer(MythTimer &timer); + bool StopRecording(const MythProgramInfo &recording); // Files MythFile ConnectFile(MythProgramInfo &recording); MythFile ConnectPath(const CStdString &filename, const CStdString &storageGroup); - StorageGroupFileList GetStorageGroupFileList(const CStdString &storageGroup); + MythStorageGroupFile GetStorageGroupFile(const CStdString &storageGroup, const CStdString &filename); // Bookmarks long long GetBookmark(MythProgramInfo &recording); diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/cppmyth/MythDatabase.cpp xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/cppmyth/MythDatabase.cpp --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/cppmyth/MythDatabase.cpp 2012-11-15 21:18:19.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/cppmyth/MythDatabase.cpp 2013-03-12 10:51:22.000000000 +0000 @@ -21,7 +21,7 @@ #include "MythDatabase.h" #include "MythChannel.h" #include "MythProgramInfo.h" -#include "MythTimer.h" +#include "MythRecordingRule.h" #include "MythPointer.h" #include "../client.h" @@ -47,10 +47,10 @@ { } -MythDatabase::MythDatabase(const CStdString &server, const CStdString &database, const CStdString &user, const CStdString &password) +MythDatabase::MythDatabase(const CStdString &server, const CStdString &database, const CStdString &user, const CStdString &password, unsigned short port) : m_database_t(new MythPointerThreadSafe()) { - *m_database_t = cmyth_database_init(const_cast(server.c_str()), const_cast(database.c_str()), const_cast(user.c_str()), const_cast(password.c_str())); + *m_database_t = cmyth_database_init(const_cast(server.c_str()), const_cast(database.c_str()), const_cast(user.c_str()), const_cast(password.c_str()), port); } bool MythDatabase::IsNull() const @@ -70,18 +70,35 @@ return retval == 1; } +int MythDatabase::GetSchemaVersion() +{ + int retval = 0; + CMYTH_DB_CALL(retval, retval < 0, cmyth_database_get_version(*m_database_t)); + return retval; +} + +CStdString MythDatabase::GetSetting(const CStdString &setting) +{ + int retval; + char* buf = NULL; + CMYTH_DB_CALL(retval, retval < 0, cmyth_mysql_get_setting(*m_database_t, const_cast(setting.c_str()), &buf)); + CStdString data(buf); + ref_release(buf); + return data; +} + bool MythDatabase::FindProgram(time_t starttime, int channelid, const CStdString &title, MythProgram* program) { int retval = 0; - CMYTH_DB_CALL(retval, retval < 0, cmyth_mysql_get_prog_finder_time_title_chan(*m_database_t, program, const_cast(title.c_str()), starttime, channelid)); + CMYTH_DB_CALL(retval, retval < 0, cmyth_mysql_get_prog_finder_time_title_chan(*m_database_t, program, starttime, const_cast(title.c_str()), channelid)); return retval > 0; } -ProgramList MythDatabase::GetGuide(time_t starttime, time_t endtime) +ProgramList MythDatabase::GetGuide(int channelid, time_t starttime, time_t endtime) { MythProgram *programs = 0; int len = 0; - CMYTH_DB_CALL(len, len < 0, cmyth_mysql_get_guide(*m_database_t, &programs, starttime, endtime)); + CMYTH_DB_CALL(len, len < 0, cmyth_mysql_get_guide(*m_database_t, &programs, channelid, starttime, endtime)); if (len < 1) return ProgramList(); @@ -91,11 +108,12 @@ return retval; } -ChannelMap MythDatabase::GetChannels() +ChannelIdMap MythDatabase::GetChannels() { - ChannelMap retval; + int ret; + ChannelIdMap retval; cmyth_chanlist_t channels = NULL; - CMYTH_DB_CALL(channels, channels == NULL, cmyth_mysql_get_chanlist(*m_database_t)); + CMYTH_DB_CALL(ret, ret < 0, cmyth_mysql_get_chanlist(*m_database_t, &channels)); int channelCount = cmyth_chanlist_get_count(channels); for (int i = 0; i < channelCount; i++) @@ -112,156 +130,96 @@ ChannelGroupMap MythDatabase::GetChannelGroups() { ChannelGroupMap retval; - cmyth_channelgroups_t *channelGroups = NULL; + cmyth_channelgroup_t *channelGroups = NULL; int channelGroupCount = 0; CMYTH_DB_CALL(channelGroupCount, channelGroupCount < 0, cmyth_mysql_get_channelgroups(*m_database_t, &channelGroups)); if (!channelGroups) return retval; - m_database_t->Lock(); - for (int i = 0; i < channelGroupCount; i++) { - MythChannelGroup channelGroup; - channelGroup.first = channelGroups[i].channelgroup; - // cmyth_mysql_get_channelids_in_group writes the list of all channel IDs to its third parameter (int**) - int* channelIDs = 0; - int channelCount = cmyth_mysql_get_channelids_in_group(*m_database_t, channelGroups[i].ID, &channelIDs); - if (channelCount) + unsigned int *channelIDs = 0; + int channelCount = cmyth_mysql_get_channelids_in_group(*m_database_t, channelGroups[i].grpid, (uint32_t**)&channelIDs); + if (channelCount > 0) { - channelGroup.second = std::vector(channelIDs, channelIDs + channelCount); + retval.insert(std::make_pair(channelGroups[i].name, std::vector(channelIDs, channelIDs + channelCount))); ref_release(channelIDs); } else - channelGroup.second = std::vector(); - - retval.insert(channelGroup); + { + retval.insert(std::make_pair(channelGroups[i].name, std::vector())); + } } ref_release(channelGroups); - - m_database_t->Unlock(); - return retval; } -SourceMap MythDatabase::GetSources() +RecorderSourceList MythDatabase::GetLiveTVRecorderSourceList(const CStdString &channum) { - SourceMap retval; - cmyth_rec_t *recorders = 0; + RecorderSourceList retval; + cmyth_recorder_source_t *recorders = 0; int recorderCount = 0; - CMYTH_DB_CALL(recorderCount, recorderCount < 0, cmyth_mysql_get_recorder_list(*m_database_t, &recorders)); - - m_database_t->Lock(); + CMYTH_DB_CALL(recorderCount, recorderCount < 0, cmyth_mysql_get_recorder_source_channum(*m_database_t, const_cast(channum.c_str()), &recorders)); - for (int i = 0; i < recorderCount; i++) + for (int i = 0; i < recorderCount; ++i) { - SourceMap::iterator it = retval.find(recorders[i].sourceid); - if (it != retval.end()) - it->second.push_back(recorders[i].recid); - else - retval[recorders[i].sourceid] = std::vector(1, recorders[i].recid); + retval.push_back(std::make_pair(recorders[i].recid, recorders[i].sourceid)); } ref_release(recorders); - - m_database_t->Unlock(); - return retval; } -TimerMap MythDatabase::GetTimers() +RecordingRuleMap MythDatabase::GetRecordingRules() { - TimerMap retval; - cmyth_timerlist_t timers = NULL; - CMYTH_DB_CALL(timers, timers == NULL, cmyth_mysql_get_timers(*m_database_t)); - int timerCount = cmyth_timerlist_get_count(timers); + int ret; + RecordingRuleMap retval; + cmyth_recordingrulelist_t rules = NULL; + CMYTH_DB_CALL(ret, ret < 0, cmyth_mysql_get_recordingrules(*m_database_t, &rules)); + int ruleCount = cmyth_recordingrulelist_get_count(rules); - for (int i = 0; i < timerCount; i++) + for (int i = 0; i < ruleCount; i++) { - cmyth_timer_t timer = cmyth_timerlist_get_item(timers, i); + cmyth_recordingrule_t rule = cmyth_recordingrulelist_get_item(rules, i); - MythTimer t(timer); - retval.insert(std::pair(t.RecordID(), t)); + MythRecordingRule t(rule); + retval.insert(std::pair(t.RecordID(), t)); } - ref_release(timers); + ref_release(rules); return retval; } -int MythDatabase::AddTimer(const MythTimer &timer) +bool MythDatabase::AddRecordingRule(const MythRecordingRule &rule) { int retval = 0; - CMYTH_DB_CALL(retval, retval < 0, - cmyth_mysql_add_timer(*m_database_t, - timer.ChannelID(), - const_cast(timer.Callsign().c_str()), - const_cast(timer.Description().c_str()), - timer.StartTime(), - timer.EndTime(), - const_cast(timer.Title(false).c_str()), - const_cast(timer.Category().c_str()), - timer.Type(), - const_cast(timer.Subtitle().c_str()), - timer.Priority(), - timer.StartOffset(), - timer.EndOffset(), - timer.SearchType(), - timer.Inactive() ? 1 : 0, - timer.DuplicateControlMethod(), - timer.CheckDuplicatesInType(), - const_cast(timer.RecordingGroup().c_str()), - const_cast(timer.StorageGroup().c_str()), - const_cast(timer.PlaybackGroup().c_str()), - timer.AutoTranscode(), - timer.UserJobs(), - timer.AutoCommFlag(), - timer.AutoExpire(), - timer.MaxEpisodes(), - timer.NewExpiresOldRecord(), - timer.Transcoder())); - return retval; + CMYTH_DB_CALL(retval, retval < 0, cmyth_mysql_add_recordingrule(*m_database_t, *rule.m_recordingrule_t)); + return retval > 0; } -bool MythDatabase::UpdateTimer(const MythTimer &timer) +bool MythDatabase::UpdateRecordingRule(const MythRecordingRule &rule) { int retval = 0; - CMYTH_DB_CALL(retval, retval < 0, - cmyth_mysql_update_timer(*m_database_t, - timer.RecordID(), - timer.ChannelID(), - const_cast(timer.m_callsign.c_str()), - const_cast(timer.m_description.c_str()), - timer.StartTime(), - timer.EndTime(), - const_cast(timer.Title(false).c_str()), - const_cast(timer.Category().c_str()), - timer.Type(), - const_cast(timer.Subtitle().c_str()), - timer.Priority(), - timer.StartOffset(), - timer.EndOffset(), - timer.SearchType(), - timer.Inactive() ? 1 : 0, - timer.DuplicateControlMethod(), - timer.CheckDuplicatesInType(), - const_cast(timer.RecordingGroup().c_str()), - const_cast(timer.StorageGroup().c_str()), - const_cast(timer.PlaybackGroup().c_str()), - timer.AutoTranscode(), - timer.UserJobs(), - timer.AutoCommFlag(), - timer.AutoExpire(), - timer.MaxEpisodes(), - timer.NewExpiresOldRecord(), - timer.Transcoder())); - return retval == 0; + CMYTH_DB_CALL(retval, retval < 0, cmyth_mysql_update_recordingrule(*m_database_t, *rule.m_recordingrule_t)); + return retval > 0; } -bool MythDatabase::DeleteTimer(int recordid) +bool MythDatabase::DeleteRecordingRule(unsigned int recordid) { int retval = 0; - CMYTH_DB_CALL(retval, retval < 0, cmyth_mysql_delete_timer(*m_database_t, recordid)); - return retval == 0; + CMYTH_DB_CALL(retval, retval < 0, cmyth_mysql_delete_recordingrule(*m_database_t, recordid)); + return retval > 0; +} + +MythRecordingRule MythDatabase::LoadRecordingRuleTemplate(const CStdString &category, const CStdString &category_type) +{ + int ret; + MythRecordingRule retval; + cmyth_recordingrule_t rule = NULL; + CMYTH_DB_CALL(ret, ret < 0, cmyth_mysql_recordingrule_from_template(*m_database_t, const_cast(category.c_str()), const_cast(category_type.c_str()), &rule)); + if (ret >= 0) + retval = MythRecordingRule(rule); + return retval; } RecordingProfileList MythDatabase::GetRecordingProfiles() @@ -272,7 +230,6 @@ CMYTH_DB_CALL(recordingProfileCount, recordingProfileCount < 0, cmyth_mysql_get_recprofiles(*m_database_t, &recordingProfiles)); - m_database_t->Lock(); for (int i = 0; i < recordingProfileCount; i++) { RecordingProfileList::iterator it = std::find(retval.begin(), retval.end(), CStdString(recordingProfiles[i].cardtype)); @@ -285,22 +242,52 @@ it->profile.insert(std::pair(recordingProfiles[i].id, recordingProfiles[i].name)); } ref_release(recordingProfiles); - - m_database_t->Unlock(); - return retval; } -int MythDatabase::SetWatchedStatus(const MythProgramInfo &recording, bool watched) +bool MythDatabase::SetWatchedStatus(const MythProgramInfo &recording, bool watched) { int retval = 0; - CMYTH_DB_CALL(retval, retval < 0, cmyth_set_watched_status_mysql(*m_database_t, *recording.m_proginfo_t, watched ? 1 : 0)); - return retval; + CMYTH_DB_CALL(retval, retval < 0, cmyth_mysql_set_watched_status(*m_database_t, *recording.m_proginfo_t, watched ? 1 : 0)); + return retval > 0; } long long MythDatabase::GetBookmarkMark(const MythProgramInfo &recording, long long bk, int mode) { long long mark = 0; - CMYTH_DB_CALL(mark, mark < 0, cmyth_get_bookmark_mark(*m_database_t, *recording.m_proginfo_t, bk, mode)); + CMYTH_DB_CALL(mark, mark < 0, cmyth_mysql_get_bookmark_mark(*m_database_t, *recording.m_proginfo_t, bk, mode)); return mark; } + +long long MythDatabase::GetRecordingMarkup(const MythProgramInfo &recording, int type) +{ + long long value = 0; + CMYTH_DB_CALL(value, value < 0, cmyth_mysql_get_recording_markup(*m_database_t, *recording.m_proginfo_t, (cmyth_recording_markup_t)type)); + return value; +} + +long long MythDatabase::GetRecordingFrameRate(const MythProgramInfo &recording) +{ + long long value = 0; + CMYTH_DB_CALL(value, value < 0, cmyth_mysql_get_recording_framerate(*m_database_t, *recording.m_proginfo_t)); + return value; +} + +bool MythDatabase::FillRecordingArtwork(MythProgramInfo &recording) +{ + int retval = 0; + char* coverart; + char* fanart; + char* banner; + CMYTH_DB_CALL(retval, retval < 0, cmyth_mysql_get_recording_artwork(*m_database_t, *recording.m_proginfo_t, &coverart, &fanart, &banner)); + if (retval > 0) + { + recording.m_coverart = coverart; + recording.m_fanart = fanart; + ref_release(coverart); + ref_release(fanart); + ref_release(banner); + return true; + } + return false; +} \ No newline at end of file diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/cppmyth/MythDatabase.h xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/cppmyth/MythDatabase.h --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/cppmyth/MythDatabase.h 2012-11-15 21:18:19.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/cppmyth/MythDatabase.h 2013-03-12 10:51:22.000000000 +0000 @@ -31,7 +31,7 @@ }; class MythChannel; -class MythTimer; +class MythRecordingRule; class MythProgramInfo; template class MythPointerThreadSafe; @@ -39,12 +39,13 @@ typedef cmyth_program_t MythProgram; typedef std::vector ProgramList; -typedef std::map ChannelMap; -typedef std::pair > MythChannelGroup; +typedef std::map ChannelIdMap; +typedef std::multimap ChannelNumberMap; typedef std::map > ChannelGroupMap; -typedef std::map > SourceMap; -typedef std::map TimerMap; +typedef std::vector > RecorderSourceList; + +typedef std::map RecordingRuleMap; // TODO: Rework MythRecordingProfile class MythRecordingProfile : public CStdString @@ -59,29 +60,40 @@ { public: MythDatabase(); - MythDatabase(const CStdString &server, const CStdString &database, const CStdString &user, const CStdString &password); + MythDatabase(const CStdString &server, const CStdString &database, const CStdString &user, const CStdString &password, unsigned short port); bool IsNull() const; bool TestConnection(CStdString *msg); + int GetSchemaVersion(); + + CStdString GetSetting(const CStdString &setting); + bool FindProgram(time_t starttime, int channelid, const CStdString &title, MythProgram* pprogram); - ProgramList GetGuide(time_t starttime, time_t endtime); + ProgramList GetGuide(int channelid, time_t starttime, time_t endtime); - ChannelMap GetChannels(); + ChannelIdMap GetChannels(); ChannelGroupMap GetChannelGroups(); - SourceMap GetSources(); - TimerMap GetTimers(); - int AddTimer(const MythTimer &timer); - bool UpdateTimer(const MythTimer &timer); - bool DeleteTimer(int recordid); + RecorderSourceList GetLiveTVRecorderSourceList(const CStdString &channum); + + RecordingRuleMap GetRecordingRules(); + bool AddRecordingRule(const MythRecordingRule &rule); + bool UpdateRecordingRule(const MythRecordingRule &rule); + bool DeleteRecordingRule(unsigned int recordid); + MythRecordingRule LoadRecordingRuleTemplate(const CStdString &category, const CStdString &category_type); RecordingProfileList GetRecordingProfiles(); - int SetWatchedStatus(const MythProgramInfo &recording, bool watched); + bool SetWatchedStatus(const MythProgramInfo &recording, bool watched); long long GetBookmarkMark(const MythProgramInfo &recording, long long bk, int mode); + long long GetRecordingMarkup(const MythProgramInfo &recording, int type); + long long GetRecordingFrameRate(const MythProgramInfo &recording); + + bool FillRecordingArtwork(MythProgramInfo &recording); + private: boost::shared_ptr > m_database_t; }; diff -Nru xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/cppmyth/MythEventHandler.cpp xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/cppmyth/MythEventHandler.cpp --- xbmc-pvr-addons-1.0.0~git20130129.2244-96774c4/addons/pvr.mythtv.cmyth/src/cppmyth/MythEventHandler.cpp 2012-11-15 21:18:19.000000000 +0000 +++ xbmc-pvr-addons-1.0.0~git20130312.1151-590f862/addons/pvr.mythtv.cmyth/src/cppmyth/MythEventHandler.cpp 2013-03-12 10:51:22.000000000 +0000 @@ -23,8 +23,12 @@ #include "MythSignal.h" #include "MythPointer.h" #include "MythFile.h" +#include "MythProgramInfo.h" +#include "MythTimestamp.h" #include "../client.h" +#include + using namespace ADDON; template @@ -62,12 +66,16 @@ virtual void* Process(void); + void HandleAskRecording(const CStdString &buffer, MythProgramInfo &programInfo); + void HandleUpdateSignal(const CStdString &buffer); void SetRecordingEventListener(const CStdString &recordid, const MythFile &file); void HandleUpdateFileSize(const CStdString &buffer); void RetryConnect(); + bool TryReconnect(); + void RecordingListChange(); // Data CStdString m_server; @@ -75,12 +83,17 @@ boost::shared_ptr > m_conn_t; + MythEventObserver *m_observer; + MythRecorder m_recorder; MythSignal m_signal; bool m_playback; + bool m_hang; CStdString m_currentRecordID; MythFile m_currentFile; + + std::list m_recordingChangeEventList; }; MythEventHandler::MythEventHandlerPrivate::MythEventHandlerPrivate(const CStdString &server, unsigned short port) @@ -89,9 +102,12 @@ , m_server(server) , m_port(port) , m_conn_t(new MythPointerThreadSafe()) + , m_observer(NULL) , m_recorder(MythRecorder()) , m_signal() , m_playback(false) + , m_hang(false) + , m_recordingChangeEventList() { *m_conn_t = cmyth_conn_connect_event(const_cast(m_server.c_str()), port, 64 * 1024, 16 * 1024); } @@ -127,12 +143,15 @@ cmyth_event_t myth_event; char databuf[2049]; databuf[0] = 0; + bool triggerRecordingUpdate = false; + unsigned int recordingChangeCount = 0; timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 100000; while (!IsStopped()) { + bool recordingChange = false; int select = 0; m_conn_t->Lock(); select = cmyth_event_select(*m_conn_t, &timeout); @@ -140,8 +159,9 @@ if (select > 0) { + cmyth_proginfo_t proginfo = NULL; m_conn_t->Lock(); - myth_event = cmyth_event_get(*m_conn_t, databuf, 2048); + myth_event = cmyth_event_get_message(*m_conn_t, databuf, 2048, &proginfo); m_conn_t->Unlock(); if (g_bExtraDebug) @@ -150,11 +170,11 @@ if (myth_event == CMYTH_EVENT_UPDATE_FILE_SIZE) { if (g_bExtraDebug) - XBMC->Log(LOG_NOTICE,"%s - Event file size update: %i", __FUNCTION__, databuf); + XBMC->Log(LOG_NOTICE,"%s - Event file size update: %s", __FUNCTION__, databuf); HandleUpdateFileSize(databuf); } - if (myth_event == CMYTH_EVENT_LIVETV_CHAIN_UPDATE) + else if (myth_event == CMYTH_EVENT_LIVETV_CHAIN_UPDATE) { Lock(); if (!m_recorder.IsNull()) @@ -169,7 +189,7 @@ Unlock(); } - if (myth_event == CMYTH_EVENT_LIVETV_WATCH) + else if (myth_event == CMYTH_EVENT_LIVETV_WATCH) { if (g_bExtraDebug) XBMC->Log(LOG_NOTICE,"%s: Event LIVETV_WATCH: recoder %s", __FUNCTION__, databuf); @@ -187,7 +207,7 @@ Unlock(); } - if(myth_event == CMYTH_EVENT_DONE_RECORDING) + else if(myth_event == CMYTH_EVENT_DONE_RECORDING) { if (g_bExtraDebug) XBMC->Log(LOG_NOTICE, "%s: Event DONE_RECORDING: recorder %s", __FUNCTION__, databuf); @@ -205,7 +225,13 @@ Unlock(); } - if (myth_event == CMYTH_EVENT_SIGNAL) + else if (myth_event == CMYTH_EVENT_ASK_RECORDING) + { + MythProgramInfo prog(proginfo); + HandleAskRecording(databuf, prog); + } + + else if (myth_event == CMYTH_EVENT_SIGNAL) { HandleUpdateSignal(databuf); } @@ -215,26 +241,66 @@ if (g_bExtraDebug) XBMC->Log(LOG_NOTICE, "%s - Event schedule change", __FUNCTION__); PVR->TriggerTimerUpdate(); - PVR->TriggerRecordingUpdate(); } - if (!m_playback && ( - myth_event == CMYTH_EVENT_RECORDING_LIST_CHANGE_ADD || - myth_event == CMYTH_EVENT_RECORDING_LIST_CHANGE_DELETE || - myth_event == CMYTH_EVENT_RECORDING_LIST_CHANGE_UPDATE || - myth_event == CMYTH_EVENT_RECORDING_LIST_CHANGE)) + else if (myth_event == CMYTH_EVENT_RECORDING_LIST_CHANGE_ADD) + { + //Event data: "4121 2010-03-06T01:06:43[]:[]empty" + unsigned int chanid; + char recstartts[20]; + if (strlen(databuf)>=24 && sscanf(databuf, "%u %19s", &chanid, recstartts) == 2) { + Lock(); + m_recordingChangeEventList.push_back(RecordingChangeEvent(CHANGE_ADD, chanid, recstartts)); + Unlock(); + if (g_bExtraDebug) + XBMC->Log(LOG_DEBUG,"%s - Event recording list add: CHANID=%u TS=%s", __FUNCTION__, chanid, recstartts); + recordingChange = true; + } + } + + else if (myth_event == CMYTH_EVENT_RECORDING_LIST_CHANGE_UPDATE) + { + //Event data: Updated 'proginfo' is returned + MythProgramInfo prog = MythProgramInfo(proginfo); + if (!prog.IsNull()) + { + Lock(); + m_recordingChangeEventList.push_back(RecordingChangeEvent(CHANGE_UPDATE, prog)); + Unlock(); + if (g_bExtraDebug) + XBMC->Log(LOG_DEBUG,"%s - Event recording list update: UID=%s", __FUNCTION__, prog.UID().c_str()); + recordingChange = true; + } + } + + else if (myth_event == CMYTH_EVENT_RECORDING_LIST_CHANGE_DELETE) + { + //Event data: "4121 2010-03-06T01:06:43[]:[]empty" + unsigned int chanid; + char recstartts[20]; + if (strlen(databuf)>=24 && sscanf(databuf, "%u %19s", &chanid, recstartts) == 2) { + Lock(); + m_recordingChangeEventList.push_back(RecordingChangeEvent(CHANGE_DELETE, chanid, recstartts)); + Unlock(); + if (g_bExtraDebug) + XBMC->Log(LOG_DEBUG,"%s - Event recording list delete: CHANID=%u TS=%s", __FUNCTION__, chanid, recstartts); + recordingChange = true; + } + } + + else if (myth_event == CMYTH_EVENT_RECORDING_LIST_CHANGE) { if (g_bExtraDebug) XBMC->Log(LOG_NOTICE, "%s - Event recording list change", __FUNCTION__); - PVR->TriggerRecordingUpdate(); + RecordingListChange(); } - if (myth_event == CMYTH_EVENT_UNKNOWN) + else if (myth_event == CMYTH_EVENT_UNKNOWN) { XBMC->Log(LOG_NOTICE, "%s - Event unknown, databuf: %s", __FUNCTION__, databuf); } - if (myth_event == CMYTH_EVENT_CLOSE) + else if (myth_event == CMYTH_EVENT_CLOSE) { XBMC->Log(LOG_NOTICE, "%s - Event client connection closed", __FUNCTION__); RetryConnect(); @@ -244,29 +310,51 @@ } else if (select < 0) { - XBMC->Log(LOG_ERROR, "%s Event client connection error", __FUNCTION__); - RetryConnect(); + XBMC->Log(LOG_ERROR, "%s Event client connection error", __FUNCTION__); + RetryConnect(); } - else if (select = 0 && cmyth_conn_hung(*m_conn_t)) + else if (cmyth_conn_hung(*m_conn_t)) { XBMC->Log(LOG_NOTICE, "%s - Connection hung - reconnect event client connection", __FUNCTION__); + if (!m_conn_t || !TryReconnect()) + RetryConnect(); + } - if (!m_conn_t) - break; - - m_conn_t->Lock(); - int retval = cmyth_conn_reconnect_event(*m_conn_t); - m_conn_t->Unlock(); - if (retval == 1) - XBMC->Log(LOG_NOTICE, "%s - Connected client to event socket", __FUNCTION__); + //Accumulate recording change events before triggering PVR event + //First timeout is 0.5 sec and next 2 secs + if (recordingChange) + { + if (recordingChangeCount == 0) + { + timeout.tv_sec = 0; + timeout.tv_usec = 500000; + } else - XBMC->Log(LOG_NOTICE, "%s - Could not connect client to event socket", __FUNCTION__); + { + timeout.tv_sec = 2; + timeout.tv_usec = 0; + } + recordingChangeCount++; + triggerRecordingUpdate = true; + } + else + { + //Restore timeout + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + //Need PVR update ? + if (triggerRecordingUpdate) + { + XBMC->Log(LOG_DEBUG, "%s - Trigger PVR recording update: %lu recording(s)", __FUNCTION__, recordingChangeCount); + PVR->TriggerRecordingUpdate(); + triggerRecordingUpdate = false; + } + //Reset counter + recordingChangeCount = 0; } - - //Restore timeout - timeout.tv_sec = 0; - timeout.tv_usec = 100000; } + // Free recording change event + m_recordingChangeEventList.clear(); return NULL; } @@ -278,6 +366,44 @@ m_currentRecordID = recordIDBuffer; } +void MythEventHandler::MythEventHandlerPrivate::HandleAskRecording(const CStdString &databuf, MythProgramInfo &programInfo) +{ + // ASK_RECORDING