aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorenen92 <92enen@gmail.com>2022-04-08 18:11:35 +0100
committerenen92 <92enen@gmail.com>2022-04-10 11:52:32 +0100
commita248001523c50f39470b4376c2d833f281260336 (patch)
tree9f9c14bb1cf29badc5890cbabf84a943ed4b8b8d
parent5144e72e4ba4071e138387bbe42c06ffb1e97e6a (diff)
[dvdnav] reimplement dvdstateserializer logic
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamNavigator.cpp87
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamNavigator.h12
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/DVDStateSerializer.cpp332
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/DVDStateSerializer.h58
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/DllDvdNav.h16
-rw-r--r--xbmc/cores/VideoPlayer/VideoPlayer.cpp6
6 files changed, 219 insertions, 292 deletions
diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamNavigator.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamNavigator.cpp
index 701747a3a3..d9ee08e033 100644
--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamNavigator.cpp
+++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamNavigator.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2018 Team Kodi
+ * Copyright (C) 2005-2022 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,7 +10,6 @@
#include "filesystem/IFileTypes.h"
#include "utils/LangCodeExpander.h"
#include "../DVDDemuxSPU.h"
-#include "DVDStateSerializer.h"
#include "settings/Settings.h"
#include "settings/SettingsComponent.h"
#include "LangInfo.h"
@@ -1129,12 +1128,12 @@ int CDVDInputStreamNavigator::GetActiveAngle()
int number_of_angles;
int current_angle;
- dvdnav_status_t status = m_dll.dvdnav_get_angle_info(m_dvdnav, &current_angle, &number_of_angles);
-
- if (status == DVDNAV_STATUS_OK)
- return current_angle;
- else
+ if (m_dll.dvdnav_get_angle_info(m_dvdnav, &current_angle, &number_of_angles) == DVDNAV_STATUS_ERR)
+ {
+ CLog::LogF(LOGERROR, "Failed to get current angle: {}", m_dll.dvdnav_err_to_string(m_dvdnav));
return -1;
+ }
+ return current_angle;
}
bool CDVDInputStreamNavigator::SetAngle(int angle)
@@ -1301,60 +1300,82 @@ bool CDVDInputStreamNavigator::IsSubtitleStreamEnabled()
return m_dll.dvdnav_get_active_spu_stream(m_dvdnav) >= 0;
}
-bool CDVDInputStreamNavigator::GetState(std::string &xmlstate)
+bool CDVDInputStreamNavigator::FillDVDState(DVDState& dvdState)
{
- if( !m_dvdnav )
+ if (!m_dvdnav)
+ {
return false;
+ }
- dvd_state_t save_state;
- if( DVDNAV_STATUS_ERR == m_dll.dvdnav_get_state(m_dvdnav, &save_state) )
+ if (m_dll.dvdnav_current_title_program(m_dvdnav, &dvdState.title, &dvdState.pgcn,
+ &dvdState.pgn) == DVDNAV_STATUS_ERR)
{
- CLog::Log(LOGWARNING, "CDVDInputStreamNavigator::GetNavigatorState - Failed to get state ({})",
- m_dll.dvdnav_err_to_string(m_dvdnav));
+ CLog::LogF(LOGERROR, "Failed to get current title info ({})",
+ m_dll.dvdnav_err_to_string(m_dvdnav));
return false;
}
- if( !CDVDStateSerializer::DVDToXMLState(xmlstate, &save_state) )
+ int current_angle = GetActiveAngle();
+ if (current_angle == -1)
{
- CLog::Log(LOGWARNING, "CDVDInputStreamNavigator::SetNavigatorState - Failed to serialize state");
+ CLog::LogF(LOGERROR, "Could not detect current angle, ignoring saved state");
return false;
}
+ dvdState.current_angle = current_angle;
+ dvdState.audio_num = GetActiveAudioStream();
+ dvdState.subp_num = GetActiveSubtitleStream();
+ dvdState.sub_enabled = IsSubtitleStreamEnabled();
return true;
}
-bool CDVDInputStreamNavigator::SetState(const std::string &xmlstate)
+bool CDVDInputStreamNavigator::GetState(std::string& xmlstate)
{
if( !m_dvdnav )
+ {
return false;
+ }
- dvd_state_t save_state = {};
+ // do not save state if we are not playing a title stream (e.g. if we are in menus)
+ if (!m_dll.dvdnav_is_domain_vts(m_dvdnav))
+ {
+ return false;
+ }
- if( !CDVDStateSerializer::XMLToDVDState(&save_state, xmlstate) )
+ DVDState dvdState;
+ if (!FillDVDState(dvdState))
{
- CLog::Log(LOGWARNING, "CDVDInputStreamNavigator::SetNavigatorState - Failed to deserialize state");
+ CLog::LogF(LOGWARNING, "Failed to obtain current dvdnav state");
return false;
}
- if( DVDNAV_STATUS_ERR == m_dll.dvdnav_set_state(m_dvdnav, &save_state) )
+ if (!m_dvdStateSerializer.DVDStateToXML(xmlstate, dvdState))
{
CLog::Log(LOGWARNING,
- "CDVDInputStreamNavigator::SetNavigatorState - Failed to set state ({}), retrying "
- "after read",
- m_dll.dvdnav_err_to_string(m_dvdnav));
+ "CDVDInputStreamNavigator::SetNavigatorState - Failed to serialize state");
+ return false;
+ }
- /* vm won't be started until after first read, this should really be handled internally */
- uint8_t buffer[DVD_VIDEO_BLOCKSIZE];
- Read(buffer,DVD_VIDEO_BLOCKSIZE);
+ return true;
+}
- if( DVDNAV_STATUS_ERR == m_dll.dvdnav_set_state(m_dvdnav, &save_state) )
- {
- CLog::Log(LOGWARNING,
- "CDVDInputStreamNavigator::SetNavigatorState - Failed to set state ({})",
- m_dll.dvdnav_err_to_string(m_dvdnav));
- return false;
- }
+bool CDVDInputStreamNavigator::SetState(const std::string& xmlstate)
+{
+ if (!m_dvdnav)
+ return false;
+
+ DVDState dvdState;
+ if (!m_dvdStateSerializer.XMLToDVDState(dvdState, xmlstate))
+ {
+ CLog::LogF(LOGWARNING, "Failed to deserialize state");
+ return false;
}
+
+ m_dll.dvdnav_program_play(m_dvdnav, dvdState.title, dvdState.pgcn, dvdState.pgn);
+ m_dll.dvdnav_angle_change(m_dvdnav, dvdState.current_angle);
+ SetActiveSubtitleStream(dvdState.subp_num);
+ SetActiveAudioStream(dvdState.audio_num);
+ EnableSubtitleStream(dvdState.sub_enabled);
return true;
}
diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamNavigator.h b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamNavigator.h
index 0b6cb640ff..77621f8f59 100644
--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamNavigator.h
+++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamNavigator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2018 Team Kodi
+ * Copyright (C) 2005-2022 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
@@ -13,6 +13,7 @@
#include "DVDDemuxers/DVDDemux.h"
#include "DVDInputStream.h"
#include "DVDInputStreamFile.h"
+#include "DVDStateSerializer.h"
#include "DllDvdNav.h"
#include "utils/Geometry.h"
@@ -129,6 +130,12 @@ protected:
int GetAngleCount();
void GetVideoResolution(uint32_t * width, uint32_t * height);
+ /*! \brief Provided a pod DVDState struct, fill it with the current dvdnav state
+ * \param[in,out] dvdstate the DVD state struct to be filled
+ * \return true if it was possible to fill the state struct based on the current dvdnav state, false otherwise
+ */
+ bool FillDVDState(DVDState& dvdstate);
+
DllDvdNav m_dll;
bool m_bCheckButtons;
bool m_bEOF;
@@ -161,5 +168,8 @@ protected:
int m_lastevent;
std::map<int, std::map<int, int64_t>> m_mapTitleChapters;
+
+ /*! DVD state serializer handler */
+ CDVDStateSerializer m_dvdStateSerializer;
};
diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDStateSerializer.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDStateSerializer.cpp
index 140a29b6d9..c09779bae2 100644
--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDStateSerializer.cpp
+++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDStateSerializer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2018 Team Kodi
+ * Copyright (C) 2005-2022 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
@@ -8,179 +8,34 @@
#include "DVDStateSerializer.h"
-#include "DllDvdNav.h"
+#include "utils/StringUtils.h"
#include "utils/XBMCTinyXML.h"
+#include "utils/log.h"
+#include <charconv>
+#include <cstring>
#include <sstream>
-bool CDVDStateSerializer::test( const dvd_state_t *state )
+namespace
{
- dvd_state_t state2 = {};
- std::string buffer;
-
- DVDToXMLState(buffer, state);
-
- XMLToDVDState( &state2, buffer);
-
- return memcmp( &state2, state, sizeof( dvd_state_t )) == 0;
-
+// Serializer version - used to avoid processing deprecated/legacy schemas
+constexpr int DVDSTATESERIALIZER_VERSION = 2;
}
-bool CDVDStateSerializer::DVDToXMLState( std::string &xmlstate, const dvd_state_t *state )
+bool CDVDStateSerializer::DVDStateToXML(std::string& xmlstate, const DVDState& state)
{
- char buffer[256];
- CXBMCTinyXML xmlDoc("navstate");
-
- TiXmlElement eRoot("navstate");
- eRoot.SetAttribute("version", 1);
-
-
- { TiXmlElement eRegisters("registers");
-
- for( int i = 0; i < 24; i++ )
- {
-
- if( state->registers.SPRM[i] )
- { TiXmlElement eReg("sprm");
- eReg.SetAttribute("index", i);
-
- { TiXmlElement eValue("value");
- sprintf(buffer, "0x%hx", state->registers.SPRM[i]);
- eValue.InsertEndChild( TiXmlText(buffer) );
- eReg.InsertEndChild(eValue);
- }
-
- eRegisters.InsertEndChild(eReg);
- }
- }
-
- for( int i = 0; i < 16; i++ )
- {
- if( state->registers.GPRM[i] || state->registers.GPRM_mode[i] || state->registers.GPRM_time[i].tv_sec || state->registers.GPRM_time[i].tv_usec )
- { TiXmlElement eReg("gprm");
- eReg.SetAttribute("index", i);
-
- { TiXmlElement eValue("value");
- sprintf(buffer, "0x%hx", state->registers.GPRM[i]);
- eValue.InsertEndChild( TiXmlText(buffer) );
- eReg.InsertEndChild(eValue);
- }
-
- { TiXmlElement eMode("mode");
- sprintf(buffer, "0x%c", state->registers.GPRM_mode[i]);
- eMode.InsertEndChild( TiXmlText(buffer) );
- eReg.InsertEndChild(eMode);
- }
-
- { TiXmlElement eTime("time");
- { TiXmlElement eValue("tv_sec");
- sprintf(buffer, "%ld", state->registers.GPRM_time[i].tv_sec);
- eValue.InsertEndChild( TiXmlText( buffer ) );
- eTime.InsertEndChild( eValue ) ;
- }
-
- { TiXmlElement eValue("tv_usec");
- sprintf(buffer, "%ld", (long int)state->registers.GPRM_time[i].tv_usec);
- eValue.InsertEndChild( TiXmlText( buffer ) );
- eTime.InsertEndChild( eValue ) ;
- }
- eReg.InsertEndChild(eTime);
- }
- eRegisters.InsertEndChild(eReg);
- }
- }
- eRoot.InsertEndChild(eRegisters);
- }
-
- { TiXmlElement element("domain");
- sprintf(buffer, "%d", state->domain);
- element.InsertEndChild( TiXmlText( buffer ) );
- eRoot.InsertEndChild(element);
- }
-
- { TiXmlElement element("vtsn");
- sprintf(buffer, "%d", state->vtsN);
- element.InsertEndChild( TiXmlText( buffer ) );
- eRoot.InsertEndChild(element);
- }
-
- { TiXmlElement element("pgcn");
- sprintf(buffer, "%d", state->pgcN);
- element.InsertEndChild( TiXmlText( buffer ) );
- eRoot.InsertEndChild(element);
- }
-
- { TiXmlElement element("pgn");
- sprintf(buffer, "%d", state->pgN);
- element.InsertEndChild( TiXmlText( buffer ) );
- eRoot.InsertEndChild(element);
- }
-
- { TiXmlElement element("celln");
- sprintf(buffer, "%d", state->cellN);
- element.InsertEndChild( TiXmlText( buffer ) );
- eRoot.InsertEndChild(element);
- }
-
- { TiXmlElement element("cell_restart");
- sprintf(buffer, "%d", state->cell_restart);
- element.InsertEndChild( TiXmlText( buffer ) );
- eRoot.InsertEndChild(element);
- }
-
- { TiXmlElement element("blockn");
- sprintf(buffer, "%d", state->blockN);
- element.InsertEndChild( TiXmlText( buffer ) );
- eRoot.InsertEndChild(element);
- }
-
- { TiXmlElement rsm("rsm");
-
- { TiXmlElement element("vtsn");
- sprintf(buffer, "%d", state->rsm_vtsN);
- element.InsertEndChild( TiXmlText( buffer ) );
- rsm.InsertEndChild(element);
- }
-
- { TiXmlElement element("blockn");
- sprintf(buffer, "%d", state->rsm_blockN);
- element.InsertEndChild( TiXmlText( buffer ) );
- rsm.InsertEndChild(element);
- }
-
- { TiXmlElement element("pgcn");
- sprintf(buffer, "%d", state->rsm_pgcN);
- element.InsertEndChild( TiXmlText( buffer ) );
- rsm.InsertEndChild(element);
- }
-
- { TiXmlElement element("celln");
- sprintf(buffer, "%d", state->rsm_cellN);
- element.InsertEndChild( TiXmlText( buffer ) );
- rsm.InsertEndChild(element);
- }
-
- { TiXmlElement regs("registers");
-
- for( int i = 0; i < 5; i++ )
- {
- TiXmlElement reg("sprm");
- reg.SetAttribute("index", i);
-
- { TiXmlElement element("value");
- sprintf(buffer, "0x%hx", state->rsm_regs[i]);
- element.InsertEndChild( TiXmlText(buffer) );
- reg.InsertEndChild(element);
- }
-
- regs.InsertEndChild(reg);
- }
- rsm.InsertEndChild(regs);
- }
- eRoot.InsertEndChild(rsm);
- }
-
-
+ CXBMCTinyXML xmlDoc{"navstate"};
+
+ TiXmlElement eRoot{"navstate"};
+ eRoot.SetAttribute("version", DVDSTATESERIALIZER_VERSION);
+
+ AddXMLElement(eRoot, "title", std::to_string(state.title));
+ AddXMLElement(eRoot, "pgn", std::to_string(state.pgn));
+ AddXMLElement(eRoot, "pgcn", std::to_string(state.pgcn));
+ AddXMLElement(eRoot, "current_angle", std::to_string(state.current_angle));
+ AddXMLElement(eRoot, "audio_num", std::to_string(state.audio_num));
+ AddXMLElement(eRoot, "subp_num", std::to_string(state.subp_num));
+ AddXMLElement(eRoot, "sub_enabled", state.sub_enabled ? "true" : "false");
xmlDoc.InsertEndChild(eRoot);
std::stringstream stream;
@@ -189,105 +44,84 @@ bool CDVDStateSerializer::DVDToXMLState( std::string &xmlstate, const dvd_state_
return true;
}
-bool CDVDStateSerializer::XMLToDVDState( dvd_state_t *state, const std::string &xmlstate )
+bool CDVDStateSerializer::XMLToDVDState(DVDState& state, const std::string& xmlstate)
{
CXBMCTinyXML xmlDoc;
xmlDoc.Parse(xmlstate);
-
- if( xmlDoc.Error() )
+ if (xmlDoc.Error())
return false;
- TiXmlHandle hRoot( xmlDoc.RootElement() );
- if( strcmp( hRoot.Element()->Value(), "navstate" ) != 0 ) return false;
-
- TiXmlElement *element = NULL;
- TiXmlText *text = NULL;
- int index = 0;
-
- element = hRoot.FirstChildElement("registers").FirstChildElement("sprm").Element();
- while( element )
+ TiXmlHandle hRoot(xmlDoc.RootElement());
+ if (!hRoot.Element() || !StringUtils::EqualsNoCase(hRoot.Element()->Value(), "navstate"))
{
- element->Attribute("index", &index);
-
- text = TiXmlHandle( element ).FirstChildElement("value").FirstChild().Text();
- if( text && index >= 0 && index < 24 )
- sscanf(text->Value(), "0x%hx", &state->registers.SPRM[index]);
+ CLog::LogF(LOGERROR, "Failed to deserialize dvd state - failed to detect root element.");
+ return false;
+ }
- element = element->NextSiblingElement("sprm");
+ auto version = hRoot.Element()->Attribute("version");
+ if (!version || !StringUtils::EqualsNoCase(version, std::to_string(DVDSTATESERIALIZER_VERSION)))
+ {
+ CLog::LogF(LOGERROR, "Failed to deserialize dvd state - incompatible serializer version.");
+ return false;
}
- element = hRoot.FirstChildElement("registers").FirstChildElement("gprm").Element();
- while( element )
+ const TiXmlElement* childElement = hRoot.Element()->FirstChildElement();
+ while (childElement)
{
- element->Attribute("index", &index);
- if( index >= 0 && index < 16 )
+ const std::string property = childElement->Value();
+ if (property == "title")
{
- text = TiXmlHandle( element ).FirstChildElement("value").FirstChild().Text();
- if( text )
- sscanf(text->Value(), "0x%hx", &state->registers.GPRM[index]);
-
- text = TiXmlHandle( element ).FirstChildElement("mode").FirstChild().Text();
- if( text )
- sscanf(text->Value(), "0x%c", &state->registers.GPRM_mode[index]);
-
- text = TiXmlHandle( element ).FirstChildElement("time").FirstChildElement("tv_sec").FirstChild().Text();
- if( text )
- sscanf(text->Value(), "%ld", &state->registers.GPRM_time[index].tv_sec);
-
- text = TiXmlHandle( element ).FirstChildElement("time").FirstChildElement("tv_usec").FirstChild().Text();
- if( text )
- sscanf(text->Value(), "%ld", (long int*)&state->registers.GPRM_time[index].tv_usec);
+ std::from_chars(childElement->GetText(),
+ childElement->GetText() + std::strlen(childElement->GetText()), state.title);
}
- element = element->NextSiblingElement("gprm");
- }
-
- if( (text = hRoot.FirstChildElement("domain").FirstChild().Text()) )
- sscanf(text->Value(), "%d", (int*) &state->domain);
-
- if( (text = hRoot.FirstChildElement("vtsn").FirstChild().Text()) )
- sscanf(text->Value(), "%d", &state->vtsN);
-
- if( (text = hRoot.FirstChildElement("pgcn").FirstChild().Text()) )
- sscanf(text->Value(), "%d", &state->pgcN);
-
- if( (text = hRoot.FirstChildElement("pgn").FirstChild().Text()) )
- sscanf(text->Value(), "%d", &state->pgN);
-
- if( (text = hRoot.FirstChildElement("celln").FirstChild().Text()) )
- sscanf(text->Value(), "%d", &state->cellN);
-
- if( (text = hRoot.FirstChildElement("cell_restart").FirstChild().Text()) )
- sscanf(text->Value(), "%d", &state->cell_restart);
-
- if( (text = hRoot.FirstChildElement("blockn").FirstChild().Text()) )
- sscanf(text->Value(), "%d", &state->blockN);
-
- { TiXmlHandle hrsm = hRoot.FirstChildElement("rsm");
-
- if( (text = hrsm.FirstChildElement("vtsn").FirstChild().Text()) )
- sscanf(text->Value(), "%d", &state->rsm_vtsN);
-
- if( (text = hrsm.FirstChildElement("blockn").FirstChild().Text()) )
- sscanf(text->Value(), "%d", &state->rsm_blockN);
-
- if( (text = hrsm.FirstChildElement("pgcn").FirstChild().Text()) )
- sscanf(text->Value(), "%d", &state->rsm_pgcN);
-
- if( (text = hrsm.FirstChildElement("celln").FirstChild().Text()) )
- sscanf(text->Value(), "%d", &state->rsm_cellN);
-
- element = hrsm.FirstChildElement("registers").FirstChildElement("sprm").Element();
- while( element )
+ else if (property == "pgn")
{
- element->Attribute("index", &index);
- text = TiXmlHandle(element).FirstChildElement("value").FirstChild().Text();
- if( text && index >= 0 && index < 5 )
- sscanf(text->Value(), "0x%hx", &state->rsm_regs[index]);
-
- element = element->NextSiblingElement("sprm");
+ std::from_chars(childElement->GetText(),
+ childElement->GetText() + std::strlen(childElement->GetText()), state.pgn);
}
+ else if (property == "pgcn")
+ {
+ std::from_chars(childElement->GetText(),
+ childElement->GetText() + std::strlen(childElement->GetText()), state.pgcn);
+ }
+ else if (property == "current_angle")
+ {
+ std::from_chars(childElement->GetText(),
+ childElement->GetText() + std::strlen(childElement->GetText()),
+ state.current_angle);
+ }
+ else if (property == "subp_num")
+ {
+ std::from_chars(childElement->GetText(),
+ childElement->GetText() + std::strlen(childElement->GetText()),
+ state.subp_num);
+ }
+ else if (property == "audio_num")
+ {
+ std::from_chars(childElement->GetText(),
+ childElement->GetText() + std::strlen(childElement->GetText()),
+ state.audio_num);
+ }
+ else if (property == "sub_enabled")
+ {
+ state.sub_enabled = StringUtils::EqualsNoCase(childElement->GetText(), "true");
+ }
+ else
+ {
+ CLog::LogF(LOGWARNING, "Unmapped dvd state property {}, ignored.", childElement->Value());
+ }
+ childElement = childElement->NextSiblingElement();
}
return true;
}
+void CDVDStateSerializer::AddXMLElement(TiXmlElement& root,
+ const std::string& name,
+ const std::string& value)
+{
+ TiXmlElement xmlElement{name};
+ TiXmlText xmlElementValue = value;
+ xmlElement.InsertEndChild(xmlElementValue);
+ root.InsertEndChild(xmlElement);
+}
diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDStateSerializer.h b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDStateSerializer.h
index 822bf14b6b..debba101dc 100644
--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDStateSerializer.h
+++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDStateSerializer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2018 Team Kodi
+ * Copyright (C) 2005-2022 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
@@ -8,16 +8,60 @@
#pragma once
-#include "DllDvdNav.h"
-
#include <string>
+class TiXmlElement;
+
+/*! \brief Pod structure which represents the current dvd state with respect to dvdnav properties */
+struct DVDState
+{
+ /*! The current title being played */
+ int32_t title = -1;
+ /*! Program number */
+ int32_t pgn = -1;
+ /*! Program cell number */
+ int32_t pgcn = -1;
+ /*! Current playing angle */
+ int32_t current_angle = -1;
+ /*! Physical subtitle id set in dvdnav */
+ int8_t subp_num = -1;
+ /*! Physical audio stream id set in dvdnav */
+ int8_t audio_num = -1;
+ /*! If subtitles are enabled or disabled */
+ bool sub_enabled = false;
+};
+
+/*! \brief Auxiliar class to serialize/deserialize the dvd state (into/from XML)
+*/
class CDVDStateSerializer
{
public:
- static bool DVDToXMLState( std::string &xmlstate, const dvd_state_t *state );
- static bool XMLToDVDState( dvd_state_t *state, const std::string &xmlstate );
+ /*! \brief Default constructor */
+ CDVDStateSerializer() = default;
- static bool test( const dvd_state_t *state );
-};
+ /*! \brief Default destructor */
+ ~CDVDStateSerializer() = default;
+
+ /*! \brief Provided the state in xml format, fills a DVDState struct representing the DVD state and returns the
+ * success status of the operation
+ * \param[in,out] state the DVD state struct to be filled
+ * \param xmlstate a string describing the dvd state (XML)
+ * \return true if it was possible to fill the state struct based on the XML content, false otherwise
+ */
+ bool XMLToDVDState(DVDState& state, const std::string& xmlstate);
+ /*! \brief Provided the DVDState struct of the current playing dvd, serializes the struct to XML
+ * \param[in,out] xmlstate a string describing the dvd state (XML)
+ * \param state the DVD state struct
+ * \return true if it was possible to serialize the struct into XML, false otherwise
+ */
+ bool DVDStateToXML(std::string& xmlstate, const DVDState& state);
+
+private:
+ /*! \brief Appends a new element with the given name and value to a provided root XML element
+ * \param[in,out] root the root xml element to append the new element
+ * \param name the new element name
+ * \param value the new element value
+ */
+ void AddXMLElement(TiXmlElement& root, const std::string& name, const std::string& value);
+};
diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DllDvdNav.h b/xbmc/cores/VideoPlayer/DVDInputStreams/DllDvdNav.h
index c567b76328..745a7a9884 100644
--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DllDvdNav.h
+++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DllDvdNav.h
@@ -101,6 +101,14 @@ public:
virtual int64_t dvdnav_get_current_time(dvdnav_t* self) = 0;
virtual void dvdnav_free(void* pdata) = 0;
virtual int dvdnav_get_video_resolution(dvdnav_t* self, uint32_t* width, uint32_t* height)=0;
+ virtual dvdnav_status_t dvdnav_program_play(dvdnav_t* self,
+ int32_t title,
+ int32_t pgcn,
+ int32_t pgn) = 0;
+ virtual dvdnav_status_t dvdnav_current_title_program(dvdnav_t* self,
+ int32_t* title,
+ int32_t* pgcn,
+ int32_t* pgn) = 0;
};
class DllDvdNav : public DllDynamic, DllDvdNavInterface
@@ -169,6 +177,12 @@ class DllDvdNav : public DllDynamic, DllDvdNavInterface
DEFINE_METHOD2(dvdnav_status_t, dvdnav_get_title_string, (dvdnav_t *p1, const char **p2))
DEFINE_METHOD2(dvdnav_status_t, dvdnav_get_serial_string, (dvdnav_t *p1, const char **p2))
DEFINE_METHOD4(uint32_t, dvdnav_describe_title_chapters, (dvdnav_t* p1, uint32_t p2, uint64_t** p3, uint64_t* p4))
+ DEFINE_METHOD4(dvdnav_status_t,
+ dvdnav_program_play,
+ (dvdnav_t * p1, int32_t p2, int32_t p3, int32_t p4))
+ DEFINE_METHOD4(dvdnav_status_t,
+ dvdnav_current_title_program,
+ (dvdnav_t * p1, int32_t* p2, int32_t* p3, int32_t* p4))
DEFINE_METHOD1(int64_t, dvdnav_get_current_time, (dvdnav_t* p1))
DEFINE_METHOD1(void, dvdnav_free, (void *p1))
DEFINE_METHOD3(int, dvdnav_get_video_resolution, (dvdnav_t* p1, uint32_t* p2, uint32_t* p3))
@@ -209,6 +223,8 @@ class DllDvdNav : public DllDynamic, DllDvdNavInterface
RESOLVE_METHOD(dvdnav_next_pg_search)
RESOLVE_METHOD(dvdnav_get_highlight_area)
RESOLVE_METHOD(dvdnav_go_up)
+ RESOLVE_METHOD(dvdnav_program_play)
+ RESOLVE_METHOD(dvdnav_current_title_program)
RESOLVE_METHOD(dvdnav_get_active_audio_stream)
RESOLVE_METHOD(dvdnav_audio_stream_to_lang)
RESOLVE_METHOD(dvdnav_get_vm)
diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
index 39944ad2db..ec324b6e9e 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp
+++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
@@ -1223,13 +1223,15 @@ void CVideoPlayer::Prepare()
if (std::shared_ptr<CDVDInputStream::IMenus> ptr = std::dynamic_pointer_cast<CDVDInputStream::IMenus>(m_pInputStream))
{
CLog::Log(LOGINFO, "VideoPlayer: playing a file with menu's");
- if(std::dynamic_pointer_cast<CDVDInputStreamNavigator>(m_pInputStream))
- m_playerOptions.starttime = 0;
if (!m_playerOptions.state.empty())
+ {
discStateRestored = ptr->SetState(m_playerOptions.state);
+ }
else if(std::shared_ptr<CDVDInputStreamNavigator> nav = std::dynamic_pointer_cast<CDVDInputStreamNavigator>(m_pInputStream))
+ {
nav->EnableSubtitleStream(m_processInfo->GetVideoSettings().m_SubtitleOn);
+ }
}
if (!OpenDemuxStream())