Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <avmedia/mediaitem.hxx>
21 :
22 : #include <com/sun/star/uno/Sequence.hxx>
23 :
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>
33 :
34 : #include <rtl/ustrbuf.hxx>
35 :
36 : #include <ucbhelper/content.hxx>
37 :
38 : #include <comphelper/processfactory.hxx>
39 : #include <comphelper/storagehelper.hxx>
40 :
41 : using namespace ::com::sun::star;
42 :
43 : namespace avmedia
44 : {
45 :
46 : // -------------
47 : // - MediaItem -
48 : // -------------
49 :
50 36 : TYPEINIT1_AUTOFACTORY( MediaItem, ::SfxPoolItem );
51 :
52 0 : struct MediaItem::Impl
53 : {
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;
64 :
65 0 : 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 0 : , m_eZoom( ::com::sun::star::media::ZoomLevel_NOT_AVAILABLE )
74 : {
75 0 : }
76 0 : 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 0 : , m_eZoom( rOther.m_eZoom )
87 : {
88 0 : }
89 : };
90 :
91 : // ------------------------------------------------------------------------------
92 :
93 0 : MediaItem::MediaItem( sal_uInt16 const i_nWhich, sal_uInt32 const nMaskSet )
94 : : SfxPoolItem( i_nWhich )
95 0 : , m_pImpl( new Impl(nMaskSet) )
96 : {
97 0 : }
98 :
99 : // ------------------------------------------------------------------------------
100 :
101 0 : MediaItem::MediaItem( const MediaItem& rItem )
102 : : SfxPoolItem( rItem )
103 0 : , m_pImpl( new Impl(*rItem.m_pImpl) )
104 : {
105 0 : }
106 :
107 : // ------------------------------------------------------------------------------
108 :
109 0 : MediaItem::~MediaItem()
110 : {
111 0 : }
112 :
113 : // ------------------------------------------------------------------------------
114 :
115 0 : int MediaItem::operator==( const SfxPoolItem& rItem ) const
116 : {
117 : assert( SfxPoolItem::operator==(rItem));
118 0 : MediaItem const& rOther(static_cast< const MediaItem& >(rItem));
119 0 : return m_pImpl->m_nMaskSet == rOther.m_pImpl->m_nMaskSet
120 0 : && m_pImpl->m_URL == rOther.m_pImpl->m_URL
121 0 : && m_pImpl->m_eState == rOther.m_pImpl->m_eState
122 0 : && m_pImpl->m_fDuration == rOther.m_pImpl->m_fDuration
123 0 : && m_pImpl->m_fTime == rOther.m_pImpl->m_fTime
124 0 : && m_pImpl->m_nVolumeDB == rOther.m_pImpl->m_nVolumeDB
125 0 : && m_pImpl->m_bLoop == rOther.m_pImpl->m_bLoop
126 0 : && m_pImpl->m_bMute == rOther.m_pImpl->m_bMute
127 0 : && m_pImpl->m_eZoom == rOther.m_pImpl->m_eZoom;
128 : }
129 :
130 : // ------------------------------------------------------------------------------
131 :
132 0 : SfxPoolItem* MediaItem::Clone( SfxItemPool* ) const
133 : {
134 0 : return new MediaItem( *this );
135 : }
136 :
137 : //------------------------------------------------------------------------
138 :
139 0 : SfxItemPresentation MediaItem::GetPresentation( SfxItemPresentation,
140 : SfxMapUnit,
141 : SfxMapUnit,
142 : XubString& rText,
143 : const IntlWrapper * ) const
144 : {
145 0 : rText.Erase();
146 0 : return SFX_ITEM_PRESENTATION_NONE;
147 : }
148 :
149 : //------------------------------------------------------------------------
150 :
151 0 : bool MediaItem::QueryValue( com::sun::star::uno::Any& rVal, sal_uInt8 ) const
152 : {
153 0 : uno::Sequence< uno::Any > aSeq( 9 );
154 :
155 0 : aSeq[ 0 ] <<= m_pImpl->m_URL;
156 0 : aSeq[ 1 ] <<= m_pImpl->m_nMaskSet;
157 0 : aSeq[ 2 ] <<= static_cast< sal_Int32 >( m_pImpl->m_eState );
158 0 : aSeq[ 3 ] <<= m_pImpl->m_fTime;
159 0 : aSeq[ 4 ] <<= m_pImpl->m_fDuration;
160 0 : aSeq[ 5 ] <<= m_pImpl->m_nVolumeDB;
161 0 : aSeq[ 6 ] <<= m_pImpl->m_bLoop;
162 0 : aSeq[ 7 ] <<= m_pImpl->m_bMute;
163 0 : aSeq[ 8 ] <<= m_pImpl->m_eZoom;
164 :
165 0 : rVal <<= aSeq;
166 :
167 0 : return true;
168 : }
169 :
170 : //------------------------------------------------------------------------
171 :
172 0 : bool MediaItem::PutValue( const com::sun::star::uno::Any& rVal, sal_uInt8 )
173 : {
174 0 : uno::Sequence< uno::Any > aSeq;
175 0 : bool bRet = false;
176 :
177 0 : if( ( rVal >>= aSeq ) && ( aSeq.getLength() == 9 ) )
178 : {
179 0 : sal_Int32 nInt32 = 0;
180 :
181 0 : aSeq[ 0 ] >>= m_pImpl->m_URL;
182 0 : aSeq[ 1 ] >>= m_pImpl->m_nMaskSet;
183 0 : aSeq[ 2 ] >>= nInt32;
184 0 : m_pImpl->m_eState = static_cast< MediaState >( nInt32 );
185 0 : aSeq[ 3 ] >>= m_pImpl->m_fTime;
186 0 : aSeq[ 4 ] >>= m_pImpl->m_fDuration;
187 0 : aSeq[ 5 ] >>= m_pImpl->m_nVolumeDB;
188 0 : aSeq[ 6 ] >>= m_pImpl->m_bLoop;
189 0 : aSeq[ 7 ] >>= m_pImpl->m_bMute;
190 0 : aSeq[ 8 ] >>= m_pImpl->m_eZoom;
191 :
192 0 : bRet = true;
193 : }
194 :
195 0 : return bRet;
196 : }
197 :
198 : //------------------------------------------------------------------------
199 :
200 0 : void MediaItem::merge( const MediaItem& rMediaItem )
201 : {
202 0 : const sal_uInt32 nMaskSet = rMediaItem.getMaskSet();
203 :
204 0 : if( AVMEDIA_SETMASK_URL & nMaskSet )
205 0 : setURL( rMediaItem.getURL(), &rMediaItem.getTempURL() );
206 :
207 0 : if( AVMEDIA_SETMASK_STATE & nMaskSet )
208 0 : setState( rMediaItem.getState() );
209 :
210 0 : if( AVMEDIA_SETMASK_DURATION & nMaskSet )
211 0 : setDuration( rMediaItem.getDuration() );
212 :
213 0 : if( AVMEDIA_SETMASK_TIME & nMaskSet )
214 0 : setTime( rMediaItem.getTime() );
215 :
216 0 : if( AVMEDIA_SETMASK_LOOP & nMaskSet )
217 0 : setLoop( rMediaItem.isLoop() );
218 :
219 0 : if( AVMEDIA_SETMASK_MUTE & nMaskSet )
220 0 : setMute( rMediaItem.isMute() );
221 :
222 0 : if( AVMEDIA_SETMASK_VOLUMEDB & nMaskSet )
223 0 : setVolumeDB( rMediaItem.getVolumeDB() );
224 :
225 0 : if( AVMEDIA_SETMASK_ZOOM & nMaskSet )
226 0 : setZoom( rMediaItem.getZoom() );
227 0 : }
228 :
229 : //------------------------------------------------------------------------
230 :
231 0 : sal_uInt32 MediaItem::getMaskSet() const
232 : {
233 0 : return m_pImpl->m_nMaskSet;
234 : }
235 :
236 : //------------------------------------------------------------------------
237 :
238 0 : void MediaItem::setURL( const OUString& rURL,
239 : OUString const*const pTempURL)
240 : {
241 0 : m_pImpl->m_URL = rURL;
242 0 : m_pImpl->m_nMaskSet |= AVMEDIA_SETMASK_URL;
243 0 : m_pImpl->m_TempFileURL = (pTempURL) ? *pTempURL : OUString();
244 0 : }
245 :
246 : //------------------------------------------------------------------------
247 :
248 0 : const OUString& MediaItem::getURL() const
249 : {
250 0 : return m_pImpl->m_URL;
251 : }
252 :
253 0 : const OUString& MediaItem::getTempURL() const
254 : {
255 0 : return m_pImpl->m_TempFileURL;
256 : }
257 :
258 : //------------------------------------------------------------------------
259 :
260 0 : void MediaItem::setState( MediaState eState )
261 : {
262 0 : m_pImpl->m_eState = eState;
263 0 : m_pImpl->m_nMaskSet |= AVMEDIA_SETMASK_STATE;
264 0 : }
265 :
266 : //------------------------------------------------------------------------
267 :
268 0 : MediaState MediaItem::getState() const
269 : {
270 0 : return m_pImpl->m_eState;
271 : }
272 :
273 : //------------------------------------------------------------------------
274 :
275 0 : void MediaItem::setDuration( double fDuration )
276 : {
277 0 : m_pImpl->m_fDuration = fDuration;
278 0 : m_pImpl->m_nMaskSet |= AVMEDIA_SETMASK_DURATION;
279 0 : }
280 :
281 : //------------------------------------------------------------------------
282 :
283 0 : double MediaItem::getDuration() const
284 : {
285 0 : return m_pImpl->m_fDuration;
286 : }
287 :
288 : //------------------------------------------------------------------------
289 :
290 0 : void MediaItem::setTime( double fTime )
291 : {
292 0 : m_pImpl->m_fTime = fTime;
293 0 : m_pImpl->m_nMaskSet |= AVMEDIA_SETMASK_TIME;
294 0 : }
295 :
296 : //------------------------------------------------------------------------
297 :
298 0 : double MediaItem::getTime() const
299 : {
300 0 : return m_pImpl->m_fTime;
301 : }
302 :
303 : //------------------------------------------------------------------------
304 :
305 0 : void MediaItem::setLoop( bool bLoop )
306 : {
307 0 : m_pImpl->m_bLoop = bLoop;
308 0 : m_pImpl->m_nMaskSet |= AVMEDIA_SETMASK_LOOP;
309 0 : }
310 :
311 : //------------------------------------------------------------------------
312 :
313 0 : bool MediaItem::isLoop() const
314 : {
315 0 : return m_pImpl->m_bLoop;
316 : }
317 :
318 : //------------------------------------------------------------------------
319 :
320 0 : void MediaItem::setMute( bool bMute )
321 : {
322 0 : m_pImpl->m_bMute = bMute;
323 0 : m_pImpl->m_nMaskSet |= AVMEDIA_SETMASK_MUTE;
324 0 : }
325 :
326 : //------------------------------------------------------------------------
327 :
328 0 : bool MediaItem::isMute() const
329 : {
330 0 : return m_pImpl->m_bMute;
331 : }
332 :
333 : //------------------------------------------------------------------------
334 :
335 0 : void MediaItem::setVolumeDB( sal_Int16 nDB )
336 : {
337 0 : m_pImpl->m_nVolumeDB = nDB;
338 0 : m_pImpl->m_nMaskSet |= AVMEDIA_SETMASK_VOLUMEDB;
339 0 : }
340 :
341 : //------------------------------------------------------------------------
342 :
343 0 : sal_Int16 MediaItem::getVolumeDB() const
344 : {
345 0 : return m_pImpl->m_nVolumeDB;
346 : }
347 :
348 : //------------------------------------------------------------------------
349 :
350 0 : void MediaItem::setZoom( ::com::sun::star::media::ZoomLevel eZoom )
351 : {
352 0 : m_pImpl->m_eZoom = eZoom;
353 0 : m_pImpl->m_nMaskSet |= AVMEDIA_SETMASK_ZOOM;
354 0 : }
355 :
356 : //------------------------------------------------------------------------
357 :
358 0 : ::com::sun::star::media::ZoomLevel MediaItem::getZoom() const
359 : {
360 0 : return m_pImpl->m_eZoom;
361 : }
362 :
363 : //------------------------------------------------------------------------
364 :
365 0 : static OUString lcl_GetFilename(OUString const& rSourceURL)
366 : {
367 : uno::Reference<uri::XUriReferenceFactory> const xUriFactory(
368 : uri::UriReferenceFactory::create(
369 0 : comphelper::getProcessComponentContext()));
370 : uno::Reference<uri::XUriReference> const xSourceURI(
371 0 : xUriFactory->parse(rSourceURL), uno::UNO_SET_THROW);
372 :
373 0 : OUString filename;
374 : {
375 0 : sal_Int32 const nSegments(xSourceURI->getPathSegmentCount());
376 0 : if (0 < nSegments)
377 : {
378 0 : filename = xSourceURI->getPathSegment(nSegments - 1);
379 : }
380 : }
381 0 : if (!::comphelper::OStorageHelper::IsValidZipEntryFileName(
382 0 : filename, false) || !filename.getLength())
383 : {
384 0 : filename = "media";
385 : }
386 0 : return filename;
387 : }
388 :
389 : static uno::Reference<io::XStream>
390 0 : lcl_CreateStream(uno::Reference<embed::XStorage> const& xStorage,
391 : OUString const& rFilename)
392 : {
393 0 : OUString filename(rFilename);
394 :
395 0 : if (xStorage->hasByName(filename))
396 : {
397 0 : OUString basename;
398 0 : OUString suffix;
399 0 : sal_Int32 const nIndex(rFilename.lastIndexOf(sal_Unicode('.')));
400 0 : if (0 < nIndex)
401 : {
402 0 : basename = rFilename.copy(0, nIndex);
403 0 : suffix = rFilename.copy(nIndex);
404 : }
405 0 : sal_Int32 count(0); // sigh... try to generate non-existent name
406 0 : do
407 : {
408 0 : ++count;
409 0 : filename = basename + OUString::valueOf(count) + suffix;
410 : }
411 0 : while (xStorage->hasByName(filename));
412 : }
413 :
414 : uno::Reference<io::XStream> const xStream(
415 0 : xStorage->openStreamElement(filename,
416 0 : embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE),
417 0 : uno::UNO_SET_THROW);
418 : uno::Reference< beans::XPropertySet > const xStreamProps(xStream,
419 0 : uno::UNO_QUERY);
420 0 : if (xStreamProps.is()) { // this is NOT supported in FileSystemStorage
421 0 : xStreamProps->setPropertyValue("MediaType", uno::makeAny(OUString(
422 : //FIXME how to detect real media type?
423 : //but currently xmloff has this one hardcoded anyway...
424 0 : "application/vnd.sun.star.media")));
425 0 : xStreamProps->setPropertyValue( // turn off compression
426 0 : "Compressed", uno::makeAny(sal_False));
427 : }
428 0 : return xStream;
429 : }
430 :
431 0 : bool EmbedMedia(uno::Reference<frame::XModel> const& xModel,
432 : OUString const& rSourceURL, OUString & o_rEmbeddedURL)
433 : {
434 : try
435 : {
436 : ::ucbhelper::Content sourceContent(rSourceURL,
437 : uno::Reference<ucb::XCommandEnvironment>(),
438 0 : comphelper::getProcessComponentContext());
439 :
440 : uno::Reference<document::XStorageBasedDocument> const xSBD(xModel,
441 0 : uno::UNO_QUERY_THROW);
442 : uno::Reference<embed::XStorage> const xStorage(
443 0 : xSBD->getDocumentStorage(), uno::UNO_QUERY_THROW);
444 :
445 0 : OUString const media("Media");
446 : uno::Reference<embed::XStorage> const xSubStorage(
447 0 : xStorage->openStorageElement(media, embed::ElementModes::WRITE));
448 :
449 0 : OUString filename(lcl_GetFilename(rSourceURL));
450 :
451 : uno::Reference<io::XStream> const xStream(
452 0 : lcl_CreateStream(xSubStorage, filename), uno::UNO_SET_THROW);
453 : uno::Reference<io::XOutputStream> const xOutStream(
454 0 : xStream->getOutputStream(), uno::UNO_SET_THROW);
455 :
456 0 : if (!sourceContent.openStream(xOutStream)) // copy file to storage
457 : {
458 : SAL_INFO("avmedia", "openStream to storage failed");
459 0 : return false;
460 : }
461 :
462 : uno::Reference<embed::XTransactedObject> const xSubTransaction(
463 0 : xSubStorage, uno::UNO_QUERY);
464 0 : if (xSubTransaction.is()) {
465 0 : xSubTransaction->commit();
466 : }
467 : uno::Reference<embed::XTransactedObject> const xTransaction(
468 0 : xStorage, uno::UNO_QUERY);
469 0 : if (xTransaction.is()) {
470 0 : xTransaction->commit();
471 : }
472 :
473 0 : OUStringBuffer buf("vnd.sun.star.Package:");
474 0 : buf.append(media);
475 0 : buf.append(sal_Unicode('/'));
476 0 : buf.append(filename);
477 0 : o_rEmbeddedURL = buf.makeStringAndClear();
478 0 : return true;
479 : }
480 0 : catch (uno::Exception const&)
481 : {
482 : SAL_WARN("avmedia",
483 : "Exception while trying to embed media");
484 : }
485 0 : return false;
486 : }
487 :
488 : }
489 :
490 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|