summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sd/qa/filter/eppt/data/video-loop.pptxbin0 -> 46545 bytes
-rw-r--r--sd/qa/filter/eppt/eppt.cxx26
-rw-r--r--sd/source/filter/eppt/pptx-animations.cxx47
3 files changed, 65 insertions, 8 deletions
diff --git a/sd/qa/filter/eppt/data/video-loop.pptx b/sd/qa/filter/eppt/data/video-loop.pptx
new file mode 100644
index 000000000000..4cb7e20b7428
--- /dev/null
+++ b/sd/qa/filter/eppt/data/video-loop.pptx
Binary files differ
diff --git a/sd/qa/filter/eppt/eppt.cxx b/sd/qa/filter/eppt/eppt.cxx
index 1e8e2c7e1491..151b9cfce27a 100644
--- a/sd/qa/filter/eppt/eppt.cxx
+++ b/sd/qa/filter/eppt/eppt.cxx
@@ -125,6 +125,32 @@ CPPUNIT_TEST_FIXTURE(Test, testThemeExport)
// i.e. the RGB color was lost on export.
xComponent->dispose();
}
+
+CPPUNIT_TEST_FIXTURE(Test, testLoopingFromAnimation)
+{
+ // Given a media shape that has an animation that specifies looping for the video:
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "video-loop.pptx";
+ getComponent() = loadFromDesktop(aURL);
+
+ // When exporting that to PPTX:
+ utl::TempFile aTempFile;
+ uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("Impress Office Open XML");
+ aTempFile.EnableKillingFile();
+ xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+ validate(aTempFile.GetFileName(), test::OOXML);
+
+ // Then make sure that the "infinite" repeat count is written:
+ std::unique_ptr<SvStream> pStream = parseExportStream(aTempFile, "ppt/slides/slide1.xml");
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
+ // Without the fix in place, this test would have failed with:
+ // - Expected: 1
+ // - Actual : 0
+ // - In <>, XPath '//p:cMediaNode/p:cTn' number of nodes is incorrect
+ // i.e. the media node was lost on export, the video no longer looped.
+ assertXPath(pXmlDoc, "//p:cMediaNode/p:cTn", "repeatCount", "indefinite");
+}
}
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/source/filter/eppt/pptx-animations.cxx b/sd/source/filter/eppt/pptx-animations.cxx
index 54dab17d1972..1c901573c00a 100644
--- a/sd/source/filter/eppt/pptx-animations.cxx
+++ b/sd/source/filter/eppt/pptx-animations.cxx
@@ -659,6 +659,9 @@ bool IsAudioURL(const OUString& rURL)
{
return rURL.endsWithIgnoreAsciiCase(".wav") || rURL.endsWithIgnoreAsciiCase(".m4a");
}
+
+/// Returns if rURL has an extension which is a video format.
+bool IsVideoURL(const OUString& rURL) { return rURL.endsWithIgnoreAsciiCase(".mp4"); }
}
namespace oox::core
@@ -1235,6 +1238,7 @@ void PPTXAnimationExport::WriteAnimationNodeAudio()
bValid = true;
}
+ bool bVideo = false;
if (!bValid)
{
if (xAudio->getSource() >>= xShape)
@@ -1243,7 +1247,8 @@ void PPTXAnimationExport::WriteAnimationNodeAudio()
bool bHasMediaURL = xShapeProps->getPropertySetInfo()->hasPropertyByName("MediaURL");
if (bHasMediaURL && (xShapeProps->getPropertyValue("MediaURL") >>= sUrl))
{
- bValid = IsAudioURL(sUrl);
+ bVideo = IsVideoURL(sUrl);
+ bValid = IsAudioURL(sUrl) || bVideo;
}
}
}
@@ -1256,12 +1261,31 @@ void PPTXAnimationExport::WriteAnimationNodeAudio()
mrPowerPointExport.embedEffectAudio(mpFS, sUrl, sRelId, sName);
}
- bool bNarration = xAudio->getNarration();
- mpFS->startElementNS(XML_p, XML_audio, XML_isNarration, bNarration ? "1" : "0");
- bool bHideDuringShow = xAudio->getHideDuringShow();
- mpFS->startElementNS(XML_p, XML_cMediaNode, XML_showWhenStopped, bHideDuringShow ? "0" : "1");
+ if (bVideo)
+ {
+ mpFS->startElementNS(XML_p, XML_video);
+ mpFS->startElementNS(XML_p, XML_cMediaNode);
+ }
+ else
+ {
+ bool bNarration = xAudio->getNarration();
+ mpFS->startElementNS(XML_p, XML_audio, XML_isNarration, bNarration ? "1" : "0");
+ bool bHideDuringShow = xAudio->getHideDuringShow();
+ mpFS->startElementNS(XML_p, XML_cMediaNode, XML_showWhenStopped,
+ bHideDuringShow ? "0" : "1");
+ }
- mpFS->startElementNS(XML_p, XML_cTn);
+ animations::Timing eTiming{};
+ bool bLooping
+ = (xAudio->getRepeatCount() >>= eTiming) && eTiming == animations::Timing_INDEFINITE;
+ if (bVideo && bLooping)
+ {
+ mpFS->startElementNS(XML_p, XML_cTn, XML_repeatCount, "indefinite");
+ }
+ else
+ {
+ mpFS->startElementNS(XML_p, XML_cTn);
+ }
WriteAnimationCondList(mpContext->getCondition(true), XML_stCondLst);
WriteAnimationCondList(mpContext->getCondition(false), XML_endCondLst);
mpFS->endElementNS(XML_p, XML_cTn);
@@ -1281,7 +1305,14 @@ void PPTXAnimationExport::WriteAnimationNodeAudio()
mpFS->endElementNS(XML_p, XML_tgtEl);
mpFS->endElementNS(XML_p, XML_cMediaNode);
- mpFS->endElementNS(XML_p, XML_audio);
+ if (bVideo)
+ {
+ mpFS->endElementNS(XML_p, XML_video);
+ }
+ else
+ {
+ mpFS->endElementNS(XML_p, XML_audio);
+ }
}
void PPTXAnimationExport::WriteAnimationNode(const NodeContextPtr& pContext)
@@ -1456,7 +1487,7 @@ void NodeContext::initValid(bool bHasValidChild, bool bIsIterateChild)
= xShapeProps->getPropertySetInfo()->hasPropertyByName("MediaURL");
if (bHasMediaURL && (xShapeProps->getPropertyValue("MediaURL") >>= sURL))
{
- mbValid = IsAudioURL(sURL);
+ mbValid = IsAudioURL(sURL) || IsVideoURL(sURL);
}
}
}