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