Version 4.0.0.1, tag libreoffice-4.0.0.1
[LibreOffice.git] / avmedia / source / framework / mediaitem.cxx
blob2776809d255a79a0e281f25eb40ddac75925283c
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 <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;
43 namespace avmedia
46 // -------------
47 // - MediaItem -
48 // -------------
50 TYPEINIT1_AUTOFACTORY( MediaItem, ::SfxPoolItem );
52 struct MediaItem::Impl
54 OUString m_URL;
55 OUString m_TempFileURL;
56 sal_uInt32 m_nMaskSet;
57 MediaState m_eState;
58 double m_fTime;
59 double m_fDuration;
60 sal_Int16 m_nVolumeDB;
61 bool m_bLoop;
62 bool m_bMute;
63 ::com::sun::star::media::ZoomLevel m_eZoom;
65 Impl(sal_uInt32 const nMaskSet)
66 : m_nMaskSet( nMaskSet )
67 , m_eState( MEDIASTATE_STOP )
68 , m_fTime( 0.0 )
69 , m_fDuration( 0.0 )
70 , m_nVolumeDB( 0 )
71 , m_bLoop( false )
72 , m_bMute( false )
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,
140 SfxMapUnit,
141 SfxMapUnit,
142 XubString& rText,
143 const IntlWrapper * ) const
145 rText.Erase();
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;
165 rVal <<= aSeq;
167 return true;
170 //------------------------------------------------------------------------
172 bool MediaItem::PutValue( const com::sun::star::uno::Any& rVal, sal_uInt8 )
174 uno::Sequence< uno::Any > aSeq;
175 bool bRet = false;
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;
192 bRet = true;
195 return bRet;
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);
373 OUString filename;
375 sal_Int32 const nSegments(xSourceURI->getPathSegmentCount());
376 if (0 < nSegments)
378 filename = xSourceURI->getPathSegment(nSegments - 1);
381 if (!::comphelper::OStorageHelper::IsValidZipEntryFileName(
382 filename, false) || !filename.getLength())
384 filename = "media";
386 return filename;
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))
397 OUString basename;
398 OUString suffix;
399 sal_Int32 const nIndex(rFilename.lastIndexOf(sal_Unicode('.')));
400 if (0 < nIndex)
402 basename = rFilename.copy(0, nIndex);
403 suffix = rFilename.copy(nIndex);
405 sal_Int32 count(0); // sigh... try to generate non-existent name
408 ++count;
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),
417 uno::UNO_SET_THROW);
418 uno::Reference< beans::XPropertySet > const xStreamProps(xStream,
419 uno::UNO_QUERY);
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));
428 return xStream;
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");
459 return false;
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:");
474 buf.append(media);
475 buf.append(sal_Unicode('/'));
476 buf.append(filename);
477 o_rEmbeddedURL = buf.makeStringAndClear();
478 return true;
480 catch (uno::Exception const&)
482 SAL_WARN("avmedia",
483 "Exception while trying to embed media");
485 return false;
490 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */