Kaydet (Commit) 6b6c0b12 authored tarafından Mark Hung's avatar Mark Hung

tdf#44223 allow slideshow to play embedded media.

Implement MediaFileManager that create the temp media
file for package urls when making slideshow.

Change-Id: I10a5ddc405928b4322ad72eb603508faf25bf0db
Reviewed-on: https://gerrit.libreoffice.org/67209
Tested-by: Jenkins
Reviewed-by: 's avatarMark Hung <marklh9@gmail.com>
üst 8a132136
......@@ -38,6 +38,7 @@
#include <comphelper/processfactory.hxx>
#include <comphelper/storagehelper.hxx>
#include <mediamisc.hxx>
#include <osl/file.hxx>
using namespace ::com::sun::star;
......@@ -475,6 +476,50 @@ bool EmbedMedia(uno::Reference<frame::XModel> const& xModel,
return false;
}
bool CreateMediaTempFile(uno::Reference<io::XInputStream> const& xInStream,
OUString& o_rTempFileURL, const OUString& rDesiredExtension)
{
OUString tempFileURL;
::osl::FileBase::RC const err =
::osl::FileBase::createTempFile(nullptr, nullptr, & tempFileURL);
if (::osl::FileBase::E_None != err)
{
SAL_WARN("avmedia", "cannot create temp file");
return false;
}
if (!rDesiredExtension.isEmpty())
{
OUString newTempFileURL = tempFileURL + rDesiredExtension;
if (osl::File::move(tempFileURL, newTempFileURL) != osl::FileBase::E_None)
{
SAL_WARN("avmedia", "Could not rename file '" << tempFileURL << "' to '" << newTempFileURL << "'");
return false;
}
tempFileURL = newTempFileURL;
}
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("avmedia", "exception: '" << e << "'");
return false;
}
o_rTempFileURL = tempFileURL;
return true;
}
MediaTempFile::~MediaTempFile()
{
::osl::File::remove(m_TempFileURL);
}
} // namespace avmedia
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -131,10 +131,25 @@ bool AVMEDIA_DLLPUBLIC EmbedMedia(
::css::uno::Reference<::css::io::XInputStream> const& xInputStream =
::css::uno::Reference<::css::io::XInputStream>());
bool AVMEDIA_DLLPUBLIC CreateMediaTempFile(
::css::uno::Reference<::css::io::XInputStream> const& xInStream,
OUString& o_rTempFileURL,
const OUString& rDesiredExtension);
OUString GetFilename(OUString const& rSourceURL);
::css::uno::Reference< ::css::io::XStream> CreateStream(
const ::css::uno::Reference< ::css::embed::XStorage>& xStorage, const OUString& rFilename);
struct AVMEDIA_DLLPUBLIC MediaTempFile
{
OUString const m_TempFileURL;
MediaTempFile(OUString const& rURL)
: m_TempFileURL(rURL)
{}
~MediaTempFile();
};
}
#endif
......
......@@ -152,7 +152,8 @@ void AnimationAudioNode::createPlayer() const
{
mpPlayer = SoundPlayer::create( getContext().mrEventMultiplexer,
maSoundURL,
getContext().mxComponentContext );
getContext().mxComponentContext,
getContext().mrMediaFileManager);
}
catch( lang::NoSupportException& )
{
......
......@@ -90,6 +90,7 @@ public:
ActivitiesQueue& rActivitiesQueue,
UserEventQueue& rUserEventQueue,
CursorManager& rCursorManager,
MediaFileManager& rMediaFileManager,
const UnoViewContainer& rViewContainer,
const uno::Reference<uno::XComponentContext>& xContext,
const ShapeEventListenerMap& rShapeListenerMap,
......@@ -310,6 +311,7 @@ SlideImpl::SlideImpl( const uno::Reference< drawing::XDrawPage >& xDra
ActivitiesQueue& rActivitiesQueue,
UserEventQueue& rUserEventQueue,
CursorManager& rCursorManager,
MediaFileManager& rMediaFileManager,
const UnoViewContainer& rViewContainer,
const uno::Reference< uno::XComponentContext >& xComponentContext,
const ShapeEventListenerMap& rShapeListenerMap,
......@@ -340,6 +342,7 @@ SlideImpl::SlideImpl( const uno::Reference< drawing::XDrawPage >& xDra
rActivitiesQueue,
rUserEventQueue,
*this,
rMediaFileManager,
rViewContainer,
xComponentContext ),
mrCursorManager( rCursorManager ),
......@@ -1096,6 +1099,7 @@ SlideSharedPtr createSlide( const uno::Reference< drawing::XDrawPage >&
ActivitiesQueue& rActivitiesQueue,
UserEventQueue& rUserEventQueue,
CursorManager& rCursorManager,
MediaFileManager& rMediaFileManager,
const UnoViewContainer& rViewContainer,
const uno::Reference< uno::XComponentContext >& xComponentContext,
const ShapeEventListenerMap& rShapeListenerMap,
......@@ -1110,7 +1114,7 @@ SlideSharedPtr createSlide( const uno::Reference< drawing::XDrawPage >&
std::shared_ptr<SlideImpl> pRet( new SlideImpl( xDrawPage, xDrawPages, xRootNode, rEventQueue,
rEventMultiplexer, rScreenUpdater,
rActivitiesQueue, rUserEventQueue,
rCursorManager, rViewContainer,
rCursorManager, rMediaFileManager, rViewContainer,
xComponentContext, rShapeListenerMap,
rShapeCursorMap, rPolyPolygonVector, rUserPaintColor,
dUserPaintStrokeWidth, bUserPaintEnabled,
......
......@@ -44,6 +44,7 @@ SlideShowContext::SlideShowContext( SubsettableShapeManagerSharedPtr& rSubsettab
ActivitiesQueue& rActivitiesQueue,
UserEventQueue& rUserEventQueue,
CursorManager& rCursorManager,
MediaFileManager& rMediaFileManager,
const UnoViewContainer& rViewContainer,
const uno::Reference<
uno::XComponentContext>& rComponentContext ) :
......@@ -54,6 +55,7 @@ SlideShowContext::SlideShowContext( SubsettableShapeManagerSharedPtr& rSubsettab
mrActivitiesQueue( rActivitiesQueue ),
mrUserEventQueue( rUserEventQueue ),
mrCursorManager( rCursorManager ),
mrMediaFileManager( rMediaFileManager ),
mrViewContainer( rViewContainer ),
mxComponentContext( rComponentContext )
{}
......
......@@ -30,6 +30,7 @@
#include <comphelper/anytostring.hxx>
#include <comphelper/scopeguard.hxx>
#include <comphelper/servicedecl.hxx>
#include <comphelper/storagehelper.hxx>
#include <cppcanvas/spritecanvas.hxx>
#include <cppcanvas/vclfactory.hxx>
......@@ -68,6 +69,7 @@
#include <com/sun/star/drawing/XLayerSupplier.hpp>
#include <com/sun/star/drawing/XLayerManager.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/document/XStorageBasedDocument.hpp>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/loader/CannotActivateFactoryException.hpp>
......@@ -78,6 +80,7 @@
#include <usereventqueue.hxx>
#include <eventqueue.hxx>
#include <cursormanager.hxx>
#include <mediafilemanager.hxx>
#include <slideshowcontext.hxx>
#include <activitiesqueue.hxx>
#include <activitiesfactory.hxx>
......@@ -209,6 +212,7 @@ typedef ::std::map< css::uno::Reference<
class SlideShowImpl : private cppu::BaseMutex,
public CursorManager,
public MediaFileManager,
public SlideShowImplBase
{
public:
......@@ -271,6 +275,9 @@ public:
*/
bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode );
/** Obtain a MediaTempFile for the specified url. */
virtual std::shared_ptr<avmedia::MediaTempFile> getMediaTempFile(const OUString& aUrl) override;
private:
// XSlideShow:
virtual sal_Bool SAL_CALL nextEffect() override;
......@@ -460,6 +467,8 @@ private:
uno::Reference<drawing::XDrawPage> mxPrefetchSlide;
/// save the XDrawPagesSupplier to retrieve polygons
uno::Reference<drawing::XDrawPagesSupplier> mxDrawPagesSupplier;
/// Used by MediaFileManager, for media files with package url.
uno::Reference<document::XStorageBasedDocument> mxSBD;
/// slide animation to be prefetched:
uno::Reference<animations::XAnimationNode> mxPrefetchAnimationNode;
......@@ -572,6 +581,7 @@ SlideShowImpl::SlideShowImpl(
mpPrefetchSlide(),
mxPrefetchSlide(),
mxDrawPagesSupplier(),
mxSBD(),
mxPrefetchAnimationNode(),
mnCurrentCursor(awt::SystemPointer::ARROW),
mnWaitSymbolRequestCount(0),
......@@ -710,7 +720,7 @@ SoundPlayerSharedPtr SlideShowImpl::resetSlideTransitionSound( const uno::Any& r
try
{
mpCurrentSlideTransitionSound = SoundPlayer::create(
maEventMultiplexer, url, mxComponentContext );
maEventMultiplexer, url, mxComponentContext, *this);
mpCurrentSlideTransitionSound->setPlaybackLoop( bLoopSound );
}
catch (lang::NoSupportException const&)
......@@ -894,6 +904,7 @@ SlideSharedPtr SlideShowImpl::makeSlide(
maActivitiesQueue,
maUserEventQueue,
*this,
*this,
maViewContainer,
mxComponentContext,
maShapeEventListeners,
......@@ -1055,6 +1066,7 @@ void SlideShowImpl::displaySlide(
DBG_TESTSOLARMUTEX();
mxDrawPagesSupplier = xDrawPages;
mxSBD = uno::Reference<document::XStorageBasedDocument>(mxDrawPagesSupplier, uno::UNO_QUERY);
stopShow(); // MUST call that: results in
// maUserEventQueue.clear(). What's more,
......@@ -1686,6 +1698,7 @@ sal_Bool SlideShowImpl::setProperty( beans::PropertyValue const& rProperty )
maActivitiesQueue,
maUserEventQueue,
*this,
*this,
maViewContainer,
mxComponentContext) );
}
......@@ -2332,6 +2345,37 @@ bool SlideShowImpl::handleAnimationEvent( const AnimationNodeSharedPtr& rNode )
return true;
}
std::shared_ptr<avmedia::MediaTempFile> SlideShowImpl::getMediaTempFile(const OUString& aUrl)
{
std::shared_ptr<avmedia::MediaTempFile> aRet;
if (!mxSBD.is())
return aRet;
comphelper::LifecycleProxy aProxy;
uno::Reference<io::XStream> xStream =
comphelper::OStorageHelper::GetStreamAtPackageURL(mxSBD->getDocumentStorage(), aUrl,
css::embed::ElementModes::READ, aProxy);
uno::Reference<io::XInputStream> xInStream = xStream->getInputStream();
if (xInStream.is())
{
sal_Int32 nLastDot = aUrl.lastIndexOf('.');
sal_Int32 nLastSlash = aUrl.lastIndexOf('/');
OUString sDesiredExtension;
if (nLastDot > nLastSlash && nLastDot+1 < aUrl.getLength())
sDesiredExtension = aUrl.copy(nLastDot);
OUString sTempUrl;
if (::avmedia::CreateMediaTempFile(xInStream, sTempUrl, sDesiredExtension))
aRet.reset(new avmedia::MediaTempFile(sTempUrl));
xInStream->closeInput();
}
return aRet;
}
//===== FrameSynchronization ==================================================
FrameSynchronization::FrameSynchronization (const double nFrameDuration)
......
......@@ -31,7 +31,7 @@
#include <tools/urlobj.hxx>
#include <avmedia/mediawindow.hxx>
#include <mediafilemanager.hxx>
#include <soundplayer.hxx>
#include <algorithm>
......@@ -48,12 +48,14 @@ namespace slideshow
std::shared_ptr<SoundPlayer> SoundPlayer::create(
EventMultiplexer & rEventMultiplexer,
const OUString& rSoundURL,
const uno::Reference< uno::XComponentContext>& rComponentContext )
const uno::Reference< uno::XComponentContext>& rComponentContext,
MediaFileManager& rMediaFileManager)
{
std::shared_ptr<SoundPlayer> pPlayer(
new SoundPlayer( rEventMultiplexer,
rSoundURL,
rComponentContext ) );
rComponentContext,
rMediaFileManager) );
rEventMultiplexer.addPauseHandler( pPlayer );
pPlayer->mThis = pPlayer;
return pPlayer;
......@@ -86,7 +88,8 @@ namespace slideshow
SoundPlayer::SoundPlayer(
EventMultiplexer & rEventMultiplexer,
const OUString& rSoundURL,
const uno::Reference< uno::XComponentContext>& rComponentContext )
const uno::Reference< uno::XComponentContext>& rComponentContext,
MediaFileManager& rMediaFileManager)
: mrEventMultiplexer(rEventMultiplexer),
mThis(),
mxPlayer()
......@@ -96,7 +99,11 @@ namespace slideshow
try
{
const INetURLObject aURL( rSoundURL );
if (rSoundURL.startsWithIgnoreAsciiCase("vnd.sun.star.Package:"))
{
mpMediaTempFile = rMediaFileManager.getMediaTempFile(rSoundURL);
}
const INetURLObject aURL( mpMediaTempFile ? mpMediaTempFile->m_TempFileURL : rSoundURL );
mxPlayer.set( avmedia::MediaWindow::createPlayer(
aURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ), ""/*TODO!*/ ),
uno::UNO_QUERY);
......
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#ifndef INCLUDED_SLIDESHOW_SOURCE_INC_MEDIAFILEMANAGER_HXX
#define INCLUDED_SLIDESHOW_SOURCE_INC_MEDIAFILEMANAGER_HXX
#include <com/sun/star/uno/Reference.hxx>
#include <memory>
namespace avmedia
{
struct MediaTempFile;
}
namespace slideshow
{
namespace internal
{
class MediaFileManager
{
public:
virtual ~MediaFileManager(){};
virtual std::shared_ptr<avmedia::MediaTempFile> getMediaTempFile(const OUString& aUrl) = 0;
};
}
}
#endif // INCLUDED_SLIDESHOW_SOURCE_INC_MEDIAFILEMANAGER_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -153,6 +153,7 @@ namespace slideshow
class EventQueue;
class CursorManager;
class MediaFileManager;
class EventMultiplexer;
class ActivitiesQueue;
class UserEventQueue;
......@@ -195,6 +196,7 @@ namespace slideshow
ActivitiesQueue& rActivitiesQueue,
UserEventQueue& rUserEventQueue,
CursorManager& rCursorManager,
MediaFileManager& rMediaFileManager,
const UnoViewContainer& rViewContainer,
const css::uno::Reference< css::uno::XComponentContext >& xContext,
const ShapeEventListenerMap& rShapeListenerMap,
......
......@@ -41,6 +41,7 @@ namespace slideshow
class ScreenUpdater;
class UnoViewContainer;
class CursorManager;
class MediaFileManager;
class SubsettableShapeManager;
/** Common arguments for slideshow objects.
......@@ -72,6 +73,9 @@ namespace slideshow
Activities queue, where repeating activities are
to be scheduled.
@param rMediaFileManager
To handle media file with package urls.
@param rUserEventQueue
User event queue
......@@ -88,6 +92,7 @@ namespace slideshow
ActivitiesQueue& rActivitiesQueue,
UserEventQueue& rUserEventQueue,
CursorManager& rCursorManager,
MediaFileManager& rMediaFileManager,
const UnoViewContainer& rViewContainer,
const css::uno::Reference< css::uno::XComponentContext>& rComponentContext );
void dispose();
......@@ -99,6 +104,7 @@ namespace slideshow
ActivitiesQueue& mrActivitiesQueue;
UserEventQueue& mrUserEventQueue;
CursorManager& mrCursorManager;
MediaFileManager& mrMediaFileManager;
const UnoViewContainer& mrViewContainer;
css::uno::Reference< css::uno::XComponentContext> mxComponentContext;
};
......
......@@ -25,6 +25,7 @@
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/media/XManager.hpp>
#include <com/sun/star/media/XPlayer.hpp>
#include <avmedia/mediaitem.hxx>
#include <memory>
......@@ -39,6 +40,8 @@ namespace slideshow
{
namespace internal
{
class MediaFileManager;
/** Little class that plays a sound from a URL.
TODO:
Must be explicitly disposed (as long as enable_shared_ptr_from_this
......@@ -64,7 +67,8 @@ namespace slideshow
static ::std::shared_ptr<SoundPlayer> create(
EventMultiplexer & rEventMultiplexer,
const OUString& rSoundURL,
const css::uno::Reference< css::uno::XComponentContext>& rComponentContext );
const css::uno::Reference< css::uno::XComponentContext>& rComponentContext,
MediaFileManager& rMediaFileManager);
virtual ~SoundPlayer() override;
......@@ -92,12 +96,15 @@ namespace slideshow
SoundPlayer(
EventMultiplexer & rEventMultiplexer,
const OUString& rSoundURL,
const css::uno::Reference< css::uno::XComponentContext>& rComponentContext );
const css::uno::Reference< css::uno::XComponentContext>& rComponentContext,
MediaFileManager & rMediaFileManager);
EventMultiplexer & mrEventMultiplexer;
// TODO(Q3): obsolete when boost::enable_shared_ptr_from_this
// is available
::std::shared_ptr<SoundPlayer> mThis;
// Temp file for pakcage url.
::std::shared_ptr<::avmedia::MediaTempFile> mpMediaTempFile;
css::uno::Reference< css::media::XPlayer > mxPlayer;
};
......
......@@ -44,25 +44,13 @@
using namespace ::com::sun::star;
// Note: the temp file is read only, until it is deleted!
// It may be shared between multiple documents in case of copy/paste,
// hence the shared_ptr.
struct MediaTempFile
{
OUString const m_TempFileURL;
MediaTempFile(OUString const& rURL)
: m_TempFileURL(rURL)
{}
~MediaTempFile()
{
::osl::File::remove(m_TempFileURL);
}
};
struct SdrMediaObj::Impl
{
::avmedia::MediaItem m_MediaProperties;
std::shared_ptr< MediaTempFile > m_pTempFile;
// Note: the temp file is read only, until it is deleted!
// It may be shared between multiple documents in case of copy/paste,
// hence the shared_ptr.
std::shared_ptr< ::avmedia::MediaTempFile > m_pTempFile;
uno::Reference< graphic::XGraphic > m_xCachedSnapshot;
OUString m_LastFailedPkgURL;
};
......@@ -270,47 +258,6 @@ uno::Reference<io::XInputStream> SdrMediaObj::GetInputStream()
return tempFile.openStream();
}
static bool lcl_CopyToTempFile(
uno::Reference<io::XInputStream> const& xInStream,
OUString & o_rTempFileURL,
const OUString& rDesiredExtension)
{
OUString tempFileURL;
::osl::FileBase::RC const err =
::osl::FileBase::createTempFile(nullptr, nullptr, & tempFileURL);
if (::osl::FileBase::E_None != err)
{
SAL_INFO("svx", "cannot create temp file");
return false;
}
if (!rDesiredExtension.isEmpty())
{
OUString newTempFileURL = tempFileURL + rDesiredExtension;
if (osl::File::move(tempFileURL, newTempFileURL) != osl::FileBase::E_None)
{
SAL_WARN("svx", "Could not rename file '" << tempFileURL << "' to '" << newTempFileURL << "'");
return false;
}
tempFileURL = newTempFileURL;
}
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 << "'");
return false;
}
o_rTempFileURL = tempFileURL;
return true;
}
void SdrMediaObj::SetInputStream(uno::Reference<io::XInputStream> const& xStream)
{
if (m_xImpl->m_pTempFile || m_xImpl->m_LastFailedPkgURL.isEmpty())
......@@ -321,14 +268,14 @@ void SdrMediaObj::SetInputStream(uno::Reference<io::XInputStream> const& xStream
OUString tempFileURL;
const bool bSuccess(
lcl_CopyToTempFile(
::avmedia::CreateMediaTempFile(
xStream,
tempFileURL,
""));
if (bSuccess)
{
m_xImpl->m_pTempFile.reset(new MediaTempFile(tempFileURL));
m_xImpl->m_pTempFile.reset(new ::avmedia::MediaTempFile(tempFileURL));
#if HAVE_FEATURE_AVMEDIA
m_xImpl->m_MediaProperties.setURL(
m_xImpl->m_LastFailedPkgURL, tempFileURL, "");
......@@ -372,7 +319,7 @@ static bool lcl_HandlePackageURL(
OUString sDesiredExtension;
if (nLastDot > nLastSlash && nLastDot+1 < rURL.getLength())
sDesiredExtension = rURL.copy(nLastDot);
return lcl_CopyToTempFile(xInStream, o_rTempFileURL, sDesiredExtension);
return ::avmedia::CreateMediaTempFile(xInStream, o_rTempFileURL, sDesiredExtension);
}
#endif
......@@ -407,7 +354,7 @@ void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProper
if (bSuccess)
{
m_xImpl->m_pTempFile.reset(
new MediaTempFile(tempFileURL));
new ::avmedia::MediaTempFile(tempFileURL));
#if HAVE_FEATURE_AVMEDIA
m_xImpl->m_MediaProperties.setURL(url, tempFileURL, "");
#endif
......
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