1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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.
50 OUString
const m_TempFileURL
;
51 MediaTempFile(OUString
const& rURL
)
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()
75 SdrMediaObj::SdrMediaObj( const tools::Rectangle
& rRect
)
81 SdrMediaObj::~SdrMediaObj()
85 bool SdrMediaObj::HasTextEdit() const
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())
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
)
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
;
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());
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();
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
);
233 setMediaProperties( aURLItem
);
236 const OUString
& SdrMediaObj::getURL() const
238 #if HAVE_FEATURE_AVMEDIA
239 return m_xImpl
->m_MediaProperties
.getURL();
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");
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");
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
<< "'");
295 o_rTempFileURL
= tempFileURL
;
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");
306 OUString tempFileURL
;
307 bool const bSuccess
= lcl_CopyToTempFile(xStream
, tempFileURL
);
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
)
326 SAL_WARN("svx", "no model");
329 ::comphelper::LifecycleProxy sourceProxy
;
330 uno::Reference
<io::XInputStream
> xInStream
;
332 xInStream
= pModel
->GetDocumentStream(rURL
, sourceProxy
);
334 catch (container::NoSuchElementException
const&)
336 SAL_INFO("svx", "not found: '" << rURL
<< "'");
339 catch (uno::Exception
const& e
)
341 SAL_WARN("svx", "exception: '" << e
<< "'");
346 SAL_WARN("svx", "no stream?");
349 return lcl_CopyToTempFile(xInStream
, o_rTempFileURL
);
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
;
376 bSuccess
= lcl_HandlePackageURL(url
, GetModel(), tempFileURL
);
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
;
394 m_xImpl
->m_MediaProperties
.setURL(url
,
395 rNewProperties
.getTempURL(), "");
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() );
418 (void) rNewProperties
;
421 if( bBroadcastChanged
)
424 BroadcastObjectChange();
428 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */