Update ooo320-m1
[ooovba.git] / filter / source / flash / swffilter.cxx
blob31e6ccf4704116acd3fd6ad3b653bea5c6d68e98
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: swffilter.cxx,v $
10 * $Revision: 1.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_filter.hxx"
33 #include <com/sun/star/frame/XDesktop.hpp>
34 #include <com/sun/star/frame/XStorable.hpp>
35 #include <com/sun/star/document/XFilter.hpp>
36 #include <com/sun/star/document/XExporter.hpp>
37 #include <com/sun/star/lang/XInitialization.hpp>
38 #include <com/sun/star/lang/XServiceInfo.hpp>
39 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
40 #include <com/sun/star/drawing/XDrawView.hpp>
41 #include <com/sun/star/container/XIndexAccess.hpp>
42 #include <com/sun/star/frame/XModel.hpp>
43 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
44 #include <com/sun/star/io/XOutputStream.hpp>
45 #include <cppuhelper/implbase1.hxx>
46 #include <cppuhelper/implbase4.hxx>
47 #include <osl/file.hxx>
49 #include "swfexporter.hxx"
51 //#include <stdlib.h>
52 //#include <windows.h>
53 #include <string.h>
55 using namespace ::com::sun::star::uno;
56 using namespace ::com::sun::star::frame;
57 using namespace ::com::sun::star::lang;
58 using namespace ::com::sun::star::drawing;
59 using namespace ::com::sun::star::presentation;
60 using namespace ::com::sun::star::task;
62 using ::rtl::OUString;
63 using ::rtl::OString;
64 using ::com::sun::star::lang::XComponent;
65 using ::com::sun::star::beans::PropertyValue;
66 using ::com::sun::star::io::XOutputStream;
67 using ::com::sun::star::container::XIndexAccess;
68 using ::osl::FileBase;
69 using ::com::sun::star::frame::XModel;
71 namespace swf {
73 typedef ::cppu::WeakImplHelper1<com::sun::star::io::XOutputStream> OslOutputStreamWrapper_Base;
74 // needed for some compilers
75 class OslOutputStreamWrapper : public OslOutputStreamWrapper_Base
77 osl::File mrFile;
79 public:
80 OslOutputStreamWrapper(const OUString& sFileName) : mrFile(sFileName)
82 osl_removeFile(sFileName.pData);
83 mrFile.open(OpenFlag_Create|OpenFlag_Write);
86 // stario::XOutputStream
87 virtual void SAL_CALL writeBytes( const ::com::sun::star::uno::Sequence< sal_Int8 >& aData ) throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
88 virtual void SAL_CALL flush( ) throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
89 virtual void SAL_CALL closeOutput( ) throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
92 void SAL_CALL OslOutputStreamWrapper::writeBytes( const ::com::sun::star::uno::Sequence< sal_Int8 >& aData ) throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
94 sal_uInt64 uBytesToWrite = aData.getLength();
95 sal_uInt64 uBytesWritten = 0;
97 sal_Int8 const * pBuffer = aData.getConstArray();
99 while( uBytesToWrite )
101 osl::File::RC eRC = mrFile.write( pBuffer, uBytesToWrite, uBytesWritten);
103 switch( eRC )
105 case osl::File::E_INVAL: // the format of the parameters was not valid
106 case osl::File::E_FBIG: // File too large
108 case osl::File::E_AGAIN: // Operation would block
109 case osl::File::E_BADF: // Bad file
110 case osl::File::E_FAULT: // Bad address
111 case osl::File::E_INTR: // function call was interrupted
112 case osl::File::E_IO: // I/O error
113 case osl::File::E_NOLCK: // No record locks available
114 case osl::File::E_NOLINK: // Link has been severed
115 case osl::File::E_NOSPC: // No space left on device
116 case osl::File::E_NXIO: // No such device or address
117 throw com::sun::star::io::IOException(); // TODO: Better error handling
118 default: break;
121 uBytesToWrite -= uBytesWritten;
122 pBuffer += uBytesWritten;
126 void SAL_CALL OslOutputStreamWrapper::flush( ) throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
130 void SAL_CALL OslOutputStreamWrapper::closeOutput( ) throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
132 osl::File::RC eRC = mrFile.close();
134 switch( eRC )
136 case osl::File::E_INVAL: // the format of the parameters was not valid
138 case osl::File::E_BADF: // Bad file
139 case osl::File::E_INTR: // function call was interrupted
140 case osl::File::E_NOLINK: // Link has been severed
141 case osl::File::E_NOSPC: // No space left on device
142 case osl::File::E_IO: // I/O error
143 throw com::sun::star::io::IOException(); // TODO: Better error handling
144 default: break;
148 // -----------------------------------------------------------------------------
150 class FlashExportFilter : public cppu::WeakImplHelper4
152 com::sun::star::document::XFilter,
153 com::sun::star::document::XExporter,
154 com::sun::star::lang::XInitialization,
155 com::sun::star::lang::XServiceInfo
158 Reference< XComponent > mxDoc;
159 Reference< XMultiServiceFactory > mxMSF;
160 Reference< XStatusIndicator> mxStatusIndicator;
162 osl::File* mpFile;
164 public:
165 FlashExportFilter( const Reference< XMultiServiceFactory > &rxMSF);
167 // XFilter
168 virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& aDescriptor ) throw(RuntimeException);
170 sal_Bool ExportAsMultipleFiles( const Sequence< PropertyValue >& aDescriptor );
171 sal_Bool ExportAsSingleFile( const Sequence< PropertyValue >& aDescriptor );
173 virtual void SAL_CALL cancel( ) throw (RuntimeException);
175 // XExporter
176 virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc ) throw(IllegalArgumentException, RuntimeException);
178 // XInitialization
179 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException);
181 // XServiceInfo
182 virtual OUString SAL_CALL getImplementationName() throw(RuntimeException);
183 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException);
184 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(RuntimeException);
187 // -----------------------------------------------------------------------------
189 FlashExportFilter::FlashExportFilter(const Reference< XMultiServiceFactory > &rxMSF)
190 : mxMSF( rxMSF )
195 // -----------------------------------------------------------------------------
197 OUString exportBackground(FlashExporter &aFlashExporter, Reference< XDrawPage > xDrawPage, OUString sPath, sal_uInt32 nPage, const char* suffix)
199 OUString filename = STR("slide") + VAL(nPage+1) + STR(suffix) + STR(".swf");
200 OUString fullpath = sPath + STR("/") + filename;
202 // AS: If suffix is "o" then the last paramter is true (for exporting objects).
203 Reference<XOutputStream> xOutputStreamWrap(*(new OslOutputStreamWrapper(fullpath)), UNO_QUERY);
204 sal_uInt16 nCached = aFlashExporter.exportBackgrounds( xDrawPage, xOutputStreamWrap, sal::static_int_cast<sal_uInt16>( nPage ), *suffix == 'o' );
205 aFlashExporter.Flush();
206 xOutputStreamWrap.clear();
208 if (nCached != nPage)
210 osl_removeFile(fullpath.pData);
211 if ( 0xffff == nCached )
212 return STR("NULL");
213 else
214 return STR("slide") + VAL(nCached+1) + STR(suffix) + STR(".swf");
217 return filename;
220 template <typename TYPE>
221 TYPE findPropertyValue(const Sequence< PropertyValue >& aPropertySequence, const sal_Char* name, TYPE def)
223 TYPE temp = TYPE();
225 sal_Int32 nLength = aPropertySequence.getLength();
226 const PropertyValue * pValue = aPropertySequence.getConstArray();
228 for ( sal_Int32 i = 0 ; i < nLength; i++)
230 if ( pValue[i].Name.equalsAsciiL ( name, strlen(name) ) )
232 pValue[i].Value >>= temp;
233 return temp;
237 return def;
240 sal_Bool SAL_CALL FlashExportFilter::filter( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
241 throw (RuntimeException)
243 mxStatusIndicator = findPropertyValue<Reference<XStatusIndicator> >(aDescriptor, "StatusIndicator", mxStatusIndicator);
245 Sequence< PropertyValue > aFilterData;
246 aFilterData = findPropertyValue<Sequence< PropertyValue > >(aDescriptor, "FilterData", aFilterData);
248 if (findPropertyValue<sal_Bool>(aFilterData, "ExportMultipleFiles", false ))
250 ExportAsMultipleFiles(aDescriptor);
252 else
254 ExportAsSingleFile(aDescriptor);
257 if( mxStatusIndicator.is() )
258 mxStatusIndicator->end();
260 return sal_True;
264 // AS: When exporting as multiple files, each background, object layer, and slide gets its own
265 // file. Additionally, a file called BackgroundConfig.txt is generated, indicating which
266 // background and objects (if any) go with each slide. The files are named slideNb.swf,
267 // slideNo.swf, and slideNp.swf, where N is the slide number, and b=background, o=objects, and
268 // p=slide contents. Note that under normal circumstances, there will be very few b and o files.
270 // AS: HACK! Right now, I create a directory as a sibling to the swf file selected in the Export
271 // dialog. This directory is called presentation.sxi-swf-files. The name of the swf file selected
272 // in the Export dialog has no impact on this. All files created are placed in this directory.
273 sal_Bool FlashExportFilter::ExportAsMultipleFiles(const Sequence< PropertyValue >& aDescriptor)
275 Reference< XDrawPagesSupplier > xDrawPagesSupplier(mxDoc, UNO_QUERY);
276 if(!xDrawPagesSupplier.is())
277 return sal_False;
279 Reference< XIndexAccess > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY );
280 if(!xDrawPages.is())
281 return sal_False;
283 Reference< XDesktop > rDesktop( mxMSF->createInstance(OUString::createFromAscii("com.sun.star.frame.Desktop")), UNO_QUERY);
284 if (!rDesktop.is())
285 return sal_False;
287 Reference< XStorable > xStorable(rDesktop->getCurrentComponent(), UNO_QUERY);
288 if (!xStorable.is())
289 return sal_False;
291 Reference< XDrawPage > xDrawPage;
293 Reference< XFrame > rFrame = rDesktop->getCurrentFrame();
294 Reference< XDrawView > rDrawView = Reference< XDrawView >( rFrame->getController(), UNO_QUERY );
296 Reference< XDrawPage > rCurrentPage = rDrawView->getCurrentPage();
298 Sequence< PropertyValue > aFilterData;
300 aFilterData = findPropertyValue<Sequence< PropertyValue > >(aDescriptor, "FilterData", aFilterData);
302 //AS: Do a bunch of path mangling to figure out where to put the files.
304 OUString sOriginalPath = findPropertyValue<OUString>(aDescriptor, "URL", OUString());
306 // AS: sPath is the parent directory, where everything else exists (like the sxi,
307 // the -swf-files folder, the -audio files, etc.
308 int lastslash = sOriginalPath.lastIndexOf('/');
309 OUString sPath( sOriginalPath.copy(0, lastslash) );
311 OUString sPresentation(xStorable->getLocation());
313 lastslash = sPresentation.lastIndexOf('/') + 1;
314 int lastdot = sPresentation.lastIndexOf('.');
316 // AS: The name of the presentation, without 3 character extension.
317 OUString sPresentationName = sPresentation.copy(lastslash, lastdot - lastslash);
319 OUString fullpath, swfdirpath, backgroundfilename, objectsfilename;
321 swfdirpath = sPath + STR("/") + sPresentationName + STR(".sxi-swf-files");
323 oslFileError err;
324 err = osl_createDirectory( swfdirpath.pData );
326 fullpath = swfdirpath + STR("/backgroundconfig.txt");
328 oslFileHandle xBackgroundConfig( 0 );
330 // AS: Only export the background config if we're exporting all of the pages, otherwise we'll
331 // screw it up.
332 sal_Bool bExportAll = findPropertyValue<sal_Bool>(aFilterData, "ExportAll", true);
333 if (bExportAll)
335 osl_removeFile(fullpath.pData);
336 osl_openFile( fullpath.pData, &xBackgroundConfig, osl_File_OpenFlag_Create | osl_File_OpenFlag_Write );
338 sal_uInt64 bytesWritten;
339 err = osl_writeFile(xBackgroundConfig, "slides=", strlen("slides="), &bytesWritten);
342 FlashExporter aFlashExporter( mxMSF, findPropertyValue<sal_Int32>(aFilterData, "CompressMode", 75),
343 findPropertyValue<sal_Bool>(aFilterData, "ExportOLEAsJPEG", false));
345 const sal_Int32 nPageCount = xDrawPages->getCount();
346 if ( mxStatusIndicator.is() )
347 mxStatusIndicator->start(OUString( RTL_CONSTASCII_USTRINGPARAM( "Saving :" )), nPageCount);
349 for(sal_Int32 nPage = 0; nPage < nPageCount; nPage++)
351 if ( mxStatusIndicator.is() )
352 mxStatusIndicator->setValue( nPage );
353 xDrawPages->getByIndex(nPage) >>= xDrawPage;
355 // AS: If we're only exporting the current page, then skip the rest.
356 if (!bExportAll && xDrawPage != rCurrentPage)
357 continue;
359 // AS: Export the background, the background objects, and then the slide contents.
360 if (bExportAll || findPropertyValue<sal_Bool>(aFilterData, "ExportBackgrounds", true))
362 backgroundfilename = exportBackground(aFlashExporter, xDrawPage, swfdirpath, nPage, "b");
365 if (bExportAll || findPropertyValue<sal_Bool>(aFilterData, "ExportBackgroundObjects", true))
367 objectsfilename = exportBackground(aFlashExporter, xDrawPage, swfdirpath, nPage, "o");
370 if (bExportAll || findPropertyValue<sal_Bool>(aFilterData, "ExportSlideContents", true))
372 fullpath = swfdirpath + STR("/slide") + VAL(nPage+1) + STR("p.swf");
374 Reference<XOutputStream> xOutputStreamWrap(*(new OslOutputStreamWrapper(fullpath)), UNO_QUERY);
375 sal_Bool ret = aFlashExporter.exportSlides( xDrawPage, xOutputStreamWrap, sal::static_int_cast<sal_uInt16>( nPage ) );
376 aFlashExporter.Flush();
377 xOutputStreamWrap.clear();
379 if (!ret)
380 osl_removeFile(fullpath.pData);
383 // AS: Write out to the background config what backgrounds and objects this
384 // slide used.
385 if (bExportAll)
387 OUString temp = backgroundfilename + STR("|") + objectsfilename;
388 OString ASCIItemp(temp.getStr(), temp.getLength(), RTL_TEXTENCODING_ASCII_US);
390 sal_uInt64 bytesWritten;
391 osl_writeFile(xBackgroundConfig, ASCIItemp.getStr(), ASCIItemp.getLength(), &bytesWritten);
393 if (nPage < nPageCount - 1)
394 osl_writeFile(xBackgroundConfig, "|", 1, &bytesWritten);
397 #ifdef AUGUSTUS
398 if (findPropertyValue<sal_Bool>(aFilterData, "ExportSound", true))
400 fullpath = swfdirpath + STR("/slide") + VAL(nPage+1) + STR("s.swf");
402 OUString wavpath = sPath + STR("/") + sPresentationName + STR(".ppt-audio/slide") + VAL(nPage+1) + STR(".wav");
403 FileBase::getSystemPathFromFileURL(wavpath, wavpath);
404 OString sASCIIPath(wavpath.getStr(), wavpath.getLength(), RTL_TEXTENCODING_ASCII_US);
406 Reference<XOutputStream> xOutputStreamWrap(*(new OslOutputStreamWrapper(fullpath)), UNO_QUERY);
407 sal_Bool ret = aFlashExporter.exportSound(xOutputStreamWrap, sASCIIPath.getStr());
408 aFlashExporter.Flush();
409 xOutputStreamWrap.clear();
411 if (!ret)
412 osl_removeFile(fullpath.pData);
414 #endif // defined AUGUSTUS
417 if (bExportAll)
418 osl_closeFile(xBackgroundConfig);
420 return sal_True;
423 sal_Bool FlashExportFilter::ExportAsSingleFile(const Sequence< PropertyValue >& aDescriptor)
425 Reference < XOutputStream > xOutputStream = findPropertyValue<Reference<XOutputStream> >(aDescriptor, "OutputStream", 0);
426 Sequence< PropertyValue > aFilterData;
428 if (!xOutputStream.is() )
430 OSL_ASSERT ( 0 );
431 return sal_False;
434 FlashExporter aFlashExporter( mxMSF, findPropertyValue<sal_Int32>(aFilterData, "CompressMode", 75),
435 findPropertyValue<sal_Bool>(aFilterData, "ExportOLEAsJPEG", false));
437 return aFlashExporter.exportAll( mxDoc, xOutputStream, mxStatusIndicator );
440 // -----------------------------------------------------------------------------
442 void SAL_CALL FlashExportFilter::cancel( )
443 throw (RuntimeException)
447 // -----------------------------------------------------------------------------
449 // XExporter
450 void SAL_CALL FlashExportFilter::setSourceDocument( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xDoc )
451 throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException)
453 mxDoc = xDoc;
456 // -----------------------------------------------------------------------------
458 // XInitialization
459 void SAL_CALL FlashExportFilter::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& /* aArguments */ )
460 throw (Exception, RuntimeException)
464 // -----------------------------------------------------------------------------
466 OUString FlashExportFilter_getImplementationName ()
467 throw (RuntimeException)
469 return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Impress.FlashExportFilter" ) );
472 // -----------------------------------------------------------------------------
474 #define SERVICE_NAME "com.sun.star.document.ExportFilter"
476 sal_Bool SAL_CALL FlashExportFilter_supportsService( const OUString& ServiceName )
477 throw (RuntimeException)
479 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
482 // -----------------------------------------------------------------------------
484 Sequence< OUString > SAL_CALL FlashExportFilter_getSupportedServiceNames( )
485 throw (RuntimeException)
487 Sequence < OUString > aRet(1);
488 OUString* pArray = aRet.getArray();
489 pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
490 return aRet;
492 #undef SERVICE_NAME
494 // -----------------------------------------------------------------------------
496 Reference< XInterface > SAL_CALL FlashExportFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr)
497 throw( Exception )
499 return (cppu::OWeakObject*) new FlashExportFilter( rSMgr );
502 // -----------------------------------------------------------------------------
504 // XServiceInfo
505 OUString SAL_CALL FlashExportFilter::getImplementationName( )
506 throw (RuntimeException)
508 return FlashExportFilter_getImplementationName();
511 // -----------------------------------------------------------------------------
513 sal_Bool SAL_CALL FlashExportFilter::supportsService( const OUString& rServiceName )
514 throw (RuntimeException)
516 return FlashExportFilter_supportsService( rServiceName );
519 // -----------------------------------------------------------------------------
521 ::com::sun::star::uno::Sequence< OUString > SAL_CALL FlashExportFilter::getSupportedServiceNames( )
522 throw (RuntimeException)
524 return FlashExportFilter_getSupportedServiceNames();
527 // -----------------------------------------------------------------------------