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