diff options
author | Mark Hung <marklh9@gmail.com> | 2019-04-27 19:02:25 +0800 |
---|---|---|
committer | Mark Hung <marklh9@gmail.com> | 2019-04-30 15:03:19 +0200 |
commit | b593634d3cfbb2fc8522d99ce1c3f2a11445ea59 (patch) | |
tree | 290fea894a03fd9779b064dd7c5ec04b5b120a35 /sd | |
parent | 83abdf803a023067ebc207fd82dde987df233754 (diff) |
tdf#124230 pptx: make exported animation sound work.
1. Fix target path for the embedded media. Move the media
file to /ppt/media ( was /media ) and use the relative path
../media for the target path when adding the relation. This
is necessary for MSO to play the sound.
2. Write timenode id for the start or end conditions if the
animation node for the begin event or the end event is
available. Events like BEGIN or END has to refer a timenode.
Without specifying referred timenode in start and end
condition, Impress will not activate the audio node after
importing the document.
Change-Id: I6027be2e836e2f86061e401c8af806b2b1993a49
Reviewed-on: https://gerrit.libreoffice.org/71427
Tested-by: Jenkins
Reviewed-by: Mark Hung <marklh9@gmail.com>
Diffstat (limited to 'sd')
-rw-r--r-- | sd/qa/unit/export-tests-ooxml2.cxx | 15 | ||||
-rw-r--r-- | sd/source/filter/eppt/pptx-animations.cxx | 39 | ||||
-rw-r--r-- | sd/source/filter/eppt/pptx-epptooxml.cxx | 5 |
3 files changed, 50 insertions, 9 deletions
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx index 7c27e0a315cc..66c6154f1da2 100644 --- a/sd/qa/unit/export-tests-ooxml2.cxx +++ b/sd/qa/unit/export-tests-ooxml2.cxx @@ -2087,31 +2087,38 @@ void SdOOXMLExportTest2::testTdf44223() = loadURL(m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/tdf44223.pptx"), PPTX); xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile); - std::shared_ptr<SvStream> const pStream1(parseExportStream(tempFile, "media/audio1.wav")); + std::shared_ptr<SvStream> const pStream1(parseExportStream(tempFile, "ppt/media/audio1.wav")); CPPUNIT_ASSERT_EQUAL(sal_uInt64(11140), pStream1->remainingSize()); - std::shared_ptr<SvStream> const pStream2(parseExportStream(tempFile, "media/audio2.wav")); + std::shared_ptr<SvStream> const pStream2(parseExportStream(tempFile, "ppt/media/audio2.wav")); CPPUNIT_ASSERT_EQUAL(sal_uInt64(28074), pStream2->remainingSize()); xmlDocPtr pXmlContentType = parseExport(tempFile, "[Content_Types].xml"); assertXPath(pXmlContentType, - "/ContentType:Types/ContentType:Override[@PartName='/media/audio1.wav']", + "/ContentType:Types/ContentType:Override[@PartName='/ppt/media/audio1.wav']", "ContentType", "audio/x-wav"); assertXPath(pXmlContentType, - "/ContentType:Types/ContentType:Override[@PartName='/media/audio2.wav']", + "/ContentType:Types/ContentType:Override[@PartName='/ppt/media/audio2.wav']", "ContentType", "audio/x-wav"); xmlDocPtr pDoc1 = parseExport(tempFile, "ppt/slides/slide1.xml"); + // Start condition: 0s after timenode id 5 begins. assertXPath(pDoc1 , "//p:audio/p:cMediaNode/p:cTn/p:stCondLst/p:cond", "evt", "begin"); assertXPath(pDoc1 , "//p:audio/p:cMediaNode/p:cTn/p:stCondLst/p:cond", "delay", "0"); + assertXPath(pDoc1 , "//p:audio/p:cMediaNode/p:cTn/p:stCondLst/p:cond/p:tn", "val", "5"); xmlDocPtr pDoc2 = parseExport(tempFile, "ppt/slides/slide2.xml"); assertXPath(pDoc2 , "//p:transition/p:sndAc/p:stSnd/p:snd[@r:embed]", 2); + xmlDocPtr pRels1 = parseExport(tempFile, "ppt/slides/_rels/slide1.xml.rels"); + assertXPath(pRels1, "//rels:Relationship[@Id='rId1']", "Type", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/audio"); + assertXPath(pRels1, "//rels:Relationship[@Id='rId1']", "Target", "../media/audio1.wav"); + xDocShRef->DoClose(); } diff --git a/sd/source/filter/eppt/pptx-animations.cxx b/sd/source/filter/eppt/pptx-animations.cxx index a8c062b5c7df..da5223c50ec7 100644 --- a/sd/source/filter/eppt/pptx-animations.cxx +++ b/sd/source/filter/eppt/pptx-animations.cxx @@ -59,6 +59,7 @@ #include "pptexanimations.hxx" #include "pptx-animations.hxx" #include "../ppt/pptanimations.hxx" +#include <comphelper/stl_types.hxx> using namespace ::com::sun::star::animations; using namespace ::com::sun::star::container; @@ -569,6 +570,7 @@ struct Cond OString msDelay; const char* mpEvent; Reference<XShape> mxShape; + Reference<XAnimationNode> mxNode; Cond(const Any& rAny, bool bIsMainSeqChild); @@ -596,7 +598,8 @@ Cond::Cond(const Any& rAny, bool bIsMainSeqChild) else { mpEvent = convertEventTrigger(aEvent.Trigger); - aEvent.Source >>= mxShape; + if (!(aEvent.Source >>= mxShape)) + aEvent.Source >>= mxNode; if (aEvent.Offset >>= fDelay) bHasFDelay = true; @@ -632,6 +635,11 @@ class PPTXAnimationExport const FSHelperPtr& mpFS; const NodeContext* mpContext; + std::map<Reference<XAnimationNode>, sal_Int32, ::comphelper::OInterfaceCompare<XAnimationNode>> + maAnimationNodeIdMap; + sal_Int32 GetNextAnimationNodeId(const Reference<XAnimationNode>& rNode); + sal_Int32 GetAnimationNodeId(const Reference<XAnimationNode>& rNode); + public: PPTXAnimationExport(PowerPointExport& rExport, const FSHelperPtr& pFS); void WriteAnimations(const Reference<XDrawPage>& rXDrawPage); @@ -751,6 +759,7 @@ void PPTXAnimationExport::WriteAnimationCondList(const Any& rAny, sal_Int32 nTok void PPTXAnimationExport::WriteAnimationCond(const Cond& rCond) { + sal_Int32 nId = -1; if (rCond.mpEvent) { if (rCond.mxShape.is()) @@ -760,6 +769,13 @@ void PPTXAnimationExport::WriteAnimationCond(const Cond& rCond) WriteAnimationTarget(makeAny(rCond.mxShape)); mpFS->endElementNS(XML_p, XML_cond); } + else if (rCond.mxNode.is() && (nId = GetAnimationNodeId(rCond.mxNode)) != -1) + { + mpFS->startElementNS(XML_p, XML_cond, XML_delay, rCond.getDelay(), XML_evt, + rCond.mpEvent); + mpFS->singleElementNS(XML_p, XML_tn, XML_val, OString::number(nId)); + mpFS->endElementNS(XML_p, XML_cond); + } else { mpFS->singleElementNS(XML_p, XML_cond, XML_delay, rCond.getDelay(), XML_evt, @@ -1041,8 +1057,7 @@ void PPTXAnimationExport::WriteAnimationNodeCommonPropsStart() bool bAutoReverse = rXNode->getAutoReverse(); mpFS->startElementNS( - XML_p, XML_cTn, XML_id, OString::number(mrPowerPointExport.GetNextAnimationNodeID()), - XML_dur, + XML_p, XML_cTn, XML_id, OString::number(GetNextAnimationNodeId(rXNode)), XML_dur, fDuration != 0 ? OString::number(static_cast<sal_Int32>(fDuration * 1000.0)).getStr() : pDuration, XML_autoRev, bAutoReverse ? "1" : nullptr, XML_restart, pRestart, XML_nodeType, pNodeType, @@ -1261,6 +1276,24 @@ void PPTXAnimationExport::WriteAnimations(const Reference<XDrawPage>& rXDrawPage } } +sal_Int32 PPTXAnimationExport::GetNextAnimationNodeId(const Reference<XAnimationNode>& xNode) +{ + sal_Int32 nId = mrPowerPointExport.GetNextAnimationNodeID(); + maAnimationNodeIdMap[xNode] = nId; + return nId; +} + +sal_Int32 PPTXAnimationExport::GetAnimationNodeId(const Reference<XAnimationNode>& xNode) +{ + sal_Int32 nId = -1; + const auto& aIter = maAnimationNodeIdMap.find(xNode); + if (aIter != maAnimationNodeIdMap.end()) + { + nId = aIter->second; + } + return nId; +} + NodeContext::NodeContext(const Reference<XAnimationNode>& xNode, bool bMainSeqChild, bool bIsIterateChild) : mxNode(xNode) diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx index abe09c4a8964..a7d51cfcd57e 100644 --- a/sd/source/filter/eppt/pptx-epptooxml.cxx +++ b/sd/source/filter/eppt/pptx-epptooxml.cxx @@ -1971,14 +1971,15 @@ void PowerPointExport::embedEffectAudio(const FSHelperPtr& pFS, const OUString& int nLastSlash = sUrl.lastIndexOf('/'); sName = sUrl.copy(nLastSlash >= 0 ? nLastSlash + 1 : 0); - OUString sPath = OUStringBuffer().append("/media/") + OUString sPath = OUStringBuffer().append("../media/") .append(sName) .makeStringAndClear(); sRelId = addRelation(pFS->getOutputStream(), oox::getRelationship(Relationship::AUDIO), sPath); - uno::Reference<io::XOutputStream> xOutputStream = openFragmentStream(sPath, "audio/x-wav"); + uno::Reference<io::XOutputStream> xOutputStream = openFragmentStream(sPath.replaceAt(0, 2, "/ppt"), + "audio/x-wav"); comphelper::OStorageHelper::CopyInputToOutput(xAudioStream, xOutputStream); } |