diff options
author | enen92 <92enen@gmail.com> | 2022-04-08 18:11:35 +0100 |
---|---|---|
committer | enen92 <92enen@gmail.com> | 2022-04-10 11:52:32 +0100 |
commit | a248001523c50f39470b4376c2d833f281260336 (patch) | |
tree | 9f9c14bb1cf29badc5890cbabf84a943ed4b8b8d | |
parent | 5144e72e4ba4071e138387bbe42c06ffb1e97e6a (diff) |
[dvdnav] reimplement dvdstateserializer logic
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, ¤t_angle, &number_of_angles); - - if (status == DVDNAV_STATUS_OK) - return current_angle; - else + if (m_dll.dvdnav_get_angle_info(m_dvdnav, ¤t_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()) |