Adjust includes
[LibreOffice.git] / svx / source / svdraw / svdomedia.cxx
blob785a3a0f73fb85c4f282981ce08a7ca464e6c520
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <osl/file.hxx>
27 #include <com/sun/star/document/XStorageBasedDocument.hpp>
28 #include <com/sun/star/embed/XStorage.hpp>
30 #include <ucbhelper/content.hxx>
31 #include <comphelper/processfactory.hxx>
32 #include <comphelper/storagehelper.hxx>
34 #include <vcl/svapp.hxx>
36 #include <svx/svdmodel.hxx>
37 #include <svdglob.hxx>
38 #include <svx/strings.hrc>
39 #include <svx/sdr/contact/viewcontactofsdrmediaobj.hxx>
40 #include <avmedia/mediawindow.hxx>
42 using namespace ::com::sun::star;
45 // Note: the temp file is read only, until it is deleted!
46 // It may be shared between multiple documents in case of copy/paste,
47 // hence the shared_ptr.
48 struct MediaTempFile
50 OUString const m_TempFileURL;
51 MediaTempFile(OUString const& rURL)
52 : m_TempFileURL(rURL)
54 ~MediaTempFile()
56 ::osl::File::remove(m_TempFileURL);
60 struct SdrMediaObj::Impl
62 ::avmedia::MediaItem m_MediaProperties;
63 std::shared_ptr< MediaTempFile > m_pTempFile;
64 uno::Reference< graphic::XGraphic > m_xCachedSnapshot;
65 OUString m_LastFailedPkgURL;
69 SdrMediaObj::SdrMediaObj()
70 : SdrRectObj()
71 , m_xImpl( new Impl )
75 SdrMediaObj::SdrMediaObj( const tools::Rectangle& rRect )
76 : SdrRectObj( rRect )
77 , m_xImpl( new Impl )
81 SdrMediaObj::~SdrMediaObj()
85 bool SdrMediaObj::HasTextEdit() const
87 return false;
90 sdr::contact::ViewContact* SdrMediaObj::CreateObjectSpecificViewContact()
92 return new sdr::contact::ViewContactOfSdrMediaObj( *this );
95 void SdrMediaObj::TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const
97 rInfo.bMoveAllowed = true;
98 rInfo.bResizeFreeAllowed = true;
99 rInfo.bResizePropAllowed = true;
100 rInfo.bRotateFreeAllowed = false;
101 rInfo.bRotate90Allowed = false;
102 rInfo.bMirrorFreeAllowed = false;
103 rInfo.bMirror45Allowed = false;
104 rInfo.bMirror90Allowed = false;
105 rInfo.bTransparenceAllowed = false;
106 rInfo.bShearAllowed = false;
107 rInfo.bEdgeRadiusAllowed = false;
108 rInfo.bNoOrthoDesired = false;
109 rInfo.bNoContortion = false;
110 rInfo.bCanConvToPath = false;
111 rInfo.bCanConvToPoly = false;
112 rInfo.bCanConvToContour = false;
113 rInfo.bCanConvToPathLineToArea = false;
114 rInfo.bCanConvToPolyLineToArea = false;
117 sal_uInt16 SdrMediaObj::GetObjIdentifier() const
119 return sal_uInt16( OBJ_MEDIA );
122 OUString SdrMediaObj::TakeObjNameSingul() const
124 OUStringBuffer sName(ImpGetResStr(STR_ObjNameSingulMEDIA));
126 OUString aName(GetName());
128 if (!aName.isEmpty())
130 sName.append(' ');
131 sName.append('\'');
132 sName.append(aName);
133 sName.append('\'');
136 return sName.makeStringAndClear();
139 OUString SdrMediaObj::TakeObjNamePlural() const
141 return ImpGetResStr(STR_ObjNamePluralMEDIA);
144 SdrMediaObj* SdrMediaObj::Clone() const
146 return CloneHelper< SdrMediaObj >();
149 SdrMediaObj& SdrMediaObj::operator=(const SdrMediaObj& rObj)
151 if( this == &rObj )
152 return *this;
153 SdrRectObj::operator=( rObj );
155 m_xImpl->m_pTempFile = rObj.m_xImpl->m_pTempFile; // before props
156 setMediaProperties( rObj.getMediaProperties() );
157 m_xImpl->m_xCachedSnapshot = rObj.m_xImpl->m_xCachedSnapshot;
158 return *this;
161 const uno::Reference< graphic::XGraphic > SdrMediaObj::getSnapshot() const
163 #if HAVE_FEATURE_AVMEDIA
164 if( !m_xImpl->m_xCachedSnapshot.is() )
166 OUString aRealURL = m_xImpl->m_MediaProperties.getTempURL();
167 if( aRealURL.isEmpty() )
168 aRealURL = m_xImpl->m_MediaProperties.getURL();
169 m_xImpl->m_xCachedSnapshot = avmedia::MediaWindow::grabFrame( aRealURL, m_xImpl->m_MediaProperties.getReferer(), m_xImpl->m_MediaProperties.getMimeType());
171 #endif
172 return m_xImpl->m_xCachedSnapshot;
175 void SdrMediaObj::AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool bShrinkOnly /* = false */ )
177 Size aSize( Application::GetDefaultDevice()->PixelToLogic(
178 static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).getPreferredSize(),
179 MapMode(MapUnit::Map100thMM)) );
180 Size aMaxSize( rMaxRect.GetSize() );
182 if( aSize.Height() != 0 && aSize.Width() != 0 )
184 Point aPos( rMaxRect.TopLeft() );
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() )
192 float fGrfWH = (float)aSize.Width() /
193 (float)aSize.Height();
194 float fWinWH = (float)aMaxSize.Width() /
195 (float)aMaxSize.Height();
197 // scale graphic to page size
198 if ( fGrfWH < fWinWH )
200 aSize.Width() = (long)(aMaxSize.Height() * fGrfWH);
201 aSize.Height()= aMaxSize.Height();
203 else if ( fGrfWH > 0.F )
205 aSize.Width() = aMaxSize.Width();
206 aSize.Height()= (long)(aMaxSize.Width() / fGrfWH);
209 aPos = rMaxRect.Center();
212 if( bShrinkOnly )
213 aPos = maRect.TopLeft();
215 aPos.X() -= aSize.Width() / 2;
216 aPos.Y() -= aSize.Height() / 2;
217 SetLogicRect( tools::Rectangle( aPos, aSize ) );
221 void SdrMediaObj::setURL( const OUString& rURL, const OUString& rReferer, const OUString& rMimeType )
223 ::avmedia::MediaItem aURLItem;
224 #if HAVE_FEATURE_AVMEDIA
225 if( !rMimeType.isEmpty() )
226 m_xImpl->m_MediaProperties.setMimeType(rMimeType);
227 aURLItem.setURL( rURL, "", rReferer );
228 #else
229 (void) rMimeType;
230 (void) rURL;
231 (void) rReferer;
232 #endif
233 setMediaProperties( aURLItem );
236 const OUString& SdrMediaObj::getURL() const
238 #if HAVE_FEATURE_AVMEDIA
239 return m_xImpl->m_MediaProperties.getURL();
240 #else
241 static OUString ret;
242 return ret;
243 #endif
246 void SdrMediaObj::setMediaProperties( const ::avmedia::MediaItem& rState )
248 mediaPropertiesChanged( rState );
249 static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).executeMediaItem( getMediaProperties() );
252 const ::avmedia::MediaItem& SdrMediaObj::getMediaProperties() const
254 return m_xImpl->m_MediaProperties;
257 uno::Reference<io::XInputStream> SdrMediaObj::GetInputStream()
259 if (!m_xImpl->m_pTempFile)
261 SAL_WARN("svx", "this is only intended for embedded media");
262 return nullptr;
264 ucbhelper::Content tempFile(m_xImpl->m_pTempFile->m_TempFileURL,
265 uno::Reference<ucb::XCommandEnvironment>(),
266 comphelper::getProcessComponentContext());
267 return tempFile.openStream();
270 static bool lcl_CopyToTempFile(
271 uno::Reference<io::XInputStream> const& xInStream,
272 OUString & o_rTempFileURL)
274 OUString tempFileURL;
275 ::osl::FileBase::RC const err =
276 ::osl::FileBase::createTempFile(nullptr, nullptr, & tempFileURL);
277 if (::osl::FileBase::E_None != err)
279 SAL_INFO("svx", "cannot create temp file");
280 return false;
285 ::ucbhelper::Content tempContent(tempFileURL,
286 uno::Reference<ucb::XCommandEnvironment>(),
287 comphelper::getProcessComponentContext());
288 tempContent.writeStream(xInStream, true); // copy stream to file
290 catch (uno::Exception const& e)
292 SAL_WARN("svx", "exception: '" << e << "'");
293 return false;
295 o_rTempFileURL = tempFileURL;
296 return true;
299 void SdrMediaObj::SetInputStream(uno::Reference<io::XInputStream> const& xStream)
301 if (m_xImpl->m_pTempFile || m_xImpl->m_LastFailedPkgURL.isEmpty())
303 SAL_WARN("svx", "this is only intended for embedded media");
304 return;
306 OUString tempFileURL;
307 bool const bSuccess = lcl_CopyToTempFile(xStream, tempFileURL);
308 if (bSuccess)
310 m_xImpl->m_pTempFile.reset(new MediaTempFile(tempFileURL));
311 m_xImpl->m_MediaProperties.setURL(
312 m_xImpl->m_LastFailedPkgURL, tempFileURL, "");
314 m_xImpl->m_LastFailedPkgURL.clear(); // once only
317 /// copy a stream from XStorage to temp file
318 #if HAVE_FEATURE_AVMEDIA
319 static bool lcl_HandlePackageURL(
320 OUString const & rURL,
321 SdrModel const *const pModel,
322 OUString & o_rTempFileURL)
324 if (!pModel)
326 SAL_WARN("svx", "no model");
327 return false;
329 ::comphelper::LifecycleProxy sourceProxy;
330 uno::Reference<io::XInputStream> xInStream;
331 try {
332 xInStream = pModel->GetDocumentStream(rURL, sourceProxy);
334 catch (container::NoSuchElementException const&)
336 SAL_INFO("svx", "not found: '" << rURL << "'");
337 return false;
339 catch (uno::Exception const& e)
341 SAL_WARN("svx", "exception: '" << e << "'");
342 return false;
344 if (!xInStream.is())
346 SAL_WARN("svx", "no stream?");
347 return false;
349 return lcl_CopyToTempFile(xInStream, o_rTempFileURL);
351 #endif
353 void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProperties )
355 bool bBroadcastChanged = false;
356 #if HAVE_FEATURE_AVMEDIA
357 const AVMediaSetMask nMaskSet = rNewProperties.getMaskSet();
359 // use only a subset of MediaItem properties for own properties
360 if( AVMediaSetMask::MIME_TYPE & nMaskSet )
361 m_xImpl->m_MediaProperties.setMimeType( rNewProperties.getMimeType() );
363 if( ( AVMediaSetMask::URL & nMaskSet ) &&
364 ( rNewProperties.getURL() != getURL() ))
366 m_xImpl->m_xCachedSnapshot.clear();
367 OUString const& url(rNewProperties.getURL());
368 if (url.startsWithIgnoreAsciiCase("vnd.sun.star.Package:"))
370 if ( !m_xImpl->m_pTempFile
371 || (m_xImpl->m_pTempFile->m_TempFileURL !=
372 rNewProperties.getTempURL()))
374 OUString tempFileURL;
375 bool bSuccess;
376 bSuccess = lcl_HandlePackageURL(url, GetModel(), tempFileURL);
377 if (bSuccess)
379 m_xImpl->m_pTempFile.reset(
380 new MediaTempFile(tempFileURL));
381 m_xImpl->m_MediaProperties.setURL(url, tempFileURL, "");
383 else // this case is for Clone via operator=
385 m_xImpl->m_pTempFile.reset();
386 m_xImpl->m_MediaProperties.setURL("", "", "");
387 // UGLY: oox import also gets here, because unlike ODF
388 // getDocumentStorage() is not the imported file...
389 m_xImpl->m_LastFailedPkgURL = url;
392 else
394 m_xImpl->m_MediaProperties.setURL(url,
395 rNewProperties.getTempURL(), "");
398 else
400 m_xImpl->m_pTempFile.reset();
401 m_xImpl->m_MediaProperties.setURL(url, "", rNewProperties.getReferer());
403 bBroadcastChanged = true;
406 if( AVMediaSetMask::LOOP & nMaskSet )
407 m_xImpl->m_MediaProperties.setLoop( rNewProperties.isLoop() );
409 if( AVMediaSetMask::MUTE & nMaskSet )
410 m_xImpl->m_MediaProperties.setMute( rNewProperties.isMute() );
412 if( AVMediaSetMask::VOLUMEDB & nMaskSet )
413 m_xImpl->m_MediaProperties.setVolumeDB( rNewProperties.getVolumeDB() );
415 if( AVMediaSetMask::ZOOM & nMaskSet )
416 m_xImpl->m_MediaProperties.setZoom( rNewProperties.getZoom() );
417 #else
418 (void) rNewProperties;
419 #endif
421 if( bBroadcastChanged )
423 SetChanged();
424 BroadcastObjectChange();
428 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */