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 <avmedia/mediaitem.hxx>
22 #include <com/sun/star/uno/Sequence.hxx>
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <com/sun/star/embed/ElementModes.hpp>
26 #include <com/sun/star/embed/XStorage.hpp>
27 #include <com/sun/star/embed/XTransactedObject.hpp>
28 #include <com/sun/star/document/XStorageBasedDocument.hpp>
29 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
30 #include <com/sun/star/uri/UriReferenceFactory.hpp>
31 #include <com/sun/star/uri/XUriReference.hpp>
32 #include <com/sun/star/uri/XUriReferenceFactory.hpp>
34 #include <rtl/ustrbuf.hxx>
36 #include <ucbhelper/content.hxx>
38 #include <comphelper/processfactory.hxx>
39 #include <comphelper/storagehelper.hxx>
41 using namespace ::com::sun::star
;
50 TYPEINIT1_AUTOFACTORY( MediaItem
, ::SfxPoolItem
);
52 struct MediaItem::Impl
55 OUString m_TempFileURL
;
56 sal_uInt32 m_nMaskSet
;
60 sal_Int16 m_nVolumeDB
;
63 ::com::sun::star::media::ZoomLevel m_eZoom
;
65 Impl(sal_uInt32
const nMaskSet
)
66 : m_nMaskSet( nMaskSet
)
67 , m_eState( MEDIASTATE_STOP
)
73 , m_eZoom( ::com::sun::star::media::ZoomLevel_NOT_AVAILABLE
)
76 Impl(Impl
const& rOther
)
77 : m_URL( rOther
.m_URL
)
78 , m_TempFileURL( rOther
.m_TempFileURL
)
79 , m_nMaskSet( rOther
.m_nMaskSet
)
80 , m_eState( rOther
.m_eState
)
81 , m_fTime( rOther
.m_fTime
)
82 , m_fDuration( rOther
.m_fDuration
)
83 , m_nVolumeDB( rOther
.m_nVolumeDB
)
84 , m_bLoop( rOther
.m_bLoop
)
85 , m_bMute( rOther
.m_bMute
)
86 , m_eZoom( rOther
.m_eZoom
)
91 // ------------------------------------------------------------------------------
93 MediaItem::MediaItem( sal_uInt16
const i_nWhich
, sal_uInt32
const nMaskSet
)
94 : SfxPoolItem( i_nWhich
)
95 , m_pImpl( new Impl(nMaskSet
) )
99 // ------------------------------------------------------------------------------
101 MediaItem::MediaItem( const MediaItem
& rItem
)
102 : SfxPoolItem( rItem
)
103 , m_pImpl( new Impl(*rItem
.m_pImpl
) )
107 // ------------------------------------------------------------------------------
109 MediaItem::~MediaItem()
113 // ------------------------------------------------------------------------------
115 int MediaItem::operator==( const SfxPoolItem
& rItem
) const
117 assert( SfxPoolItem::operator==(rItem
));
118 MediaItem
const& rOther(static_cast< const MediaItem
& >(rItem
));
119 return m_pImpl
->m_nMaskSet
== rOther
.m_pImpl
->m_nMaskSet
120 && m_pImpl
->m_URL
== rOther
.m_pImpl
->m_URL
121 && m_pImpl
->m_eState
== rOther
.m_pImpl
->m_eState
122 && m_pImpl
->m_fDuration
== rOther
.m_pImpl
->m_fDuration
123 && m_pImpl
->m_fTime
== rOther
.m_pImpl
->m_fTime
124 && m_pImpl
->m_nVolumeDB
== rOther
.m_pImpl
->m_nVolumeDB
125 && m_pImpl
->m_bLoop
== rOther
.m_pImpl
->m_bLoop
126 && m_pImpl
->m_bMute
== rOther
.m_pImpl
->m_bMute
127 && m_pImpl
->m_eZoom
== rOther
.m_pImpl
->m_eZoom
;
130 // ------------------------------------------------------------------------------
132 SfxPoolItem
* MediaItem::Clone( SfxItemPool
* ) const
134 return new MediaItem( *this );
137 //------------------------------------------------------------------------
139 SfxItemPresentation
MediaItem::GetPresentation( SfxItemPresentation
,
143 const IntlWrapper
* ) const
146 return SFX_ITEM_PRESENTATION_NONE
;
149 //------------------------------------------------------------------------
151 bool MediaItem::QueryValue( com::sun::star::uno::Any
& rVal
, sal_uInt8
) const
153 uno::Sequence
< uno::Any
> aSeq( 9 );
155 aSeq
[ 0 ] <<= m_pImpl
->m_URL
;
156 aSeq
[ 1 ] <<= m_pImpl
->m_nMaskSet
;
157 aSeq
[ 2 ] <<= static_cast< sal_Int32
>( m_pImpl
->m_eState
);
158 aSeq
[ 3 ] <<= m_pImpl
->m_fTime
;
159 aSeq
[ 4 ] <<= m_pImpl
->m_fDuration
;
160 aSeq
[ 5 ] <<= m_pImpl
->m_nVolumeDB
;
161 aSeq
[ 6 ] <<= m_pImpl
->m_bLoop
;
162 aSeq
[ 7 ] <<= m_pImpl
->m_bMute
;
163 aSeq
[ 8 ] <<= m_pImpl
->m_eZoom
;
170 //------------------------------------------------------------------------
172 bool MediaItem::PutValue( const com::sun::star::uno::Any
& rVal
, sal_uInt8
)
174 uno::Sequence
< uno::Any
> aSeq
;
177 if( ( rVal
>>= aSeq
) && ( aSeq
.getLength() == 9 ) )
179 sal_Int32 nInt32
= 0;
181 aSeq
[ 0 ] >>= m_pImpl
->m_URL
;
182 aSeq
[ 1 ] >>= m_pImpl
->m_nMaskSet
;
183 aSeq
[ 2 ] >>= nInt32
;
184 m_pImpl
->m_eState
= static_cast< MediaState
>( nInt32
);
185 aSeq
[ 3 ] >>= m_pImpl
->m_fTime
;
186 aSeq
[ 4 ] >>= m_pImpl
->m_fDuration
;
187 aSeq
[ 5 ] >>= m_pImpl
->m_nVolumeDB
;
188 aSeq
[ 6 ] >>= m_pImpl
->m_bLoop
;
189 aSeq
[ 7 ] >>= m_pImpl
->m_bMute
;
190 aSeq
[ 8 ] >>= m_pImpl
->m_eZoom
;
198 //------------------------------------------------------------------------
200 void MediaItem::merge( const MediaItem
& rMediaItem
)
202 const sal_uInt32 nMaskSet
= rMediaItem
.getMaskSet();
204 if( AVMEDIA_SETMASK_URL
& nMaskSet
)
205 setURL( rMediaItem
.getURL(), &rMediaItem
.getTempURL() );
207 if( AVMEDIA_SETMASK_STATE
& nMaskSet
)
208 setState( rMediaItem
.getState() );
210 if( AVMEDIA_SETMASK_DURATION
& nMaskSet
)
211 setDuration( rMediaItem
.getDuration() );
213 if( AVMEDIA_SETMASK_TIME
& nMaskSet
)
214 setTime( rMediaItem
.getTime() );
216 if( AVMEDIA_SETMASK_LOOP
& nMaskSet
)
217 setLoop( rMediaItem
.isLoop() );
219 if( AVMEDIA_SETMASK_MUTE
& nMaskSet
)
220 setMute( rMediaItem
.isMute() );
222 if( AVMEDIA_SETMASK_VOLUMEDB
& nMaskSet
)
223 setVolumeDB( rMediaItem
.getVolumeDB() );
225 if( AVMEDIA_SETMASK_ZOOM
& nMaskSet
)
226 setZoom( rMediaItem
.getZoom() );
229 //------------------------------------------------------------------------
231 sal_uInt32
MediaItem::getMaskSet() const
233 return m_pImpl
->m_nMaskSet
;
236 //------------------------------------------------------------------------
238 void MediaItem::setURL( const OUString
& rURL
,
239 OUString
const*const pTempURL
)
241 m_pImpl
->m_URL
= rURL
;
242 m_pImpl
->m_nMaskSet
|= AVMEDIA_SETMASK_URL
;
243 m_pImpl
->m_TempFileURL
= (pTempURL
) ? *pTempURL
: OUString();
246 //------------------------------------------------------------------------
248 const OUString
& MediaItem::getURL() const
250 return m_pImpl
->m_URL
;
253 const OUString
& MediaItem::getTempURL() const
255 return m_pImpl
->m_TempFileURL
;
258 //------------------------------------------------------------------------
260 void MediaItem::setState( MediaState eState
)
262 m_pImpl
->m_eState
= eState
;
263 m_pImpl
->m_nMaskSet
|= AVMEDIA_SETMASK_STATE
;
266 //------------------------------------------------------------------------
268 MediaState
MediaItem::getState() const
270 return m_pImpl
->m_eState
;
273 //------------------------------------------------------------------------
275 void MediaItem::setDuration( double fDuration
)
277 m_pImpl
->m_fDuration
= fDuration
;
278 m_pImpl
->m_nMaskSet
|= AVMEDIA_SETMASK_DURATION
;
281 //------------------------------------------------------------------------
283 double MediaItem::getDuration() const
285 return m_pImpl
->m_fDuration
;
288 //------------------------------------------------------------------------
290 void MediaItem::setTime( double fTime
)
292 m_pImpl
->m_fTime
= fTime
;
293 m_pImpl
->m_nMaskSet
|= AVMEDIA_SETMASK_TIME
;
296 //------------------------------------------------------------------------
298 double MediaItem::getTime() const
300 return m_pImpl
->m_fTime
;
303 //------------------------------------------------------------------------
305 void MediaItem::setLoop( bool bLoop
)
307 m_pImpl
->m_bLoop
= bLoop
;
308 m_pImpl
->m_nMaskSet
|= AVMEDIA_SETMASK_LOOP
;
311 //------------------------------------------------------------------------
313 bool MediaItem::isLoop() const
315 return m_pImpl
->m_bLoop
;
318 //------------------------------------------------------------------------
320 void MediaItem::setMute( bool bMute
)
322 m_pImpl
->m_bMute
= bMute
;
323 m_pImpl
->m_nMaskSet
|= AVMEDIA_SETMASK_MUTE
;
326 //------------------------------------------------------------------------
328 bool MediaItem::isMute() const
330 return m_pImpl
->m_bMute
;
333 //------------------------------------------------------------------------
335 void MediaItem::setVolumeDB( sal_Int16 nDB
)
337 m_pImpl
->m_nVolumeDB
= nDB
;
338 m_pImpl
->m_nMaskSet
|= AVMEDIA_SETMASK_VOLUMEDB
;
341 //------------------------------------------------------------------------
343 sal_Int16
MediaItem::getVolumeDB() const
345 return m_pImpl
->m_nVolumeDB
;
348 //------------------------------------------------------------------------
350 void MediaItem::setZoom( ::com::sun::star::media::ZoomLevel eZoom
)
352 m_pImpl
->m_eZoom
= eZoom
;
353 m_pImpl
->m_nMaskSet
|= AVMEDIA_SETMASK_ZOOM
;
356 //------------------------------------------------------------------------
358 ::com::sun::star::media::ZoomLevel
MediaItem::getZoom() const
360 return m_pImpl
->m_eZoom
;
363 //------------------------------------------------------------------------
365 static OUString
lcl_GetFilename(OUString
const& rSourceURL
)
367 uno::Reference
<uri::XUriReferenceFactory
> const xUriFactory(
368 uri::UriReferenceFactory::create(
369 comphelper::getProcessComponentContext()));
370 uno::Reference
<uri::XUriReference
> const xSourceURI(
371 xUriFactory
->parse(rSourceURL
), uno::UNO_SET_THROW
);
375 sal_Int32
const nSegments(xSourceURI
->getPathSegmentCount());
378 filename
= xSourceURI
->getPathSegment(nSegments
- 1);
381 if (!::comphelper::OStorageHelper::IsValidZipEntryFileName(
382 filename
, false) || !filename
.getLength())
389 static uno::Reference
<io::XStream
>
390 lcl_CreateStream(uno::Reference
<embed::XStorage
> const& xStorage
,
391 OUString
const& rFilename
)
393 OUString
filename(rFilename
);
395 if (xStorage
->hasByName(filename
))
399 sal_Int32
const nIndex(rFilename
.lastIndexOf(sal_Unicode('.')));
402 basename
= rFilename
.copy(0, nIndex
);
403 suffix
= rFilename
.copy(nIndex
);
405 sal_Int32
count(0); // sigh... try to generate non-existent name
409 filename
= basename
+ OUString::valueOf(count
) + suffix
;
411 while (xStorage
->hasByName(filename
));
414 uno::Reference
<io::XStream
> const xStream(
415 xStorage
->openStreamElement(filename
,
416 embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
),
418 uno::Reference
< beans::XPropertySet
> const xStreamProps(xStream
,
420 if (xStreamProps
.is()) { // this is NOT supported in FileSystemStorage
421 xStreamProps
->setPropertyValue("MediaType", uno::makeAny(OUString(
422 //FIXME how to detect real media type?
423 //but currently xmloff has this one hardcoded anyway...
424 "application/vnd.sun.star.media")));
425 xStreamProps
->setPropertyValue( // turn off compression
426 "Compressed", uno::makeAny(sal_False
));
431 bool EmbedMedia(uno::Reference
<frame::XModel
> const& xModel
,
432 OUString
const& rSourceURL
, OUString
& o_rEmbeddedURL
)
436 ::ucbhelper::Content
sourceContent(rSourceURL
,
437 uno::Reference
<ucb::XCommandEnvironment
>(),
438 comphelper::getProcessComponentContext());
440 uno::Reference
<document::XStorageBasedDocument
> const xSBD(xModel
,
441 uno::UNO_QUERY_THROW
);
442 uno::Reference
<embed::XStorage
> const xStorage(
443 xSBD
->getDocumentStorage(), uno::UNO_QUERY_THROW
);
445 OUString
const media("Media");
446 uno::Reference
<embed::XStorage
> const xSubStorage(
447 xStorage
->openStorageElement(media
, embed::ElementModes::WRITE
));
449 OUString
filename(lcl_GetFilename(rSourceURL
));
451 uno::Reference
<io::XStream
> const xStream(
452 lcl_CreateStream(xSubStorage
, filename
), uno::UNO_SET_THROW
);
453 uno::Reference
<io::XOutputStream
> const xOutStream(
454 xStream
->getOutputStream(), uno::UNO_SET_THROW
);
456 if (!sourceContent
.openStream(xOutStream
)) // copy file to storage
458 SAL_INFO("avmedia", "openStream to storage failed");
462 uno::Reference
<embed::XTransactedObject
> const xSubTransaction(
463 xSubStorage
, uno::UNO_QUERY
);
464 if (xSubTransaction
.is()) {
465 xSubTransaction
->commit();
467 uno::Reference
<embed::XTransactedObject
> const xTransaction(
468 xStorage
, uno::UNO_QUERY
);
469 if (xTransaction
.is()) {
470 xTransaction
->commit();
473 OUStringBuffer
buf("vnd.sun.star.Package:");
475 buf
.append(sal_Unicode('/'));
476 buf
.append(filename
);
477 o_rEmbeddedURL
= buf
.makeStringAndClear();
480 catch (uno::Exception
const&)
483 "Exception while trying to embed media");
490 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */