LibreOffice Module svx (master)  1
svdomedia.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column:100 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <config_features.h>
21 
22 #include <svx/svdomedia.hxx>
23 
24 #include <rtl/ustring.hxx>
25 #include <sal/log.hxx>
26 
27 #include <ucbhelper/content.hxx>
30 
31 #include <vcl/svapp.hxx>
32 
33 #include <svx/svdmodel.hxx>
34 #include <svx/dialmgr.hxx>
35 #include <svx/strings.hrc>
37 #include <avmedia/mediawindow.hxx>
38 #include <tools/diagnose_ex.h>
39 
40 using namespace ::com::sun::star;
41 
42 
44 {
46 #if HAVE_FEATURE_AVMEDIA
47  // Note: the temp file is read only, until it is deleted!
48  // It may be shared between multiple documents in case of copy/paste,
49  // hence the shared_ptr.
50  std::shared_ptr< ::avmedia::MediaTempFile > m_pTempFile;
51 #endif
52  uno::Reference< graphic::XGraphic > m_xCachedSnapshot;
55 };
56 
58 : SdrRectObj(rSdrModel)
59  ,m_xImpl( new Impl )
60 {
61 }
62 
63 SdrMediaObj::SdrMediaObj(SdrModel& rSdrModel, SdrMediaObj const & rSource)
64 : SdrRectObj(rSdrModel, rSource)
65  ,m_xImpl( new Impl )
66 {
67 #if HAVE_FEATURE_AVMEDIA
68  m_xImpl->m_pTempFile = rSource.m_xImpl->m_pTempFile; // before props
69 #endif
71  m_xImpl->m_xCachedSnapshot = rSource.m_xImpl->m_xCachedSnapshot;
72 }
73 
75  SdrModel& rSdrModel,
76  const tools::Rectangle& rRect)
77 : SdrRectObj(rSdrModel, rRect)
78  ,m_xImpl( new Impl )
79 {
80  const bool bUndo(rSdrModel.IsUndoEnabled());
81  rSdrModel.EnableUndo(false);
83  rSdrModel.EnableUndo(bUndo);
84 }
85 
87 {
88 }
89 
91 {
92  return false;
93 }
94 
95 std::unique_ptr<sdr::contact::ViewContact> SdrMediaObj::CreateObjectSpecificViewContact()
96 {
97  return std::make_unique<sdr::contact::ViewContactOfSdrMediaObj>( *this );
98 }
99 
101 {
102  rInfo.bMoveAllowed = true;
103  rInfo.bResizeFreeAllowed = true;
104  rInfo.bResizePropAllowed = true;
105  rInfo.bRotateFreeAllowed = false;
106  rInfo.bRotate90Allowed = false;
107  rInfo.bMirrorFreeAllowed = false;
108  rInfo.bMirror45Allowed = false;
109  rInfo.bMirror90Allowed = false;
110  rInfo.bTransparenceAllowed = false;
111  rInfo.bShearAllowed = false;
112  rInfo.bEdgeRadiusAllowed = false;
113  rInfo.bNoOrthoDesired = false;
114  rInfo.bNoContortion = false;
115  rInfo.bCanConvToPath = false;
116  rInfo.bCanConvToPoly = false;
117  rInfo.bCanConvToContour = false;
118  rInfo.bCanConvToPathLineToArea = false;
119  rInfo.bCanConvToPolyLineToArea = false;
120 }
121 
123 {
124  return SdrObjKind::Media;
125 }
126 
128 {
129  OUString sName(SvxResId(STR_ObjNameSingulMEDIA));
130 
131  OUString aName(GetName());
132 
133  if (!aName.isEmpty())
134  sName += " '" + aName + "'";
135 
136  return sName;
137 }
138 
140 {
141  return SvxResId(STR_ObjNamePluralMEDIA);
142 }
143 
145 {
146  return new SdrMediaObj(rTargetModel, *this);
147 }
148 
149 uno::Reference< graphic::XGraphic > const & SdrMediaObj::getSnapshot() const
150 {
151 #if HAVE_FEATURE_AVMEDIA
152  if( !m_xImpl->m_xCachedSnapshot.is() )
153  {
154  OUString aRealURL = m_xImpl->m_MediaProperties.getTempURL();
155  if( aRealURL.isEmpty() )
156  aRealURL = m_xImpl->m_MediaProperties.getURL();
157  OUString sReferer = m_xImpl->m_MediaProperties.getReferer();
158  OUString sMimeType = m_xImpl->m_MediaProperties.getMimeType();
159  uno::Reference<graphic::XGraphic> xCachedSnapshot = m_xImpl->m_xCachedSnapshot;
160 
161  m_xImpl->m_xPlayerListener.set(new avmedia::PlayerListener(
162  [this, xCachedSnapshot, aRealURL, sReferer, sMimeType](const css::uno::Reference<css::media::XPlayer>& rPlayer){
163  SolarMutexGuard g;
164  m_xImpl->m_xCachedSnapshot = avmedia::MediaWindow::grabFrame(rPlayer);
165  ActionChanged();
166  }));
167 
168  avmedia::MediaWindow::grabFrame(aRealURL, sReferer, sMimeType, m_xImpl->m_xPlayerListener);
169  }
170 #endif
171  return m_xImpl->m_xCachedSnapshot;
172 }
173 
174 void SdrMediaObj::AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool bShrinkOnly /* = false */ )
175 {
176  Size aSize( Application::GetDefaultDevice()->PixelToLogic(
177  static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).getPreferredSize(),
178  MapMode(MapUnit::Map100thMM)) );
179  Size aMaxSize( rMaxRect.GetSize() );
180 
181  if( aSize.IsEmpty() )
182  return;
183 
184  Point aPos( rMaxRect.TopLeft() );
185 
186  // if graphic is too large, fit it to the page
187  if ( (!bShrinkOnly ||
188  ( aSize.Height() > aMaxSize.Height() ) ||
189  ( aSize.Width() > aMaxSize.Width() ) )&&
190  aSize.Height() && aMaxSize.Height() )
191  {
192  float fGrfWH = static_cast<float>(aSize.Width()) /
193  static_cast<float>(aSize.Height());
194  float fWinWH = static_cast<float>(aMaxSize.Width()) /
195  static_cast<float>(aMaxSize.Height());
196 
197  // scale graphic to page size
198  if ( fGrfWH < fWinWH )
199  {
200  aSize.setWidth( static_cast<tools::Long>(aMaxSize.Height() * fGrfWH) );
201  aSize.setHeight( aMaxSize.Height() );
202  }
203  else if ( fGrfWH > 0.F )
204  {
205  aSize.setWidth( aMaxSize.Width() );
206  aSize.setHeight( static_cast<tools::Long>(aMaxSize.Width() / fGrfWH) );
207  }
208 
209  aPos = rMaxRect.Center();
210  }
211 
212  if( bShrinkOnly )
213  aPos = maRect.TopLeft();
214 
215  aPos.AdjustX( -(aSize.Width() / 2) );
216  aPos.AdjustY( -(aSize.Height() / 2) );
217  SetLogicRect( tools::Rectangle( aPos, aSize ) );
218 }
219 
220 void SdrMediaObj::setURL( const OUString& rURL, const OUString& rReferer, const OUString& rMimeType )
221 {
222  ::avmedia::MediaItem aURLItem;
223 #if HAVE_FEATURE_AVMEDIA
224  if( !rMimeType.isEmpty() )
225  m_xImpl->m_MediaProperties.setMimeType(rMimeType);
226  aURLItem.setURL( rURL, "", rReferer );
227 #else
228  (void) rMimeType;
229  (void) rURL;
230  (void) rReferer;
231 #endif
232  setMediaProperties( aURLItem );
233 }
234 
235 const OUString& SdrMediaObj::getURL() const
236 {
237 #if HAVE_FEATURE_AVMEDIA
238  return m_xImpl->m_MediaProperties.getURL();
239 #else
240  static OUString ret;
241  return ret;
242 #endif
243 }
244 
245 void SdrMediaObj::setMediaProperties( const ::avmedia::MediaItem& rState )
246 {
247  mediaPropertiesChanged( rState );
248  static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).executeMediaItem( getMediaProperties() );
249 }
250 
251 const ::avmedia::MediaItem& SdrMediaObj::getMediaProperties() const
252 {
253  return m_xImpl->m_MediaProperties;
254 }
255 
256 uno::Reference<io::XInputStream> SdrMediaObj::GetInputStream() const
257 {
258 #if HAVE_FEATURE_AVMEDIA
259  if (!m_xImpl->m_pTempFile)
260  {
261  SAL_WARN("svx", "this is only intended for embedded media");
262  return nullptr;
263  }
264  ucbhelper::Content tempFile(m_xImpl->m_pTempFile->m_TempFileURL,
265  uno::Reference<ucb::XCommandEnvironment>(),
267  return tempFile.openStream();
268 #else
269  return nullptr;
270 #endif
271 }
272 
273 void SdrMediaObj::SetInputStream(uno::Reference<io::XInputStream> const& xStream)
274 {
275 #if !HAVE_FEATURE_AVMEDIA
276  (void) xStream;
277 #else
278  if (m_xImpl->m_pTempFile || m_xImpl->m_LastFailedPkgURL.isEmpty())
279  {
280  SAL_WARN("svx", "this is only intended for embedded media");
281  return;
282  }
283 
284  OUString tempFileURL;
285  const bool bSuccess(
287  xStream,
288  tempFileURL,
289  u""));
290 
291  if (bSuccess)
292  {
293  m_xImpl->m_pTempFile = std::make_shared<::avmedia::MediaTempFile>(tempFileURL);
294  m_xImpl->m_MediaProperties.setURL(
295  m_xImpl->m_LastFailedPkgURL, tempFileURL, "");
296  }
297  m_xImpl->m_LastFailedPkgURL.clear(); // once only
298 #endif
299 }
300 
302 #if HAVE_FEATURE_AVMEDIA
303 static bool lcl_HandlePackageURL(
304  OUString const & rURL,
305  const SdrModel& rModel,
306  OUString & o_rTempFileURL)
307 {
308  ::comphelper::LifecycleProxy sourceProxy;
309  uno::Reference<io::XInputStream> xInStream;
310  try {
311  xInStream = rModel.GetDocumentStream(rURL, sourceProxy);
312  }
313  catch (container::NoSuchElementException const&)
314  {
315  SAL_INFO("svx", "not found: '" << rURL << "'");
316  return false;
317  }
318  catch (uno::Exception const&)
319  {
320  TOOLS_WARN_EXCEPTION("svx", "");
321  return false;
322  }
323  if (!xInStream.is())
324  {
325  SAL_WARN("svx", "no stream?");
326  return false;
327  }
328  // Make sure the temporary copy has the same file name extension as the original media file
329  // (like .mp4). That seems to be important for some AVFoundation APIs. For random extension-less
330  // file names, they don't seem to even bother looking inside the file.
331  sal_Int32 nLastDot = rURL.lastIndexOf('.');
332  sal_Int32 nLastSlash = rURL.lastIndexOf('/');
333  OUString sDesiredExtension;
334  if (nLastDot > nLastSlash && nLastDot+1 < rURL.getLength())
335  sDesiredExtension = rURL.copy(nLastDot);
336  return ::avmedia::CreateMediaTempFile(xInStream, o_rTempFileURL, sDesiredExtension);
337 }
338 #endif
339 
340 void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProperties )
341 {
342  bool bBroadcastChanged = false;
343 #if HAVE_FEATURE_AVMEDIA
344  const AVMediaSetMask nMaskSet = rNewProperties.getMaskSet();
345 
346  // use only a subset of MediaItem properties for own properties
347  if( AVMediaSetMask::MIME_TYPE & nMaskSet )
348  m_xImpl->m_MediaProperties.setMimeType( rNewProperties.getMimeType() );
349 
350  if (nMaskSet & AVMediaSetMask::GRAPHIC)
351  {
352  m_xImpl->m_MediaProperties.setGraphic(rNewProperties.getGraphic());
353  }
354 
355  if( ( AVMediaSetMask::URL & nMaskSet ) &&
356  ( rNewProperties.getURL() != getURL() ))
357  {
358  m_xImpl->m_xCachedSnapshot.clear();
359  m_xImpl->m_xPlayerListener.clear();
360  OUString const& url(rNewProperties.getURL());
361  if (url.startsWithIgnoreAsciiCase("vnd.sun.star.Package:"))
362  {
363  if ( !m_xImpl->m_pTempFile
364  || (m_xImpl->m_pTempFile->m_TempFileURL !=
365  rNewProperties.getTempURL()))
366  {
367  OUString tempFileURL;
368  const bool bSuccess(
369  lcl_HandlePackageURL(
370  url,
372  tempFileURL));
373 
374  if (bSuccess)
375  {
376  m_xImpl->m_pTempFile =
377  std::make_shared<::avmedia::MediaTempFile>(tempFileURL);
378  m_xImpl->m_MediaProperties.setURL(url, tempFileURL, "");
379  }
380  else // this case is for Clone via operator=
381  {
382  m_xImpl->m_pTempFile.reset();
383  m_xImpl->m_MediaProperties.setURL("", "", "");
384  // UGLY: oox import also gets here, because unlike ODF
385  // getDocumentStorage() is not the imported file...
386  m_xImpl->m_LastFailedPkgURL = url;
387  }
388  }
389  else
390  {
391  m_xImpl->m_MediaProperties.setURL(url,
392  rNewProperties.getTempURL(), "");
393  }
394  }
395  else
396  {
397  m_xImpl->m_pTempFile.reset();
398  m_xImpl->m_MediaProperties.setURL(url, "", rNewProperties.getReferer());
399  }
400  bBroadcastChanged = true;
401  }
402 
403  if( AVMediaSetMask::LOOP & nMaskSet )
404  m_xImpl->m_MediaProperties.setLoop( rNewProperties.isLoop() );
405 
406  if( AVMediaSetMask::MUTE & nMaskSet )
407  m_xImpl->m_MediaProperties.setMute( rNewProperties.isMute() );
408 
409  if( AVMediaSetMask::VOLUMEDB & nMaskSet )
410  m_xImpl->m_MediaProperties.setVolumeDB( rNewProperties.getVolumeDB() );
411 
412  if( AVMediaSetMask::ZOOM & nMaskSet )
413  m_xImpl->m_MediaProperties.setZoom( rNewProperties.getZoom() );
414 #else
415  (void) rNewProperties;
416 #endif
417 
418  if( bBroadcastChanged )
419  {
420  SetChanged();
422  }
423 }
424 
425 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static css::uno::Reference< css::graphic::XGraphic > grabFrame(const css::uno::Reference< css::media::XPlayer > &rPlayer)
OUString m_LastFailedPkgURL
Definition: svdomedia.cxx:54
bool setURL(const OUString &rURL, const OUString &rTempURL, const OUString &rReferer)
AVMediaSetMask
void setWidth(tools::Long nWidth)
virtual ~SdrMediaObj() override
Definition: svdomedia.cxx:86
virtual bool HasTextEdit() const override
Definition: svdomedia.cxx:90
sdr::contact::ViewContact & GetViewContact() const
Definition: svdobj.cxx:251
uno::Reference< graphic::XGraphic > m_xCachedSnapshot
Definition: svdomedia.cxx:52
SdrObjKind
Definition: svdobjkind.hxx:24
Rectangle objects (rectangle, circle, ...)
Definition: svdorect.hxx:38
static OutputDevice * GetDefaultDevice()
constexpr tools::Long Width() const
Provides information about various ZObject properties.
Definition: svdobj.hxx:195
virtual SdrMediaObj * CloneSdrObject(SdrModel &rTargetModel) const override
Definition: svdomedia.cxx:144
void EnableUndo(bool bEnable)
enables (true) or disables (false) recording of undo actions If undo actions are added while undo is ...
Definition: svdmodel.cxx:521
const ::avmedia::MediaItem & getMediaProperties() const
Definition: svdomedia.cxx:251
OUString SvxResId(TranslateId aId)
Definition: dialmgr.cxx:24
tools::Rectangle maRect
Definition: svdotext.hxx:170
void MakeNameUnique()
Definition: svdobj.cxx:3109
std::unique_ptr< Impl > m_xImpl
Definition: svdomedia.hxx:79
virtual OUString TakeObjNamePlural() const override
Definition: svdomedia.cxx:139
#define TOOLS_WARN_EXCEPTION(area, stream)
void setURL(const OUString &rURL, const OUString &rReferer, const OUString &rMimeType=OUString())
Definition: svdomedia.cxx:220
bool IsEmpty() const
virtual void TakeObjInfo(SdrObjTransformInfoRec &rInfo) const override
Definition: svdomedia.cxx:100
bool IsUndoEnabled() const
returns true if undo is currently enabled This returns false if undo was disabled using EnableUndo( f...
Definition: svdmodel.cxx:533
OUString sName
void BroadcastObjectChange() const
Definition: svdobj.cxx:1001
void ActionChanged() const
Definition: svdobj.cxx:263
const OUString & getURL() const
Definition: svdomedia.cxx:235
float u
SdrModel & getSdrModelFromSdrObject() const
Definition: svdobj.cxx:279
void mediaPropertiesChanged(const ::avmedia::MediaItem &rNewState)
copy a stream from XStorage to temp file
Definition: svdomedia.cxx:340
virtual OUString TakeObjNameSingul() const override
Definition: svdomedia.cxx:127
virtual void SetLogicRect(const tools::Rectangle &rRect)
Definition: svdobj.cxx:1694
constexpr Point Center() const
constexpr Point TopLeft() const
void SetInputStream(css::uno::Reference< css::io::XInputStream > const &)
Definition: svdomedia.cxx:273
css::uno::Reference< css::io::XInputStream > openStream()
constexpr Size GetSize() const
css::uno::Reference< css::graphic::XGraphic > const & getSnapshot() const
Definition: svdomedia.cxx:149
constexpr tools::Long Height() const
#define SAL_INFO(area, stream)
OUString aName
SdrMediaObj(SdrModel &rSdrModel)
Definition: svdomedia.cxx:57
Reference< XComponentContext > getProcessComponentContext()
custom shape
void setMediaProperties(const ::avmedia::MediaItem &rState)
Definition: svdomedia.cxx:245
virtual void AdjustToMaxRect(const tools::Rectangle &rMaxRect, bool bShrinkOnly=false) override
Definition: svdomedia.cxx:174
::avmedia::MediaItem m_MediaProperties
Definition: svdomedia.cxx:45
void setHeight(tools::Long nHeight)
css::uno::Reference< css::io::XInputStream > GetInputStream() const
Definition: svdomedia.cxx:256
#define SAL_WARN(area, stream)
virtual std::unique_ptr< sdr::contact::ViewContact > CreateObjectSpecificViewContact() override
Definition: svdomedia.cxx:95
virtual void SetChanged()
Definition: svdobj.cxx:1025
bool CreateMediaTempFile(uno::Reference< io::XInputStream > const &xInStream, OUString &o_rTempFileURL, std::u16string_view rDesiredExtension)
const OUString & GetName() const
Definition: svdobj.cxx:792
css::uno::Reference< css::io::XInputStream > GetDocumentStream(OUString const &rURL,::comphelper::LifecycleProxy const &rProxy) const
Definition: svdmodel.cxx:753
rtl::Reference< avmedia::PlayerListener > m_xPlayerListener
Definition: svdomedia.cxx:53
virtual SdrObjKind GetObjIdentifier() const override
Definition: svdomedia.cxx:122
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo