Skip to content

Commit

Permalink
Merge pull request #611 from ksooo/fix-no-channels
Browse files Browse the repository at this point in the history
Fixes for async state (Nexus)
  • Loading branch information
ksooo authored Mar 19, 2023
2 parents 3ae87c0 + e30b230 commit b6b9368
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 27 deletions.
2 changes: 1 addition & 1 deletion pvr.hts/addon.xml.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon
id="pvr.hts"
version="20.6.1"
version="20.6.2"
name="Tvheadend HTSP Client"
provider-name="Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld">
<requires>@ADDON_DEPENDS@</requires>
Expand Down
4 changes: 4 additions & 0 deletions pvr.hts/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
v20.6.2
- Fixed cases where existing channels were treated by Kodi as deleted from backend.
(Info in Kodi log: "Removed stale channel foo from group bar")

v20.6.1
- Translations updates from Weblate
- ast_es, be_by, cs_cz, da_dk, de_de, es_es, fi_fi, fr_fr, hr_hr, it_it, pl_pl, vi_vn
Expand Down
65 changes: 39 additions & 26 deletions src/Tvheadend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,8 @@ PVR_ERROR CTvheadend::GetChannelsAmount(int& amount)
if (!m_asyncState.WaitForState(ASYNC_DVR))
return PVR_ERROR_FAILED;

std::lock_guard<std::recursive_mutex> lock(m_mutex);
amount = m_channels.size();

return PVR_ERROR_NO_ERROR;
}

Expand Down Expand Up @@ -377,6 +377,9 @@ PVR_ERROR CTvheadend::GetChannelStreamProperties(const kodi::addon::PVRChannel&
if (!m_settings->GetStreamingHTTP())
return PVR_ERROR_NO_ERROR;

if (!m_asyncState.WaitForState(ASYNC_DVR))
return PVR_ERROR_FAILED;

std::lock_guard<std::recursive_mutex> lock(m_mutex);

auto it = m_channels.find(channel.GetUniqueId());
Expand Down Expand Up @@ -748,6 +751,9 @@ PVR_ERROR CTvheadend::GetRecordingLastPlayedPosition(const kodi::addon::PVRRecor
if (m_conn->GetProtocol() < 27 || !m_settings->GetDvrPlayStatus())
return PVR_ERROR_NOT_IMPLEMENTED;

if (!m_asyncState.WaitForState(ASYNC_EPG))
return PVR_ERROR_FAILED;

std::lock_guard<std::recursive_mutex> lock(m_mutex);

const auto& it = m_recordings.find(std::stoul(rec.GetRecordingId()));
Expand Down Expand Up @@ -1201,6 +1207,9 @@ PVR_ERROR CTvheadend::AddTimer(const kodi::addon::PVRTimer& timer)

PVR_ERROR CTvheadend::DeleteTimer(const kodi::addon::PVRTimer& timer, bool)
{
if (!m_asyncState.WaitForState(ASYNC_EPG))
return PVR_ERROR_FAILED;

{
std::lock_guard<std::recursive_mutex> lock(m_mutex);

Expand Down Expand Up @@ -1288,6 +1297,9 @@ PVR_ERROR CTvheadend::UpdateTimer(const kodi::addon::PVRTimer& timer)
else if ((timer.GetTimerType() == TIMER_ONCE_CREATED_BY_TIMEREC) ||
(timer.GetTimerType() == TIMER_ONCE_CREATED_BY_AUTOREC))
{
if (!m_asyncState.WaitForState(ASYNC_EPG))
return PVR_ERROR_FAILED;

/* Read-only timer created by autorec or timerec */
std::lock_guard<std::recursive_mutex> lock(m_mutex);

Expand Down Expand Up @@ -1452,7 +1464,6 @@ PVR_ERROR CTvheadend::SetEPGMaxFutureDays(int iFutureDays)

void CTvheadend::Disconnected()
{
m_asyncState.SetState(ASYNC_NONE);
}

bool CTvheadend::Connected(std::unique_lock<std::recursive_mutex>& lock)
Expand All @@ -1476,7 +1487,8 @@ bool CTvheadend::Connected(std::unique_lock<std::recursive_mutex>& lock)
}

/* Request Async data, first is init (which rebuilds state) */
m_asyncState.SetState(ASYNC_INIT);
if (m_asyncState.GetState() == ASYNC_NONE)
m_asyncState.SetState(ASYNC_INIT);

htsmsg_t* msg = htsmsg_create_map();
if (m_settings->GetAsyncEpg())
Expand Down Expand Up @@ -1556,6 +1568,9 @@ PVR_ERROR CTvheadend::OnSystemWake()

bool CTvheadend::OpenRecordedStream(const kodi::addon::PVRRecording& rec)
{
if (!m_asyncState.WaitForState(ASYNC_EPG))
return false;

bool ret = m_vfs->Open(rec);

if (ret)
Expand Down Expand Up @@ -1859,29 +1874,13 @@ void CTvheadend::PushEpgEventUpdate(const Event& epg, EPG_EVENT_STATE state)
m_events.emplace_back(event);
}

void CTvheadend::SyncCompleted()
{
Logger::Log(LogLevel::LEVEL_INFO, "Async updates initialised");

/* The complete calls are probably redundant, but its a safety feature */
SyncInitCompleted();
SyncChannelsCompleted();
SyncDvrCompleted();
SyncEpgCompleted();
m_asyncState.SetState(ASYNC_DONE);
}

void CTvheadend::SyncInitCompleted()
{
/* check state engine */
if (m_asyncState.GetState() != ASYNC_INIT)
return;

/* Rebuild state */
for (auto* dmx : m_dmx)
dmx->RebuildState();

m_vfs->RebuildState();
m_timeRecordings.RebuildState();
m_autoRecordings.RebuildState();

Expand All @@ -1901,6 +1900,8 @@ void CTvheadend::SyncInitCompleted()

void CTvheadend::SyncChannelsCompleted()
{
SyncInitCompleted();

/* check state engine */
if (m_asyncState.GetState() != ASYNC_CHN)
return;
Expand All @@ -1922,6 +1923,8 @@ void CTvheadend::SyncChannelsCompleted()

void CTvheadend::SyncDvrCompleted()
{
SyncChannelsCompleted();

/* check state engine */
if (m_asyncState.GetState() != ASYNC_DVR)
return;
Expand Down Expand Up @@ -1959,6 +1962,8 @@ void CTvheadend::SyncDvrCompleted()

void CTvheadend::SyncEpgCompleted()
{
SyncDvrCompleted();

/* check state engine */
if (m_asyncState.GetState() != ASYNC_EPG)
return;
Expand Down Expand Up @@ -2010,6 +2015,20 @@ void CTvheadend::SyncEpgCompleted()
m_asyncState.SetState(ASYNC_DONE);
}

void CTvheadend::SyncCompleted()
{
for (auto* dmx : m_dmx)
dmx->RebuildState();

m_vfs->RebuildState();

SyncEpgCompleted();

m_asyncState.SetState(ASYNC_DONE);

Logger::Log(LogLevel::LEVEL_INFO, "Async updates initialised");
}

void CTvheadend::ParseTagAddOrUpdate(htsmsg_t* msg, bool bAdd)
{
/* Rebuild state upon arrival of first async data */
Expand Down Expand Up @@ -2206,9 +2225,6 @@ void CTvheadend::ParseChannelDelete(htsmsg_t* msg)

void CTvheadend::ParseRecordingAddOrUpdate(htsmsg_t* msg, bool bAdd)
{
/* Rebuild state upon arrival of first async data */
SyncInitCompleted();

/* Channels complete */
SyncChannelsCompleted();

Expand Down Expand Up @@ -2608,9 +2624,6 @@ void CTvheadend::ParseRecordingDelete(htsmsg_t* msg)

bool CTvheadend::ParseEvent(htsmsg_t* msg, bool bAdd, Event& evt)
{
/* Rebuild state upon arrival of first async data */
SyncInitCompleted();

/* Recordings complete */
SyncDvrCompleted();

Expand Down Expand Up @@ -2790,7 +2803,7 @@ void CTvheadend::ParseEventAddOrUpdate(htsmsg_t* msg, bool bAdd)
EventUids& events = sched.GetEvents();

bool bUpdated = false;
if (bAdd && m_asyncState.GetState() < ASYNC_DONE)
if (bAdd && m_asyncState.GetState() == ASYNC_DONE)
{
// After a reconnect, during processing of "enableAsyncMetadata" htsp
// method, tvheadend sends all events as "added". Check whether we
Expand Down

0 comments on commit b6b9368

Please sign in to comment.