Kaydet (Commit) 220a3686 authored tarafından Michael Stahl's avatar Michael Stahl

oox: refactor embedded media import

Currently the oox import creates a temp file and leaks it, and there is
no way to clean it up afterwards.  Unfortunately it turns out that
SdrModel has no way to access the imported OOXML storage, so add a
really ugly hack to get the embedded media into the SdrMediaObj by
setting both MediaURL and PrivateStream properties (currently oox really
wants to set the properties in alphabetical order too...)

Change-Id: I5a235fbeb08e7bc17faf066de52b94867e9a79a2
üst 8b7f96d2
...@@ -72,6 +72,7 @@ public: ...@@ -72,6 +72,7 @@ public:
getSnapshot(); getSnapshot();
::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream> ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>
GetInputStream(); GetInputStream();
void SetInputStream(css::uno::Reference<css::io::XInputStream> const&);
protected: protected:
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include <sal/config.h> #include <sal/config.h>
#include <com/sun/star/io/XInputStream.hpp>
#include <oox/drawingml/fillproperties.hxx> #include <oox/drawingml/fillproperties.hxx>
#include <oox/helper/helper.hxx> #include <oox/helper/helper.hxx>
...@@ -36,7 +38,8 @@ namespace drawingml { ...@@ -36,7 +38,8 @@ namespace drawingml {
struct GraphicProperties struct GraphicProperties
{ {
BlipFillProperties maBlipProps; ///< Properties for the graphic. BlipFillProperties maBlipProps; ///< Properties for the graphic.
OUString msMediaTempFile; ///< Audio/Video temporary file. OUString m_sMediaPackageURL; ///< Audio/Video URL.
css::uno::Reference<css::io::XInputStream> m_xMediaStream; ///< Audio/Video input stream.
/** Overwrites all members that are explicitly set in rSourceProps. */ /** Overwrites all members that are explicitly set in rSourceProps. */
void assignUsed( const GraphicProperties& rSourceProps ); void assignUsed( const GraphicProperties& rSourceProps );
......
...@@ -753,8 +753,12 @@ void GraphicProperties::pushToPropMap( PropertyMap& rPropMap, const GraphicHelpe ...@@ -753,8 +753,12 @@ void GraphicProperties::pushToPropMap( PropertyMap& rPropMap, const GraphicHelpe
rPropMap.setProperty(PROP_AdjustContrast, nContrast); rPropMap.setProperty(PROP_AdjustContrast, nContrast);
// Media content // Media content
if( !msMediaTempFile.isEmpty() ) assert(m_xMediaStream.is() != m_sMediaPackageURL.isEmpty());
rPropMap.setProperty(PROP_MediaURL, msMediaTempFile); if (m_xMediaStream.is() && !m_sMediaPackageURL.isEmpty())
{
rPropMap.setProperty(PROP_PrivateStream, m_xMediaStream);
rPropMap.setProperty(PROP_MediaURL, m_sMediaPackageURL);
}
} }
bool ArtisticEffectProperties::isEmpty() const bool ArtisticEffectProperties::isEmpty() const
......
...@@ -49,20 +49,19 @@ using namespace ::com::sun::star::beans; ...@@ -49,20 +49,19 @@ using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::xml::sax; using namespace ::com::sun::star::xml::sax;
using namespace ::oox::core; using namespace ::oox::core;
static OUString lcl_CopyToTempFile(const OUString& rStream, const oox::core::XmlFilterBase& rFilter) static uno::Reference<io::XInputStream>
lcl_GetMediaStream(const OUString& rStream, const oox::core::XmlFilterBase& rFilter)
{ {
if (rStream.isEmpty()) if (rStream.isEmpty())
return OUString(); return nullptr;
Reference< XInputStream > xInStrm( rFilter.openInputStream(rStream), UNO_SET_THROW ); Reference< XInputStream > xInStrm( rFilter.openInputStream(rStream), UNO_SET_THROW );
Reference< XTempFile > xTempFile( TempFile::create(rFilter.getComponentContext()) ); return xInStrm;
Reference< XOutputStream > xOutStrm( xTempFile->getOutputStream(), UNO_SET_THROW ); }
oox::BinaryXOutputStream aOutStrm( xOutStrm, false );
oox::BinaryXInputStream aInStrm( xInStrm, false ); static OUString lcl_GetMediaReference(const OUString& rStream)
aInStrm.copyToStream( aOutStrm ); {
return rStream.isEmpty() ? OUString() : "vnd.sun.star.Package:" + rStream;
xTempFile->setRemoveFile( false );
return xTempFile->getUri();
} }
namespace oox { namespace oox {
...@@ -86,8 +85,11 @@ ContextHandlerRef GraphicShapeContext::onCreateContext( sal_Int32 aElementToken, ...@@ -86,8 +85,11 @@ ContextHandlerRef GraphicShapeContext::onCreateContext( sal_Int32 aElementToken,
return new BlipFillContext( *this, rAttribs, mpShapePtr->getGraphicProperties().maBlipProps ); return new BlipFillContext( *this, rAttribs, mpShapePtr->getGraphicProperties().maBlipProps );
case XML_wavAudioFile: case XML_wavAudioFile:
{ {
mpShapePtr->getGraphicProperties().msMediaTempFile = OUString const path(getEmbeddedWAVAudioFile(getRelations(), rAttribs));
lcl_CopyToTempFile( getEmbeddedWAVAudioFile(getRelations(), rAttribs), getFilter() ); mpShapePtr->getGraphicProperties().m_xMediaStream =
lcl_GetMediaStream(path, getFilter());
mpShapePtr->getGraphicProperties().m_sMediaPackageURL =
lcl_GetMediaReference(path);
} }
break; break;
case XML_audioFile: case XML_audioFile:
...@@ -95,8 +97,10 @@ ContextHandlerRef GraphicShapeContext::onCreateContext( sal_Int32 aElementToken, ...@@ -95,8 +97,10 @@ ContextHandlerRef GraphicShapeContext::onCreateContext( sal_Int32 aElementToken,
{ {
OUString rPath = getRelations().getFragmentPathFromRelId( OUString rPath = getRelations().getFragmentPathFromRelId(
rAttribs.getString(R_TOKEN(link)).get() ); rAttribs.getString(R_TOKEN(link)).get() );
mpShapePtr->getGraphicProperties().msMediaTempFile = mpShapePtr->getGraphicProperties().m_xMediaStream =
lcl_CopyToTempFile( rPath, getFilter() ); lcl_GetMediaStream(rPath, getFilter());
mpShapePtr->getGraphicProperties().m_sMediaPackageURL =
lcl_GetMediaReference(rPath);
} }
break; break;
} }
......
...@@ -405,7 +405,7 @@ Reference< XShape > Shape::createAndInsert( ...@@ -405,7 +405,7 @@ Reference< XShape > Shape::createAndInsert(
OUString aServiceName; OUString aServiceName;
if( rServiceName == "com.sun.star.drawing.GraphicObjectShape" && if( rServiceName == "com.sun.star.drawing.GraphicObjectShape" &&
mpGraphicPropertiesPtr && !mpGraphicPropertiesPtr->msMediaTempFile.isEmpty() ) mpGraphicPropertiesPtr && !mpGraphicPropertiesPtr->m_sMediaPackageURL.isEmpty())
{ {
aServiceName = finalizeServiceName( rFilterBase, "com.sun.star.presentation.MediaShape", aShapeRectHmm ); aServiceName = finalizeServiceName( rFilterBase, "com.sun.star.presentation.MediaShape", aShapeRectHmm );
bIsEmbMedia = true; bIsEmbMedia = true;
......
...@@ -808,6 +808,7 @@ void SdImportTest::testBnc591147() ...@@ -808,6 +808,7 @@ void SdImportTest::testBnc591147()
OUString sVideoURL("emptyURL"); OUString sVideoURL("emptyURL");
bool bSucess = xPropSet->getPropertyValue("MediaURL") >>= sVideoURL; bool bSucess = xPropSet->getPropertyValue("MediaURL") >>= sVideoURL;
CPPUNIT_ASSERT_MESSAGE( "MediaURL property is not set", bSucess ); CPPUNIT_ASSERT_MESSAGE( "MediaURL property is not set", bSucess );
CPPUNIT_ASSERT_MESSAGE("MediaURL is empty", !sVideoURL.isEmpty());
// Second page has audio file inserted // Second page has audio file inserted
xPage.set( xDoc->getDrawPages()->getByIndex(1), uno::UNO_QUERY_THROW ); xPage.set( xDoc->getDrawPages()->getByIndex(1), uno::UNO_QUERY_THROW );
...@@ -818,6 +819,7 @@ void SdImportTest::testBnc591147() ...@@ -818,6 +819,7 @@ void SdImportTest::testBnc591147()
OUString sAudioURL("emptyURL"); OUString sAudioURL("emptyURL");
bSucess = xPropSet->getPropertyValue("MediaURL") >>= sAudioURL; bSucess = xPropSet->getPropertyValue("MediaURL") >>= sAudioURL;
CPPUNIT_ASSERT_MESSAGE( "MediaURL property is not set", bSucess ); CPPUNIT_ASSERT_MESSAGE( "MediaURL property is not set", bSucess );
CPPUNIT_ASSERT_MESSAGE("MediaURL is empty", !sAudioURL.isEmpty());
CPPUNIT_ASSERT_MESSAGE( "sAudioURL and sVideoURL should not be equal", sAudioURL != sVideoURL ); CPPUNIT_ASSERT_MESSAGE( "sAudioURL and sVideoURL should not be equal", sAudioURL != sVideoURL );
......
...@@ -66,6 +66,7 @@ struct SdrMediaObj::Impl ...@@ -66,6 +66,7 @@ struct SdrMediaObj::Impl
::avmedia::MediaItem m_MediaProperties; ::avmedia::MediaItem m_MediaProperties;
::boost::shared_ptr< MediaTempFile > m_pTempFile; ::boost::shared_ptr< MediaTempFile > m_pTempFile;
uno::Reference< graphic::XGraphic > m_xCachedSnapshot; uno::Reference< graphic::XGraphic > m_xCachedSnapshot;
OUString m_LastFailedPkgURL;
}; };
TYPEINIT1( SdrMediaObj, SdrRectObj ); TYPEINIT1( SdrMediaObj, SdrRectObj );
...@@ -326,6 +327,53 @@ static bool lcl_HandleJsonPackageURL( ...@@ -326,6 +327,53 @@ static bool lcl_HandleJsonPackageURL(
} }
#endif #endif
static bool lcl_CopyToTempFile(
uno::Reference<io::XInputStream> const& xInStream,
OUString & o_rTempFileURL)
{
OUString tempFileURL;
::osl::FileBase::RC const err =
::osl::FileBase::createTempFile(0, 0, & tempFileURL);
if (::osl::FileBase::E_None != err)
{
SAL_INFO("svx", "cannot create temp file");
return false;
}
try
{
::ucbhelper::Content tempContent(tempFileURL,
uno::Reference<ucb::XCommandEnvironment>(),
comphelper::getProcessComponentContext());
tempContent.writeStream(xInStream, true); // copy stream to file
}
catch (uno::Exception const& e)
{
SAL_WARN("svx", "exception: '" << e.Message << "'");
return false;
}
o_rTempFileURL = tempFileURL;
return true;
}
void SdrMediaObj::SetInputStream(uno::Reference<io::XInputStream> const& xStream)
{
if (m_pImpl->m_pTempFile || m_pImpl->m_LastFailedPkgURL.isEmpty())
{
SAL_WARN("svx", "this is only intended for embedded media");
return;
}
OUString tempFileURL;
bool const bSuccess = lcl_CopyToTempFile(xStream, tempFileURL);
if (bSuccess)
{
m_pImpl->m_pTempFile.reset(new MediaTempFile(tempFileURL));
m_pImpl->m_MediaProperties.setURL(
m_pImpl->m_LastFailedPkgURL, tempFileURL, "");
}
m_pImpl->m_LastFailedPkgURL = ""; // once only
}
/// copy a stream from XStorage to temp file /// copy a stream from XStorage to temp file
static bool lcl_HandlePackageURL( static bool lcl_HandlePackageURL(
OUString const & rURL, OUString const & rURL,
...@@ -357,30 +405,7 @@ static bool lcl_HandlePackageURL( ...@@ -357,30 +405,7 @@ static bool lcl_HandlePackageURL(
SAL_WARN("svx", "no stream?"); SAL_WARN("svx", "no stream?");
return false; return false;
} }
return lcl_CopyToTempFile(xInStream, o_rTempFileURL);
OUString tempFileURL;
::osl::FileBase::RC const err =
::osl::FileBase::createTempFile(0, 0, & tempFileURL);
if (::osl::FileBase::E_None != err)
{
SAL_INFO("svx", "cannot create temp file");
return false;
}
try
{
::ucbhelper::Content tempContent(tempFileURL,
uno::Reference<ucb::XCommandEnvironment>(),
comphelper::getProcessComponentContext());
tempContent.writeStream(xInStream, true); // copy stream to file
}
catch (uno::Exception const& e)
{
SAL_WARN("svx", "exception: '" << e.Message << "'");
return false;
}
o_rTempFileURL = tempFileURL;
return true;
} }
void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProperties ) void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProperties )
...@@ -420,6 +445,9 @@ void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProper ...@@ -420,6 +445,9 @@ void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProper
{ {
m_pImpl->m_pTempFile.reset(); m_pImpl->m_pTempFile.reset();
m_pImpl->m_MediaProperties.setURL("", "", ""); m_pImpl->m_MediaProperties.setURL("", "", "");
// UGLY: oox import also gets here, because unlike ODF
// getDocumentStorage() is not the imported file...
m_pImpl->m_LastFailedPkgURL = url;
} }
} }
else else
......
...@@ -730,7 +730,7 @@ SfxItemPropertyMapEntry const * ImplGetSvxMediaShapePropertyMap() ...@@ -730,7 +730,7 @@ SfxItemPropertyMapEntry const * ImplGetSvxMediaShapePropertyMap()
// #i68101# // #i68101#
{ OUString(UNO_NAME_MISC_OBJ_TITLE), OWN_ATTR_MISC_OBJ_TITLE , cppu::UnoType<OUString>::get(), 0, 0}, { OUString(UNO_NAME_MISC_OBJ_TITLE), OWN_ATTR_MISC_OBJ_TITLE , cppu::UnoType<OUString>::get(), 0, 0},
{ OUString(UNO_NAME_MISC_OBJ_DESCRIPTION), OWN_ATTR_MISC_OBJ_DESCRIPTION , cppu::UnoType<OUString>::get(), 0, 0}, { OUString(UNO_NAME_MISC_OBJ_DESCRIPTION), OWN_ATTR_MISC_OBJ_DESCRIPTION , cppu::UnoType<OUString>::get(), 0, 0},
{OUString("PrivateStream"), OWN_ATTR_MEDIA_STREAM, cppu::UnoType<css::io::XInputStream>::get(), ::com::sun::star::beans::PropertyAttribute::READONLY, 0}, {OUString("PrivateStream"), OWN_ATTR_MEDIA_STREAM, cppu::UnoType<css::io::XInputStream>::get(), 0, 0},
{OUString("PrivateTempFileURL"), OWN_ATTR_MEDIA_TEMPFILEURL, cppu::UnoType<OUString>::get(), ::com::sun::star::beans::PropertyAttribute::READONLY, 0}, {OUString("PrivateTempFileURL"), OWN_ATTR_MEDIA_TEMPFILEURL, cppu::UnoType<OUString>::get(), ::com::sun::star::beans::PropertyAttribute::READONLY, 0},
{ OUString("MediaMimeType"), OWN_ATTR_MEDIA_MIMETYPE, cppu::UnoType<OUString>::get(), 0, 0}, { OUString("MediaMimeType"), OWN_ATTR_MEDIA_MIMETYPE, cppu::UnoType<OUString>::get(), 0, 0},
{ OUString("FallbackGraphic"), OWN_ATTR_FALLBACK_GRAPHIC, cppu::UnoType<css::graphic::XGraphic>::get(), ::com::sun::star::beans::PropertyAttribute::READONLY, 0}, { OUString("FallbackGraphic"), OWN_ATTR_FALLBACK_GRAPHIC, cppu::UnoType<css::graphic::XGraphic>::get(), ::com::sun::star::beans::PropertyAttribute::READONLY, 0},
......
...@@ -808,6 +808,7 @@ SvxMediaShape::~SvxMediaShape() throw() ...@@ -808,6 +808,7 @@ SvxMediaShape::~SvxMediaShape() throw()
bool SvxMediaShape::setPropertyValueImpl( const OUString& rName, const SfxItemPropertySimpleEntry* pProperty, const ::com::sun::star::uno::Any& rValue ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) bool SvxMediaShape::setPropertyValueImpl( const OUString& rName, const SfxItemPropertySimpleEntry* pProperty, const ::com::sun::star::uno::Any& rValue ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
{ {
if( ((pProperty->nWID >= OWN_ATTR_MEDIA_URL) && (pProperty->nWID <= OWN_ATTR_MEDIA_ZOOM)) if( ((pProperty->nWID >= OWN_ATTR_MEDIA_URL) && (pProperty->nWID <= OWN_ATTR_MEDIA_ZOOM))
|| (pProperty->nWID == OWN_ATTR_MEDIA_STREAM)
|| (pProperty->nWID == OWN_ATTR_MEDIA_MIMETYPE) ) || (pProperty->nWID == OWN_ATTR_MEDIA_MIMETYPE) )
{ {
SdrMediaObj* pMedia = static_cast< SdrMediaObj* >( mpObj.get() ); SdrMediaObj* pMedia = static_cast< SdrMediaObj* >( mpObj.get() );
...@@ -886,6 +887,31 @@ bool SvxMediaShape::setPropertyValueImpl( const OUString& rName, const SfxItemPr ...@@ -886,6 +887,31 @@ bool SvxMediaShape::setPropertyValueImpl( const OUString& rName, const SfxItemPr
} }
break; break;
case OWN_ATTR_MEDIA_STREAM:
try
{
uno::Reference<io::XInputStream> xStream;
if (rValue >>= xStream)
{
pMedia->SetInputStream(xStream);
}
}
catch (const css::ucb::ContentCreationException& e)
{
throw css::lang::WrappedTargetException(
"ContentCreationException Setting InputStream!",
static_cast<OWeakObject *>(this),
makeAny(e));
}
catch (const css::ucb::CommandFailedException& e)
{
throw css::lang::WrappedTargetException(
"CommandFailedException Setting InputStream!",
static_cast<OWeakObject *>(this),
makeAny(e));
}
break;
default: default:
OSL_FAIL("SvxMediaShape::setPropertyValueImpl(), unknown argument!"); OSL_FAIL("SvxMediaShape::setPropertyValueImpl(), unknown argument!");
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment