summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Hung <marklh9@gmail.com>2019-03-01 10:09:30 +0800
committerMark Hung <marklh9@gmail.com>2019-03-04 14:32:15 +0100
commitd98d3e2a0bc087ec9157e8e32e9f0ea4207d36e2 (patch)
treed656dc2987effb49837cfdebb7219878ea5a76df
parent1b4cfd79240f153703a02d63639b3895ab7c1d1b (diff)
tdf#44223: Export the audio of effects and transitions.
This will allow to round trip the test case for the slide transition and the animation effect audio. Change-Id: Iac524e6bbcdb0a29491cfeba63121c845685fd11 Reviewed-on: https://gerrit.libreoffice.org/68540 Tested-by: Jenkins Reviewed-by: Mark Hung <marklh9@gmail.com>
-rw-r--r--sd/qa/unit/export-tests-ooxml2.cxx37
-rw-r--r--sd/qa/unit/import-tests.cxx27
-rw-r--r--sd/source/filter/eppt/epptooxml.hxx3
-rw-r--r--sd/source/filter/eppt/pptx-animations.cxx47
-rw-r--r--sd/source/filter/eppt/pptx-epptooxml.cxx73
5 files changed, 158 insertions, 29 deletions
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index ae60952752fc..eda6827a6869 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -198,6 +198,7 @@ public:
void testTdf119118();
void testTdf99213();
void testPotxExport();
+ void testTdf44223();
CPPUNIT_TEST_SUITE(SdOOXMLExportTest2);
@@ -278,6 +279,7 @@ public:
CPPUNIT_TEST(testTdf119118);
CPPUNIT_TEST(testTdf99213);
CPPUNIT_TEST(testPotxExport);
+ CPPUNIT_TEST(testTdf44223);
CPPUNIT_TEST_SUITE_END();
@@ -297,6 +299,7 @@ public:
{ "wp", "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" },
{ "p", "http://schemas.openxmlformats.org/presentationml/2006/main" },
{ "p14", "http://schemas.microsoft.com/office/powerpoint/2010/main" },
+ { "r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships" },
{ "w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main" },
{ "a14", "http://schemas.microsoft.com/office/drawing/2010/main" },
{ "wps", "http://schemas.microsoft.com/office/word/2010/wordprocessingShape" },
@@ -2066,6 +2069,40 @@ void SdOOXMLExportTest2::testPotxExport()
assertXPath(pContentTypes, "/ContentType:Types/ContentType:Override[@PartName='/ppt/presentation.xml']",
"ContentType", "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml");
}
+
+void SdOOXMLExportTest2::testTdf44223()
+{
+ utl::TempFile tempFile;
+ ::sd::DrawDocShellRef xDocShRef
+ = 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"));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(11140), pStream1->remainingSize());
+
+ std::shared_ptr<SvStream> const pStream2(parseExportStream(tempFile, "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",
+ "audio/x-wav");
+
+ assertXPath(pXmlContentType,
+ "/ContentType:Types/ContentType:Override[@PartName='/media/audio2.wav']",
+ "ContentType",
+ "audio/x-wav");
+
+ xmlDocPtr pDoc1 = parseExport(tempFile, "ppt/slides/slide1.xml");
+ assertXPath(pDoc1 , "//p:audio/p:cMediaNode/p:tgtEl/p:sndTgt[@r:embed]", 1);
+
+ xmlDocPtr pDoc2 = parseExport(tempFile, "ppt/slides/slide2.xml");
+ assertXPath(pDoc2 , "//p:transition/p:sndAc/p:stSnd/p:snd[@r:embed]", 2);
+
+ xDocShRef->DoClose();
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest2);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx
index 684dacbb7a84..44464e2559a2 100644
--- a/sd/qa/unit/import-tests.cxx
+++ b/sd/qa/unit/import-tests.cxx
@@ -44,8 +44,6 @@
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
#include <com/sun/star/document/XEventsSupplier.hpp>
-#include <com/sun/star/document/XStorageBasedDocument.hpp>
-#include <com/sun/star/embed/XStorage.hpp>
#include <com/sun/star/presentation/ClickAction.hpp>
#include <com/sun/star/presentation/XPresentationPage.hpp>
#include <com/sun/star/presentation/XPresentationSupplier.hpp>
@@ -194,7 +192,6 @@ public:
void testTdf123090();
void testTdf120028();
void testTdf120028b();
- void testTdf44223();
void testDescriptionImport();
void testTdf83247();
void testTdf47365();
@@ -282,7 +279,6 @@ public:
CPPUNIT_TEST(testTdf123090);
CPPUNIT_TEST(testTdf120028);
CPPUNIT_TEST(testTdf120028b);
- CPPUNIT_TEST(testTdf44223);
CPPUNIT_TEST(testDescriptionImport);
CPPUNIT_TEST(testTdf83247);
CPPUNIT_TEST(testTdf47365);
@@ -2632,29 +2628,6 @@ void SdImportTest::testTdf120028b()
xDocShRef->DoClose();
}
-void SdImportTest::testTdf44223()
-{
- ::sd::DrawDocShellRef xDocShRef
- = loadURL(m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/tdf44223.pptx"), PPTX);
- uno::Reference<document::XStorageBasedDocument> xSBD(xDocShRef->GetDoc()->getUnoModel(), uno::UNO_QUERY);
- CPPUNIT_ASSERT(xSBD.is());
-
- uno::Reference<embed::XStorage> xStorage = xSBD->getDocumentStorage();
- CPPUNIT_ASSERT(xStorage.is());
-
- uno::Reference<container::XNameAccess> xNameAccess(xStorage, uno::UNO_QUERY);
- CPPUNIT_ASSERT(xNameAccess.is());
-
- uno::Reference<embed::XStorage> xStorage_2(xNameAccess->getByName("Media"), uno::UNO_QUERY);
- CPPUNIT_ASSERT(xStorage_2.is());
- uno::Reference< container::XNameAccess > xNameAccess_2(xStorage_2, uno::UNO_QUERY);
-
- CPPUNIT_ASSERT(xNameAccess_2->hasByName("audio1.wav"));
- CPPUNIT_ASSERT(xNameAccess_2->hasByName("audio2.wav"));
-
- xDocShRef->DoClose();
-}
-
void SdImportTest::testDescriptionImport()
{
sd::DrawDocShellRef xDocShRef
diff --git a/sd/source/filter/eppt/epptooxml.hxx b/sd/source/filter/eppt/epptooxml.hxx
index 5d6be2286af9..5791c0249b24 100644
--- a/sd/source/filter/eppt/epptooxml.hxx
+++ b/sd/source/filter/eppt/epptooxml.hxx
@@ -76,6 +76,9 @@ public:
sal_Int32 GetShapeID(const css::uno::Reference<css::drawing::XShape>& rXShape);
sal_Int32 GetNextAnimationNodeID();
+
+ void embedEffectAudio(const FSHelperPtr& pFS, const OUString& sUrl, OUString& sRelId, OUString& sName);
+
private:
virtual void ImplWriteSlide( sal_uInt32 nPageNum, sal_uInt32 nMasterNum, sal_uInt16 nMode,
diff --git a/sd/source/filter/eppt/pptx-animations.cxx b/sd/source/filter/eppt/pptx-animations.cxx
index 7e0967d19789..d484fcc91cb0 100644
--- a/sd/source/filter/eppt/pptx-animations.cxx
+++ b/sd/source/filter/eppt/pptx-animations.cxx
@@ -41,6 +41,7 @@
#include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
#include <com/sun/star/animations/XAnimateColor.hpp>
#include <com/sun/star/animations/XCommand.hpp>
+#include <com/sun/star/animations/XAudio.hpp>
#include <com/sun/star/animations/XTransitionFilter.hpp>
#include <com/sun/star/animations/XIterateContainer.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
@@ -393,6 +394,9 @@ sal_Int32 extractNodeType(const Reference<XAnimationNode>& rXNode)
case AnimationNodeType::COMMAND:
xmlNodeType = XML_cmd;
break;
+ case AnimationNodeType::AUDIO:
+ xmlNodeType = XML_audio;
+ break;
default:
SAL_WARN("sd.eppt", "unhandled animation node: " << nType);
break;
@@ -615,6 +619,7 @@ class PPTXAnimationExport
void WriteAnimationNodeSeq();
void WriteAnimationNodeEffect();
void WriteAnimationNodeCommand();
+ void WriteAnimationNodeAudio();
void WriteAnimationNodeCommonPropsStart();
void WriteAnimationTarget(const Any& rTarget);
void WriteAnimationCondList(const Any& rAny, sal_Int32 nToken);
@@ -1144,6 +1149,39 @@ void PPTXAnimationExport::WriteAnimationNodeCommand()
mpFS->endElementNS(XML_p, XML_cmd);
}
+void PPTXAnimationExport::WriteAnimationNodeAudio()
+{
+ SAL_INFO("sd.eppt", "write animation node audio");
+ Reference<XAudio> xAudio(getCurrentNode(), UNO_QUERY);
+
+ OUString sUrl;
+ OUString sRelId;
+ OUString sName;
+
+ if (!(xAudio.is() && (xAudio->getSource() >>= sUrl) && !sUrl.isEmpty()
+ && sUrl.endsWithIgnoreAsciiCase(".wav")))
+ return;
+
+ mrPowerPointExport.embedEffectAudio(mpFS, sUrl, sRelId, sName);
+
+ mpFS->startElementNS(XML_p, XML_audio, FSEND);
+ mpFS->startElementNS(XML_p, XML_cMediaNode, FSEND);
+
+ mpFS->startElementNS(XML_p, XML_cTn, FSEND);
+ WriteAnimationCondList(mpContext->getCondition(true), XML_stCondLst);
+ WriteAnimationCondList(mpContext->getCondition(false), XML_endCondLst);
+ mpFS->endElementNS(XML_p, XML_cTn);
+
+ mpFS->startElementNS(XML_p, XML_tgtEl, FSEND);
+ mpFS->singleElementNS(XML_p, XML_sndTgt, FSNS(XML_r, XML_embed),
+ sRelId.isEmpty() ? nullptr : USS(sRelId), XML_name,
+ sUrl.isEmpty() ? nullptr : USS(sName), FSEND);
+ mpFS->endElementNS(XML_p, XML_tgtEl);
+
+ mpFS->endElementNS(XML_p, XML_cMediaNode);
+ mpFS->endElementNS(XML_p, XML_audio);
+}
+
void PPTXAnimationExport::WriteAnimationNode(const NodeContextPtr& pContext)
{
const NodeContext* pSavedContext = mpContext;
@@ -1178,6 +1216,9 @@ void PPTXAnimationExport::WriteAnimationNode(const NodeContextPtr& pContext)
case XML_cmd:
WriteAnimationNodeCommand();
break;
+ case XML_audio:
+ WriteAnimationNodeAudio();
+ break;
default:
SAL_WARN("sd.eppt", "export ooxml node type: " << xmlNodeType);
break;
@@ -1278,8 +1319,10 @@ void NodeContext::initValid(bool bHasValidChild, bool bIsIterateChild)
}
else if (nType == AnimationNodeType::AUDIO)
{
- SAL_WARN("sd.eppt", "Export AUDIO node is not supported yet.");
- mbValid = false;
+ Reference<XAudio> xAudio(mxNode, UNO_QUERY);
+ OUString sURL;
+ mbValid
+ = xAudio.is() && (xAudio->getSource() >>= sURL) && sURL.endsWithIgnoreAsciiCase(".wav");
}
else
{
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx
index b91c265b90bd..2d244f2fb523 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -115,6 +115,21 @@ public:
bool WritePlaceholder(const Reference< XShape >& xShape, PlaceholderType ePlaceholder, bool bMaster);
};
+
+namespace
+{
+void WriteSndAc(const FSHelperPtr& pFS, const OUString& sSoundRelId, const OUString& sSoundName)
+{
+ pFS->startElementNS(XML_p, XML_sndAc, FSEND);
+ pFS->startElementNS(XML_p, XML_stSnd, FSEND);
+ pFS->singleElementNS(XML_p, XML_snd,
+ FSNS(XML_r, XML_embed), sSoundRelId.isEmpty() ? nullptr : USS(sSoundRelId),
+ XML_name, sSoundName.isEmpty() ? nullptr : USS(sSoundName), FSEND);
+ pFS->endElement(FSNS(XML_p, XML_stSnd));
+ pFS->endElement(FSNS(XML_p, XML_sndAc));
+}
+}
+
}
}
@@ -546,6 +561,10 @@ void PowerPointExport::WriteTransition(const FSHelperPtr& pFS)
sal_Int8 nPPTTransitionType = 0;
sal_uInt8 nDirection = 0;
+ OUString sSoundUrl;
+ OUString sSoundRelId;
+ OUString sSoundName;
+
if (ImplGetPropertyValue(mXPagePropSet, "TransitionType") && (mAny >>= nTransitionType) &&
ImplGetPropertyValue(mXPagePropSet, "TransitionSubtype") && (mAny >>= nTransitionSubtype))
nPPTTransitionType = GetTransition(nTransitionType, nTransitionSubtype, eFadeEffect, nDirection);
@@ -553,6 +572,9 @@ void PowerPointExport::WriteTransition(const FSHelperPtr& pFS)
if (!nPPTTransitionType && eFadeEffect != FadeEffect_NONE)
nPPTTransitionType = GetTransition(eFadeEffect, nDirection);
+ if (ImplGetPropertyValue(mXPagePropSet, "Sound") && (mAny >>= sSoundUrl))
+ embedEffectAudio(pFS, sSoundUrl, sSoundRelId, sSoundName);
+
bool bOOXmlSpecificTransition = false;
sal_Int32 nTransition = 0;
@@ -866,6 +888,9 @@ void PowerPointExport::WriteTransition(const FSHelperPtr& pFS)
FSEND);
}
+ if (!sSoundRelId.isEmpty())
+ WriteSndAc(pFS, sSoundRelId, sSoundName);
+
pFS->endElement(FSNS(XML_p, XML_transition));
pFS->endElement(FSNS(XML_mc, XML_Choice));
@@ -887,6 +912,9 @@ void PowerPointExport::WriteTransition(const FSHelperPtr& pFS)
FSEND);
}
+ if (!sSoundRelId.isEmpty())
+ WriteSndAc(pFS, sSoundRelId, sSoundName);
+
pFS->endElementNS(XML_p, XML_transition);
if (nTransition14 || pPresetTransition || isTransitionDurationSet)
@@ -1935,6 +1963,51 @@ void PowerPointExport::WriteNotesMaster()
SAL_INFO("sd.eppt", "----------------");
}
+void PowerPointExport::embedEffectAudio(const FSHelperPtr& pFS, const OUString& sUrl, OUString& sRelId, OUString& sName)
+{
+ comphelper::LifecycleProxy aProxy;
+
+ if (!sUrl.endsWithIgnoreAsciiCase(".wav"))
+ return;
+
+ uno::Reference<io::XInputStream> xAudioStream;
+ if (sUrl.startsWith("vnd.sun.star.Package:"))
+ {
+ uno::Reference<document::XStorageBasedDocument> xStorageBasedDocument(getModel(), uno::UNO_QUERY);
+ if (!xStorageBasedDocument.is())
+ return;
+
+ uno::Reference<embed::XStorage> xDocumentStorage(xStorageBasedDocument->getDocumentStorage(), uno::UNO_QUERY);
+ if (!xDocumentStorage.is())
+ return;
+
+ uno::Reference<io::XStream> xStream = comphelper::OStorageHelper::GetStreamAtPackageURL(xDocumentStorage, sUrl,
+ css::embed::ElementModes::READ, aProxy);
+
+ if (xStream.is())
+ xAudioStream = xStream->getInputStream();
+ }
+ else
+ xAudioStream = comphelper::OStorageHelper::GetInputStreamFromURL(sUrl, getComponentContext());
+
+ if (!xAudioStream.is())
+ return;
+
+ int nLastSlash = sUrl.lastIndexOf('/');
+ sName = sUrl.copy(nLastSlash >= 0 ? nLastSlash + 1 : 0);
+
+ 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");
+
+ comphelper::OStorageHelper::CopyInputToOutput(xAudioStream, xOutputStream);
+}
+
sal_Int32 PowerPointExport::GetShapeID(const Reference<XShape>& rXShape)
{
return ShapeExport::GetShapeID(rXShape, &maShapeMap);