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