nss: upgrade to release 3.73
[LibreOffice.git] / svx / source / svdraw / svdomedia.cxx
blob42c7a6c59c8d688ec4b11490c606739265c00653
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.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_features.h>
22 #include <svx/svdomedia.hxx>
24 #include <rtl/ustring.hxx>
25 #include <rtl/ustrbuf.hxx>
26 #include <sal/log.hxx>
28 #include <ucbhelper/content.hxx>
29 #include <comphelper/processfactory.hxx>
30 #include <comphelper/storagehelper.hxx>
32 #include <vcl/svapp.hxx>
34 #include <svx/svdmodel.hxx>
35 #include <svx/dialmgr.hxx>
36 #include <svx/strings.hrc>
37 #include <svx/sdr/contact/viewcontactofsdrmediaobj.hxx>
38 #include <avmedia/mediawindow.hxx>
39 #include <tools/diagnose_ex.h>
41 using namespace ::com::sun::star;
44 struct SdrMediaObj::Impl
46 ::avmedia::MediaItem m_MediaProperties;
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;
52 OUString m_LastFailedPkgURL;
55 SdrMediaObj::SdrMediaObj(SdrModel& rSdrModel)
56 : SdrRectObj(rSdrModel)
57 ,m_xImpl( new Impl )
61 SdrMediaObj::SdrMediaObj(
62 SdrModel& rSdrModel,
63 const tools::Rectangle& rRect)
64 : SdrRectObj(rSdrModel, rRect)
65 ,m_xImpl( new Impl )
69 SdrMediaObj::~SdrMediaObj()
73 bool SdrMediaObj::HasTextEdit() const
75 return false;
78 std::unique_ptr<sdr::contact::ViewContact> SdrMediaObj::CreateObjectSpecificViewContact()
80 return std::make_unique<sdr::contact::ViewContactOfSdrMediaObj>( *this );
83 void SdrMediaObj::TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const
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;
105 SdrObjKind SdrMediaObj::GetObjIdentifier() const
107 return OBJ_MEDIA;
110 OUString SdrMediaObj::TakeObjNameSingul() const
112 OUStringBuffer sName(SvxResId(STR_ObjNameSingulMEDIA));
114 OUString aName(GetName());
116 if (!aName.isEmpty())
118 sName.append(' ');
119 sName.append('\'');
120 sName.append(aName);
121 sName.append('\'');
124 return sName.makeStringAndClear();
127 OUString SdrMediaObj::TakeObjNamePlural() const
129 return SvxResId(STR_ObjNamePluralMEDIA);
132 SdrMediaObj* SdrMediaObj::CloneSdrObject(SdrModel& rTargetModel) const
134 return CloneHelper< SdrMediaObj >(rTargetModel);
137 SdrMediaObj& SdrMediaObj::operator=(const SdrMediaObj& rObj)
139 if( this == &rObj )
140 return *this;
141 SdrRectObj::operator=( rObj );
143 m_xImpl->m_pTempFile = rObj.m_xImpl->m_pTempFile; // before props
144 setMediaProperties( rObj.getMediaProperties() );
145 m_xImpl->m_xCachedSnapshot = rObj.m_xImpl->m_xCachedSnapshot;
146 return *this;
149 uno::Reference< graphic::XGraphic > const & SdrMediaObj::getSnapshot() const
151 #if HAVE_FEATURE_AVMEDIA
152 if( !m_xImpl->m_xCachedSnapshot.is() )
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());
159 #endif
160 return m_xImpl->m_xCachedSnapshot;
163 void SdrMediaObj::AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool bShrinkOnly /* = false */ )
165 Size aSize( Application::GetDefaultDevice()->PixelToLogic(
166 static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).getPreferredSize(),
167 MapMode(MapUnit::Map100thMM)) );
168 Size aMaxSize( rMaxRect.GetSize() );
170 if( aSize.IsEmpty() )
171 return;
173 Point aPos( rMaxRect.TopLeft() );
175 // if graphic is too large, fit it to the page
176 if ( (!bShrinkOnly ||
177 ( aSize.Height() > aMaxSize.Height() ) ||
178 ( aSize.Width() > aMaxSize.Width() ) )&&
179 aSize.Height() && aMaxSize.Height() )
181 float fGrfWH = static_cast<float>(aSize.Width()) /
182 static_cast<float>(aSize.Height());
183 float fWinWH = static_cast<float>(aMaxSize.Width()) /
184 static_cast<float>(aMaxSize.Height());
186 // scale graphic to page size
187 if ( fGrfWH < fWinWH )
189 aSize.setWidth( static_cast<tools::Long>(aMaxSize.Height() * fGrfWH) );
190 aSize.setHeight( aMaxSize.Height() );
192 else if ( fGrfWH > 0.F )
194 aSize.setWidth( aMaxSize.Width() );
195 aSize.setHeight( static_cast<tools::Long>(aMaxSize.Width() / fGrfWH) );
198 aPos = rMaxRect.Center();
201 if( bShrinkOnly )
202 aPos = maRect.TopLeft();
204 aPos.AdjustX( -(aSize.Width() / 2) );
205 aPos.AdjustY( -(aSize.Height() / 2) );
206 SetLogicRect( tools::Rectangle( aPos, aSize ) );
209 void SdrMediaObj::setURL( const OUString& rURL, const OUString& rReferer, const OUString& rMimeType )
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 );
224 const OUString& SdrMediaObj::getURL() const
226 #if HAVE_FEATURE_AVMEDIA
227 return m_xImpl->m_MediaProperties.getURL();
228 #else
229 static OUString ret;
230 return ret;
231 #endif
234 void SdrMediaObj::setMediaProperties( const ::avmedia::MediaItem& rState )
236 mediaPropertiesChanged( rState );
237 static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).executeMediaItem( getMediaProperties() );
240 const ::avmedia::MediaItem& SdrMediaObj::getMediaProperties() const
242 return m_xImpl->m_MediaProperties;
245 uno::Reference<io::XInputStream> SdrMediaObj::GetInputStream() const
247 if (!m_xImpl->m_pTempFile)
249 SAL_WARN("svx", "this is only intended for embedded media");
250 return nullptr;
252 ucbhelper::Content tempFile(m_xImpl->m_pTempFile->m_TempFileURL,
253 uno::Reference<ucb::XCommandEnvironment>(),
254 comphelper::getProcessComponentContext());
255 return tempFile.openStream();
258 void SdrMediaObj::SetInputStream(uno::Reference<io::XInputStream> const& xStream)
260 if (m_xImpl->m_pTempFile || m_xImpl->m_LastFailedPkgURL.isEmpty())
262 SAL_WARN("svx", "this is only intended for embedded media");
263 return;
266 OUString tempFileURL;
267 const bool bSuccess(
268 ::avmedia::CreateMediaTempFile(
269 xStream,
270 tempFileURL,
271 ""));
273 if (bSuccess)
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
281 m_xImpl->m_LastFailedPkgURL.clear(); // once only
284 /// copy a stream from XStorage to temp file
285 #if HAVE_FEATURE_AVMEDIA
286 static bool lcl_HandlePackageURL(
287 OUString const & rURL,
288 const SdrModel& rModel,
289 OUString & o_rTempFileURL)
291 ::comphelper::LifecycleProxy sourceProxy;
292 uno::Reference<io::XInputStream> xInStream;
293 try {
294 xInStream = rModel.GetDocumentStream(rURL, sourceProxy);
296 catch (container::NoSuchElementException const&)
298 SAL_INFO("svx", "not found: '" << rURL << "'");
299 return false;
301 catch (uno::Exception const&)
303 TOOLS_WARN_EXCEPTION("svx", "");
304 return false;
306 if (!xInStream.is())
308 SAL_WARN("svx", "no stream?");
309 return false;
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);
321 #endif
323 void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProperties )
325 bool bBroadcastChanged = false;
326 #if HAVE_FEATURE_AVMEDIA
327 const AVMediaSetMask nMaskSet = rNewProperties.getMaskSet();
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() );
333 if( ( AVMediaSetMask::URL & nMaskSet ) &&
334 ( rNewProperties.getURL() != getURL() ))
336 m_xImpl->m_xCachedSnapshot.clear();
337 OUString const& url(rNewProperties.getURL());
338 if (url.startsWithIgnoreAsciiCase("vnd.sun.star.Package:"))
340 if ( !m_xImpl->m_pTempFile
341 || (m_xImpl->m_pTempFile->m_TempFileURL !=
342 rNewProperties.getTempURL()))
344 OUString tempFileURL;
345 const bool bSuccess(
346 lcl_HandlePackageURL(
347 url,
348 getSdrModelFromSdrObject(),
349 tempFileURL));
351 if (bSuccess)
353 m_xImpl->m_pTempFile =
354 std::make_shared<::avmedia::MediaTempFile>(tempFileURL);
355 m_xImpl->m_MediaProperties.setURL(url, tempFileURL, "");
357 else // this case is for Clone via operator=
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;
366 else
368 m_xImpl->m_MediaProperties.setURL(url,
369 rNewProperties.getTempURL(), "");
372 else
374 m_xImpl->m_pTempFile.reset();
375 m_xImpl->m_MediaProperties.setURL(url, "", rNewProperties.getReferer());
377 bBroadcastChanged = true;
380 if( AVMediaSetMask::LOOP & nMaskSet )
381 m_xImpl->m_MediaProperties.setLoop( rNewProperties.isLoop() );
383 if( AVMediaSetMask::MUTE & nMaskSet )
384 m_xImpl->m_MediaProperties.setMute( rNewProperties.isMute() );
386 if( AVMediaSetMask::VOLUMEDB & nMaskSet )
387 m_xImpl->m_MediaProperties.setVolumeDB( rNewProperties.getVolumeDB() );
389 if( AVMediaSetMask::ZOOM & nMaskSet )
390 m_xImpl->m_MediaProperties.setZoom( rNewProperties.getZoom() );
391 #else
392 (void) rNewProperties;
393 #endif
395 if( bBroadcastChanged )
397 SetChanged();
398 BroadcastObjectChange();
402 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */