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 <rtl/ustrbuf.hxx>
26 #include <sal/log.hxx>
27 
28 #include <ucbhelper/content.hxx>
31 
32 #include <vcl/svapp.hxx>
33 
34 #include <svx/svdmodel.hxx>
35 #include <svx/dialmgr.hxx>
36 #include <svx/strings.hrc>
38 #include <avmedia/mediawindow.hxx>
39 #include <tools/diagnose_ex.h>
40 
41 using namespace ::com::sun::star;
42 
43 
45 {
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  uno::Reference< graphic::XGraphic > m_xCachedSnapshot;
53 };
54 
56 : SdrRectObj(rSdrModel)
57  ,m_xImpl( new Impl )
58 {
59 }
60 
61 SdrMediaObj::SdrMediaObj(SdrModel& rSdrModel, SdrMediaObj const & rSource)
62 : SdrRectObj(rSdrModel, rSource)
63  ,m_xImpl( new Impl )
64 {
65  m_xImpl->m_pTempFile = rSource.m_xImpl->m_pTempFile; // before props
67  m_xImpl->m_xCachedSnapshot = rSource.m_xImpl->m_xCachedSnapshot;
68 }
69 
71  SdrModel& rSdrModel,
72  const tools::Rectangle& rRect)
73 : SdrRectObj(rSdrModel, rRect)
74  ,m_xImpl( new Impl )
75 {
76 }
77 
79 {
80 }
81 
83 {
84  return false;
85 }
86 
87 std::unique_ptr<sdr::contact::ViewContact> SdrMediaObj::CreateObjectSpecificViewContact()
88 {
89  return std::make_unique<sdr::contact::ViewContactOfSdrMediaObj>( *this );
90 }
91 
93 {
94  rInfo.bMoveAllowed = true;
95  rInfo.bResizeFreeAllowed = true;
96  rInfo.bResizePropAllowed = true;
97  rInfo.bRotateFreeAllowed = false;
98  rInfo.bRotate90Allowed = false;
99  rInfo.bMirrorFreeAllowed = false;
100  rInfo.bMirror45Allowed = false;
101  rInfo.bMirror90Allowed = false;
102  rInfo.bTransparenceAllowed = false;
103  rInfo.bShearAllowed = false;
104  rInfo.bEdgeRadiusAllowed = false;
105  rInfo.bNoOrthoDesired = false;
106  rInfo.bNoContortion = false;
107  rInfo.bCanConvToPath = false;
108  rInfo.bCanConvToPoly = false;
109  rInfo.bCanConvToContour = false;
110  rInfo.bCanConvToPathLineToArea = false;
111  rInfo.bCanConvToPolyLineToArea = false;
112 }
113 
115 {
116  return OBJ_MEDIA;
117 }
118 
120 {
121  OUStringBuffer sName(SvxResId(STR_ObjNameSingulMEDIA));
122 
123  OUString aName(GetName());
124 
125  if (!aName.isEmpty())
126  {
127  sName.append(' ');
128  sName.append('\'');
129  sName.append(aName);
130  sName.append('\'');
131  }
132 
133  return sName.makeStringAndClear();
134 }
135 
137 {
138  return SvxResId(STR_ObjNamePluralMEDIA);
139 }
140 
142 {
143  return new SdrMediaObj(rTargetModel, *this);
144 }
145 
146 uno::Reference< graphic::XGraphic > const & SdrMediaObj::getSnapshot() const
147 {
148 #if HAVE_FEATURE_AVMEDIA
149  if( !m_xImpl->m_xCachedSnapshot.is() )
150  {
151  OUString aRealURL = m_xImpl->m_MediaProperties.getTempURL();
152  if( aRealURL.isEmpty() )
153  aRealURL = m_xImpl->m_MediaProperties.getURL();
154  m_xImpl->m_xCachedSnapshot = avmedia::MediaWindow::grabFrame( aRealURL, m_xImpl->m_MediaProperties.getReferer(), m_xImpl->m_MediaProperties.getMimeType());
155  }
156 #endif
157  return m_xImpl->m_xCachedSnapshot;
158 }
159 
160 void SdrMediaObj::AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool bShrinkOnly /* = false */ )
161 {
162  Size aSize( Application::GetDefaultDevice()->PixelToLogic(
163  static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).getPreferredSize(),
164  MapMode(MapUnit::Map100thMM)) );
165  Size aMaxSize( rMaxRect.GetSize() );
166 
167  if( aSize.IsEmpty() )
168  return;
169 
170  Point aPos( rMaxRect.TopLeft() );
171 
172  // if graphic is too large, fit it to the page
173  if ( (!bShrinkOnly ||
174  ( aSize.Height() > aMaxSize.Height() ) ||
175  ( aSize.Width() > aMaxSize.Width() ) )&&
176  aSize.Height() && aMaxSize.Height() )
177  {
178  float fGrfWH = static_cast<float>(aSize.Width()) /
179  static_cast<float>(aSize.Height());
180  float fWinWH = static_cast<float>(aMaxSize.Width()) /
181  static_cast<float>(aMaxSize.Height());
182 
183  // scale graphic to page size
184  if ( fGrfWH < fWinWH )
185  {
186  aSize.setWidth( static_cast<tools::Long>(aMaxSize.Height() * fGrfWH) );
187  aSize.setHeight( aMaxSize.Height() );
188  }
189  else if ( fGrfWH > 0.F )
190  {
191  aSize.setWidth( aMaxSize.Width() );
192  aSize.setHeight( static_cast<tools::Long>(aMaxSize.Width() / fGrfWH) );
193  }
194 
195  aPos = rMaxRect.Center();
196  }
197 
198  if( bShrinkOnly )
199  aPos = maRect.TopLeft();
200 
201  aPos.AdjustX( -(aSize.Width() / 2) );
202  aPos.AdjustY( -(aSize.Height() / 2) );
203  SetLogicRect( tools::Rectangle( aPos, aSize ) );
204 }
205 
206 void SdrMediaObj::setURL( const OUString& rURL, const OUString& rReferer, const OUString& rMimeType )
207 {
208  ::avmedia::MediaItem aURLItem;
209 #if HAVE_FEATURE_AVMEDIA
210  if( !rMimeType.isEmpty() )
211  m_xImpl->m_MediaProperties.setMimeType(rMimeType);
212  aURLItem.setURL( rURL, "", rReferer );
213 #else
214  (void) rMimeType;
215  (void) rURL;
216  (void) rReferer;
217 #endif
218  setMediaProperties( aURLItem );
219 }
220 
221 const OUString& SdrMediaObj::getURL() const
222 {
223 #if HAVE_FEATURE_AVMEDIA
224  return m_xImpl->m_MediaProperties.getURL();
225 #else
226 static OUString ret;
227  return ret;
228 #endif
229 }
230 
231 void SdrMediaObj::setMediaProperties( const ::avmedia::MediaItem& rState )
232 {
233  mediaPropertiesChanged( rState );
234  static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).executeMediaItem( getMediaProperties() );
235 }
236 
237 const ::avmedia::MediaItem& SdrMediaObj::getMediaProperties() const
238 {
239  return m_xImpl->m_MediaProperties;
240 }
241 
242 uno::Reference<io::XInputStream> SdrMediaObj::GetInputStream() const
243 {
244  if (!m_xImpl->m_pTempFile)
245  {
246  SAL_WARN("svx", "this is only intended for embedded media");
247  return nullptr;
248  }
249  ucbhelper::Content tempFile(m_xImpl->m_pTempFile->m_TempFileURL,
250  uno::Reference<ucb::XCommandEnvironment>(),
252  return tempFile.openStream();
253 }
254 
255 void SdrMediaObj::SetInputStream(uno::Reference<io::XInputStream> const& xStream)
256 {
257  if (m_xImpl->m_pTempFile || m_xImpl->m_LastFailedPkgURL.isEmpty())
258  {
259  SAL_WARN("svx", "this is only intended for embedded media");
260  return;
261  }
262 
263  OUString tempFileURL;
264  const bool bSuccess(
266  xStream,
267  tempFileURL,
268  u""));
269 
270  if (bSuccess)
271  {
272  m_xImpl->m_pTempFile = std::make_shared<::avmedia::MediaTempFile>(tempFileURL);
273 #if HAVE_FEATURE_AVMEDIA
274  m_xImpl->m_MediaProperties.setURL(
275  m_xImpl->m_LastFailedPkgURL, tempFileURL, "");
276 #endif
277  }
278  m_xImpl->m_LastFailedPkgURL.clear(); // once only
279 }
280 
282 #if HAVE_FEATURE_AVMEDIA
283 static bool lcl_HandlePackageURL(
284  OUString const & rURL,
285  const SdrModel& rModel,
286  OUString & o_rTempFileURL)
287 {
288  ::comphelper::LifecycleProxy sourceProxy;
289  uno::Reference<io::XInputStream> xInStream;
290  try {
291  xInStream = rModel.GetDocumentStream(rURL, sourceProxy);
292  }
293  catch (container::NoSuchElementException const&)
294  {
295  SAL_INFO("svx", "not found: '" << rURL << "'");
296  return false;
297  }
298  catch (uno::Exception const&)
299  {
300  TOOLS_WARN_EXCEPTION("svx", "");
301  return false;
302  }
303  if (!xInStream.is())
304  {
305  SAL_WARN("svx", "no stream?");
306  return false;
307  }
308  // Make sure the temporary copy has the same file name extension as the original media file
309  // (like .mp4). That seems to be important for some AVFoundation APIs. For random extension-less
310  // file names, they don't seem to even bother looking inside the file.
311  sal_Int32 nLastDot = rURL.lastIndexOf('.');
312  sal_Int32 nLastSlash = rURL.lastIndexOf('/');
313  OUString sDesiredExtension;
314  if (nLastDot > nLastSlash && nLastDot+1 < rURL.getLength())
315  sDesiredExtension = rURL.copy(nLastDot);
316  return ::avmedia::CreateMediaTempFile(xInStream, o_rTempFileURL, sDesiredExtension);
317 }
318 #endif
319 
320 void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProperties )
321 {
322  bool bBroadcastChanged = false;
323 #if HAVE_FEATURE_AVMEDIA
324  const AVMediaSetMask nMaskSet = rNewProperties.getMaskSet();
325 
326  // use only a subset of MediaItem properties for own properties
327  if( AVMediaSetMask::MIME_TYPE & nMaskSet )
328  m_xImpl->m_MediaProperties.setMimeType( rNewProperties.getMimeType() );
329 
330  if (nMaskSet & AVMediaSetMask::GRAPHIC)
331  {
332  m_xImpl->m_MediaProperties.setGraphic(rNewProperties.getGraphic());
333  }
334 
335  if( ( AVMediaSetMask::URL & nMaskSet ) &&
336  ( rNewProperties.getURL() != getURL() ))
337  {
338  m_xImpl->m_xCachedSnapshot.clear();
339  OUString const& url(rNewProperties.getURL());
340  if (url.startsWithIgnoreAsciiCase("vnd.sun.star.Package:"))
341  {
342  if ( !m_xImpl->m_pTempFile
343  || (m_xImpl->m_pTempFile->m_TempFileURL !=
344  rNewProperties.getTempURL()))
345  {
346  OUString tempFileURL;
347  const bool bSuccess(
348  lcl_HandlePackageURL(
349  url,
351  tempFileURL));
352 
353  if (bSuccess)
354  {
355  m_xImpl->m_pTempFile =
356  std::make_shared<::avmedia::MediaTempFile>(tempFileURL);
357  m_xImpl->m_MediaProperties.setURL(url, tempFileURL, "");
358  }
359  else // this case is for Clone via operator=
360  {
361  m_xImpl->m_pTempFile.reset();
362  m_xImpl->m_MediaProperties.setURL("", "", "");
363  // UGLY: oox import also gets here, because unlike ODF
364  // getDocumentStorage() is not the imported file...
365  m_xImpl->m_LastFailedPkgURL = url;
366  }
367  }
368  else
369  {
370  m_xImpl->m_MediaProperties.setURL(url,
371  rNewProperties.getTempURL(), "");
372  }
373  }
374  else
375  {
376  m_xImpl->m_pTempFile.reset();
377  m_xImpl->m_MediaProperties.setURL(url, "", rNewProperties.getReferer());
378  }
379  bBroadcastChanged = true;
380  }
381 
382  if( AVMediaSetMask::LOOP & nMaskSet )
383  m_xImpl->m_MediaProperties.setLoop( rNewProperties.isLoop() );
384 
385  if( AVMediaSetMask::MUTE & nMaskSet )
386  m_xImpl->m_MediaProperties.setMute( rNewProperties.isMute() );
387 
388  if( AVMediaSetMask::VOLUMEDB & nMaskSet )
389  m_xImpl->m_MediaProperties.setVolumeDB( rNewProperties.getVolumeDB() );
390 
391  if( AVMediaSetMask::ZOOM & nMaskSet )
392  m_xImpl->m_MediaProperties.setZoom( rNewProperties.getZoom() );
393 #else
394  (void) rNewProperties;
395 #endif
396 
397  if( bBroadcastChanged )
398  {
399  SetChanged();
401  }
402 }
403 
404 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Point TopLeft() const
OUString m_LastFailedPkgURL
Definition: svdomedia.cxx:52
AVMediaSetMask
void setWidth(tools::Long nWidth)
virtual ~SdrMediaObj() override
Definition: svdomedia.cxx:78
virtual bool HasTextEdit() const override
Definition: svdomedia.cxx:82
std::shared_ptr< ::avmedia::MediaTempFile > m_pTempFile
Definition: svdomedia.cxx:50
SdrObjKind
Definition: svdobjkind.hxx:24
sdr::contact::ViewContact & GetViewContact() const
Definition: svdobj.cxx:248
uno::Reference< graphic::XGraphic > m_xCachedSnapshot
Definition: svdomedia.cxx:51
Rectangle objects (rectangle, circle, ...)
Definition: svdorect.hxx:39
static OutputDevice * GetDefaultDevice()
constexpr tools::Long Width() const
Provides information about various ZObject properties.
Definition: svdobj.hxx:194
virtual SdrMediaObj * CloneSdrObject(SdrModel &rTargetModel) const override
Definition: svdomedia.cxx:141
OUString SvxResId(const char *pId)
Definition: dialmgr.cxx:25
const ::avmedia::MediaItem & getMediaProperties() const
Definition: svdomedia.cxx:237
tools::Rectangle maRect
Definition: svdotext.hxx:182
std::unique_ptr< Impl > m_xImpl
Definition: svdomedia.hxx:80
virtual OUString TakeObjNamePlural() const override
Definition: svdomedia.cxx:136
#define TOOLS_WARN_EXCEPTION(area, stream)
void setURL(const OUString &rURL, const OUString &rReferer, const OUString &rMimeType=OUString())
Definition: svdomedia.cxx:206
bool IsEmpty() const
virtual void TakeObjInfo(SdrObjTransformInfoRec &rInfo) const override
Definition: svdomedia.cxx:92
OUString sName
void BroadcastObjectChange() const
Definition: svdobj.cxx:982
const OUString & getURL() const
Definition: svdomedia.cxx:221
float u
SdrModel & getSdrModelFromSdrObject() const
Definition: svdobj.cxx:276
void mediaPropertiesChanged(const ::avmedia::MediaItem &rNewState)
copy a stream from XStorage to temp file
Definition: svdomedia.cxx:320
virtual OUString TakeObjNameSingul() const override
Definition: svdomedia.cxx:119
virtual void SetLogicRect(const tools::Rectangle &rRect)
Definition: svdobj.cxx:1679
OUString GetName() const
Definition: svdobj.cxx:775
Size GetSize() const
void SetInputStream(css::uno::Reference< css::io::XInputStream > const &)
Definition: svdomedia.cxx:255
css::uno::Reference< css::io::XInputStream > openStream()
css::uno::Reference< css::graphic::XGraphic > const & getSnapshot() const
Definition: svdomedia.cxx:146
constexpr tools::Long Height() const
#define SAL_INFO(area, stream)
OUString aName
SdrMediaObj(SdrModel &rSdrModel)
Definition: svdomedia.cxx:55
Reference< XComponentContext > getProcessComponentContext()
void setMediaProperties(const ::avmedia::MediaItem &rState)
Definition: svdomedia.cxx:231
virtual void AdjustToMaxRect(const tools::Rectangle &rMaxRect, bool bShrinkOnly=false) override
Definition: svdomedia.cxx:160
::avmedia::MediaItem m_MediaProperties
Definition: svdomedia.cxx:46
void setHeight(tools::Long nHeight)
css::uno::Reference< css::io::XInputStream > GetInputStream() const
Definition: svdomedia.cxx:242
#define SAL_WARN(area, stream)
virtual std::unique_ptr< sdr::contact::ViewContact > CreateObjectSpecificViewContact() override
Definition: svdomedia.cxx:87
virtual void SetChanged()
Definition: svdobj.cxx:1006
static css::uno::Reference< css::graphic::XGraphic > grabFrame(const OUString &rURL, const OUString &rReferer, const OUString &sMimeType)
bool CreateMediaTempFile(uno::Reference< io::XInputStream > const &xInStream, OUString &o_rTempFileURL, std::u16string_view rDesiredExtension)
void setURL(const OUString &rURL, const OUString &rTempURL, const OUString &rReferer)
css::uno::Reference< css::io::XInputStream > GetDocumentStream(OUString const &rURL,::comphelper::LifecycleProxy const &rProxy) const
Definition: svdmodel.cxx:798
Point Center() const
custom shape
Definition: svdobjkind.hxx:56
virtual SdrObjKind GetObjIdentifier() const override
Definition: svdomedia.cxx:114
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo