| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_filter.hxx" |
| #include <com/sun/star/frame/XDesktop.hpp> |
| #include <com/sun/star/frame/XStorable.hpp> |
| #include <com/sun/star/document/XFilter.hpp> |
| #include <com/sun/star/document/XExporter.hpp> |
| #include <com/sun/star/lang/XInitialization.hpp> |
| #include <com/sun/star/lang/XServiceInfo.hpp> |
| #include <com/sun/star/drawing/XDrawPagesSupplier.hpp> |
| #include <com/sun/star/drawing/XDrawView.hpp> |
| #include <com/sun/star/container/XIndexAccess.hpp> |
| #include <com/sun/star/frame/XModel.hpp> |
| #include <com/sun/star/task/XStatusIndicatorFactory.hpp> |
| #include <com/sun/star/io/XOutputStream.hpp> |
| #include <cppuhelper/implbase1.hxx> |
| #include <cppuhelper/implbase4.hxx> |
| #include <osl/file.hxx> |
| |
| #include "swfexporter.hxx" |
| |
| //#include <stdlib.h> |
| //#include <windows.h> |
| #include <string.h> |
| |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::frame; |
| using namespace ::com::sun::star::lang; |
| using namespace ::com::sun::star::drawing; |
| using namespace ::com::sun::star::presentation; |
| using namespace ::com::sun::star::task; |
| |
| using ::rtl::OUString; |
| using ::rtl::OString; |
| using ::com::sun::star::lang::XComponent; |
| using ::com::sun::star::beans::PropertyValue; |
| using ::com::sun::star::io::XOutputStream; |
| using ::com::sun::star::container::XIndexAccess; |
| using ::osl::FileBase; |
| using ::com::sun::star::frame::XModel; |
| |
| namespace swf { |
| |
| typedef ::cppu::WeakImplHelper1<com::sun::star::io::XOutputStream> OslOutputStreamWrapper_Base; |
| // needed for some compilers |
| class OslOutputStreamWrapper : public OslOutputStreamWrapper_Base |
| { |
| osl::File mrFile; |
| |
| public: |
| OslOutputStreamWrapper(const OUString& sFileName) : mrFile(sFileName) |
| { |
| osl_removeFile(sFileName.pData); |
| mrFile.open(OpenFlag_Create|OpenFlag_Write); |
| } |
| |
| // stario::XOutputStream |
| 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); |
| 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); |
| 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); |
| }; |
| |
| 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) |
| { |
| sal_uInt64 uBytesToWrite = aData.getLength(); |
| sal_uInt64 uBytesWritten = 0; |
| |
| sal_Int8 const * pBuffer = aData.getConstArray(); |
| |
| while( uBytesToWrite ) |
| { |
| osl::File::RC eRC = mrFile.write( pBuffer, uBytesToWrite, uBytesWritten); |
| |
| switch( eRC ) |
| { |
| case osl::File::E_INVAL: // the format of the parameters was not valid |
| case osl::File::E_FBIG: // File too large |
| |
| case osl::File::E_AGAIN: // Operation would block |
| case osl::File::E_BADF: // Bad file |
| case osl::File::E_FAULT: // Bad address |
| case osl::File::E_INTR: // function call was interrupted |
| case osl::File::E_IO: // I/O error |
| case osl::File::E_NOLCK: // No record locks available |
| case osl::File::E_NOLINK: // Link has been severed |
| case osl::File::E_NOSPC: // No space left on device |
| case osl::File::E_NXIO: // No such device or address |
| throw com::sun::star::io::IOException(); // TODO: Better error handling |
| default: break; |
| } |
| |
| uBytesToWrite -= uBytesWritten; |
| pBuffer += uBytesWritten; |
| } |
| } |
| |
| 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) |
| { |
| } |
| |
| 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) |
| { |
| osl::File::RC eRC = mrFile.close(); |
| |
| switch( eRC ) |
| { |
| case osl::File::E_INVAL: // the format of the parameters was not valid |
| |
| case osl::File::E_BADF: // Bad file |
| case osl::File::E_INTR: // function call was interrupted |
| case osl::File::E_NOLINK: // Link has been severed |
| case osl::File::E_NOSPC: // No space left on device |
| case osl::File::E_IO: // I/O error |
| throw com::sun::star::io::IOException(); // TODO: Better error handling |
| default: break; |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| class FlashExportFilter : public cppu::WeakImplHelper4 |
| < |
| com::sun::star::document::XFilter, |
| com::sun::star::document::XExporter, |
| com::sun::star::lang::XInitialization, |
| com::sun::star::lang::XServiceInfo |
| > |
| { |
| Reference< XComponent > mxDoc; |
| Reference< XMultiServiceFactory > mxMSF; |
| Reference< XStatusIndicator> mxStatusIndicator; |
| |
| osl::File* mpFile; |
| |
| public: |
| FlashExportFilter( const Reference< XMultiServiceFactory > &rxMSF); |
| |
| // XFilter |
| virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& aDescriptor ) throw(RuntimeException); |
| |
| sal_Bool ExportAsMultipleFiles( const Sequence< PropertyValue >& aDescriptor ); |
| sal_Bool ExportAsSingleFile( const Sequence< PropertyValue >& aDescriptor ); |
| |
| virtual void SAL_CALL cancel( ) throw (RuntimeException); |
| |
| // XExporter |
| virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc ) throw(IllegalArgumentException, RuntimeException); |
| |
| // XInitialization |
| virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException); |
| |
| // XServiceInfo |
| virtual OUString SAL_CALL getImplementationName() throw(RuntimeException); |
| virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException); |
| virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(RuntimeException); |
| }; |
| |
| // ----------------------------------------------------------------------------- |
| |
| FlashExportFilter::FlashExportFilter(const Reference< XMultiServiceFactory > &rxMSF) |
| : mxMSF( rxMSF ) |
| { |
| } |
| |
| |
| // ----------------------------------------------------------------------------- |
| |
| OUString exportBackground(FlashExporter &aFlashExporter, Reference< XDrawPage > xDrawPage, OUString sPath, sal_uInt32 nPage, const char* suffix) |
| { |
| OUString filename = STR("slide") + VAL(nPage+1) + STR(suffix) + STR(".swf"); |
| OUString fullpath = sPath + STR("/") + filename; |
| |
| // AS: If suffix is "o" then the last paramter is true (for exporting objects). |
| Reference<XOutputStream> xOutputStreamWrap(*(new OslOutputStreamWrapper(fullpath)), UNO_QUERY); |
| sal_uInt16 nCached = aFlashExporter.exportBackgrounds( xDrawPage, xOutputStreamWrap, sal::static_int_cast<sal_uInt16>( nPage ), *suffix == 'o' ); |
| aFlashExporter.Flush(); |
| xOutputStreamWrap.clear(); |
| |
| if (nCached != nPage) |
| { |
| osl_removeFile(fullpath.pData); |
| if ( 0xffff == nCached ) |
| return STR("NULL"); |
| else |
| return STR("slide") + VAL(nCached+1) + STR(suffix) + STR(".swf"); |
| } |
| |
| return filename; |
| } |
| |
| template <typename TYPE> |
| TYPE findPropertyValue(const Sequence< PropertyValue >& aPropertySequence, const sal_Char* name, TYPE def) |
| { |
| TYPE temp = TYPE(); |
| |
| sal_Int32 nLength = aPropertySequence.getLength(); |
| const PropertyValue * pValue = aPropertySequence.getConstArray(); |
| |
| for ( sal_Int32 i = 0 ; i < nLength; i++) |
| { |
| if ( pValue[i].Name.equalsAsciiL ( name, strlen(name) ) ) |
| { |
| pValue[i].Value >>= temp; |
| return temp; |
| } |
| } |
| |
| return def; |
| } |
| |
| sal_Bool SAL_CALL FlashExportFilter::filter( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) |
| throw (RuntimeException) |
| { |
| mxStatusIndicator = findPropertyValue<Reference<XStatusIndicator> >(aDescriptor, "StatusIndicator", mxStatusIndicator); |
| |
| Sequence< PropertyValue > aFilterData; |
| aFilterData = findPropertyValue<Sequence< PropertyValue > >(aDescriptor, "FilterData", aFilterData); |
| |
| if (findPropertyValue<sal_Bool>(aFilterData, "ExportMultipleFiles", false )) |
| { |
| ExportAsMultipleFiles(aDescriptor); |
| } |
| else |
| { |
| ExportAsSingleFile(aDescriptor); |
| } |
| |
| if( mxStatusIndicator.is() ) |
| mxStatusIndicator->end(); |
| |
| return sal_True; |
| } |
| |
| |
| // AS: When exporting as multiple files, each background, object layer, and slide gets its own |
| // file. Additionally, a file called BackgroundConfig.txt is generated, indicating which |
| // background and objects (if any) go with each slide. The files are named slideNb.swf, |
| // slideNo.swf, and slideNp.swf, where N is the slide number, and b=background, o=objects, and |
| // p=slide contents. Note that under normal circumstances, there will be very few b and o files. |
| |
| // AS: HACK! Right now, I create a directory as a sibling to the swf file selected in the Export |
| // dialog. This directory is called presentation.sxi-swf-files. The name of the swf file selected |
| // in the Export dialog has no impact on this. All files created are placed in this directory. |
| sal_Bool FlashExportFilter::ExportAsMultipleFiles(const Sequence< PropertyValue >& aDescriptor) |
| { |
| Reference< XDrawPagesSupplier > xDrawPagesSupplier(mxDoc, UNO_QUERY); |
| if(!xDrawPagesSupplier.is()) |
| return sal_False; |
| |
| Reference< XIndexAccess > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY ); |
| if(!xDrawPages.is()) |
| return sal_False; |
| |
| Reference< XDesktop > rDesktop( mxMSF->createInstance(OUString::createFromAscii("com.sun.star.frame.Desktop")), UNO_QUERY); |
| if (!rDesktop.is()) |
| return sal_False; |
| |
| Reference< XStorable > xStorable(rDesktop->getCurrentComponent(), UNO_QUERY); |
| if (!xStorable.is()) |
| return sal_False; |
| |
| Reference< XDrawPage > xDrawPage; |
| |
| Reference< XFrame > rFrame = rDesktop->getCurrentFrame(); |
| Reference< XDrawView > rDrawView = Reference< XDrawView >( rFrame->getController(), UNO_QUERY ); |
| |
| Reference< XDrawPage > rCurrentPage = rDrawView->getCurrentPage(); |
| |
| Sequence< PropertyValue > aFilterData; |
| |
| aFilterData = findPropertyValue<Sequence< PropertyValue > >(aDescriptor, "FilterData", aFilterData); |
| |
| //AS: Do a bunch of path mangling to figure out where to put the files. |
| |
| OUString sOriginalPath = findPropertyValue<OUString>(aDescriptor, "URL", OUString()); |
| |
| // AS: sPath is the parent directory, where everything else exists (like the sxi, |
| // the -swf-files folder, the -audio files, etc. |
| int lastslash = sOriginalPath.lastIndexOf('/'); |
| OUString sPath( sOriginalPath.copy(0, lastslash) ); |
| |
| OUString sPresentation(xStorable->getLocation()); |
| |
| lastslash = sPresentation.lastIndexOf('/') + 1; |
| int lastdot = sPresentation.lastIndexOf('.'); |
| |
| // AS: The name of the presentation, without 3 character extension. |
| OUString sPresentationName = sPresentation.copy(lastslash, lastdot - lastslash); |
| |
| OUString fullpath, swfdirpath, backgroundfilename, objectsfilename; |
| |
| swfdirpath = sPath + STR("/") + sPresentationName + STR(".sxi-swf-files"); |
| |
| oslFileError err; |
| err = osl_createDirectory( swfdirpath.pData ); |
| |
| fullpath = swfdirpath + STR("/backgroundconfig.txt"); |
| |
| oslFileHandle xBackgroundConfig( 0 ); |
| |
| // AS: Only export the background config if we're exporting all of the pages, otherwise we'll |
| // screw it up. |
| sal_Bool bExportAll = findPropertyValue<sal_Bool>(aFilterData, "ExportAll", true); |
| if (bExportAll) |
| { |
| osl_removeFile(fullpath.pData); |
| osl_openFile( fullpath.pData, &xBackgroundConfig, osl_File_OpenFlag_Create | osl_File_OpenFlag_Write ); |
| |
| sal_uInt64 bytesWritten; |
| err = osl_writeFile(xBackgroundConfig, "slides=", strlen("slides="), &bytesWritten); |
| } |
| |
| FlashExporter aFlashExporter( mxMSF, findPropertyValue<sal_Int32>(aFilterData, "CompressMode", 75), |
| findPropertyValue<sal_Bool>(aFilterData, "ExportOLEAsJPEG", false)); |
| |
| const sal_Int32 nPageCount = xDrawPages->getCount(); |
| if ( mxStatusIndicator.is() ) |
| mxStatusIndicator->start(OUString( RTL_CONSTASCII_USTRINGPARAM( "Saving :" )), nPageCount); |
| |
| for(sal_Int32 nPage = 0; nPage < nPageCount; nPage++) |
| { |
| if ( mxStatusIndicator.is() ) |
| mxStatusIndicator->setValue( nPage ); |
| xDrawPages->getByIndex(nPage) >>= xDrawPage; |
| |
| // AS: If we're only exporting the current page, then skip the rest. |
| if (!bExportAll && xDrawPage != rCurrentPage) |
| continue; |
| |
| // AS: Export the background, the background objects, and then the slide contents. |
| if (bExportAll || findPropertyValue<sal_Bool>(aFilterData, "ExportBackgrounds", true)) |
| { |
| backgroundfilename = exportBackground(aFlashExporter, xDrawPage, swfdirpath, nPage, "b"); |
| } |
| |
| if (bExportAll || findPropertyValue<sal_Bool>(aFilterData, "ExportBackgroundObjects", true)) |
| { |
| objectsfilename = exportBackground(aFlashExporter, xDrawPage, swfdirpath, nPage, "o"); |
| } |
| |
| if (bExportAll || findPropertyValue<sal_Bool>(aFilterData, "ExportSlideContents", true)) |
| { |
| fullpath = swfdirpath + STR("/slide") + VAL(nPage+1) + STR("p.swf"); |
| |
| Reference<XOutputStream> xOutputStreamWrap(*(new OslOutputStreamWrapper(fullpath)), UNO_QUERY); |
| sal_Bool ret = aFlashExporter.exportSlides( xDrawPage, xOutputStreamWrap, sal::static_int_cast<sal_uInt16>( nPage ) ); |
| aFlashExporter.Flush(); |
| xOutputStreamWrap.clear(); |
| |
| if (!ret) |
| osl_removeFile(fullpath.pData); |
| } |
| |
| // AS: Write out to the background config what backgrounds and objects this |
| // slide used. |
| if (bExportAll) |
| { |
| OUString temp = backgroundfilename + STR("|") + objectsfilename; |
| OString ASCIItemp(temp.getStr(), temp.getLength(), RTL_TEXTENCODING_ASCII_US); |
| |
| sal_uInt64 bytesWritten; |
| osl_writeFile(xBackgroundConfig, ASCIItemp.getStr(), ASCIItemp.getLength(), &bytesWritten); |
| |
| if (nPage < nPageCount - 1) |
| osl_writeFile(xBackgroundConfig, "|", 1, &bytesWritten); |
| } |
| |
| #ifdef AUGUSTUS |
| if (findPropertyValue<sal_Bool>(aFilterData, "ExportSound", true)) |
| { |
| fullpath = swfdirpath + STR("/slide") + VAL(nPage+1) + STR("s.swf"); |
| |
| OUString wavpath = sPath + STR("/") + sPresentationName + STR(".ppt-audio/slide") + VAL(nPage+1) + STR(".wav"); |
| FileBase::getSystemPathFromFileURL(wavpath, wavpath); |
| OString sASCIIPath(wavpath.getStr(), wavpath.getLength(), RTL_TEXTENCODING_ASCII_US); |
| |
| Reference<XOutputStream> xOutputStreamWrap(*(new OslOutputStreamWrapper(fullpath)), UNO_QUERY); |
| sal_Bool ret = aFlashExporter.exportSound(xOutputStreamWrap, sASCIIPath.getStr()); |
| aFlashExporter.Flush(); |
| xOutputStreamWrap.clear(); |
| |
| if (!ret) |
| osl_removeFile(fullpath.pData); |
| } |
| #endif // defined AUGUSTUS |
| } |
| |
| if (bExportAll) |
| osl_closeFile(xBackgroundConfig); |
| |
| return sal_True; |
| } |
| |
| sal_Bool FlashExportFilter::ExportAsSingleFile(const Sequence< PropertyValue >& aDescriptor) |
| { |
| Reference < XOutputStream > xOutputStream = findPropertyValue<Reference<XOutputStream> >(aDescriptor, "OutputStream", 0); |
| Sequence< PropertyValue > aFilterData; |
| |
| if (!xOutputStream.is() ) |
| { |
| OSL_ASSERT ( 0 ); |
| return sal_False; |
| } |
| |
| FlashExporter aFlashExporter( mxMSF, findPropertyValue<sal_Int32>(aFilterData, "CompressMode", 75), |
| findPropertyValue<sal_Bool>(aFilterData, "ExportOLEAsJPEG", false)); |
| |
| return aFlashExporter.exportAll( mxDoc, xOutputStream, mxStatusIndicator ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void SAL_CALL FlashExportFilter::cancel( ) |
| throw (RuntimeException) |
| { |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| // XExporter |
| void SAL_CALL FlashExportFilter::setSourceDocument( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xDoc ) |
| throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException) |
| { |
| mxDoc = xDoc; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| // XInitialization |
| void SAL_CALL FlashExportFilter::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& /* aArguments */ ) |
| throw (Exception, RuntimeException) |
| { |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| OUString FlashExportFilter_getImplementationName () |
| throw (RuntimeException) |
| { |
| return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Impress.FlashExportFilter" ) ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| #define SERVICE_NAME "com.sun.star.document.ExportFilter" |
| |
| sal_Bool SAL_CALL FlashExportFilter_supportsService( const OUString& ServiceName ) |
| throw (RuntimeException) |
| { |
| return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| Sequence< OUString > SAL_CALL FlashExportFilter_getSupportedServiceNames( ) |
| throw (RuntimeException) |
| { |
| Sequence < OUString > aRet(1); |
| OUString* pArray = aRet.getArray(); |
| pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) ); |
| return aRet; |
| } |
| #undef SERVICE_NAME |
| |
| // ----------------------------------------------------------------------------- |
| |
| Reference< XInterface > SAL_CALL FlashExportFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr) |
| throw( Exception ) |
| { |
| return (cppu::OWeakObject*) new FlashExportFilter( rSMgr ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| // XServiceInfo |
| OUString SAL_CALL FlashExportFilter::getImplementationName( ) |
| throw (RuntimeException) |
| { |
| return FlashExportFilter_getImplementationName(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| sal_Bool SAL_CALL FlashExportFilter::supportsService( const OUString& rServiceName ) |
| throw (RuntimeException) |
| { |
| return FlashExportFilter_supportsService( rServiceName ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| ::com::sun::star::uno::Sequence< OUString > SAL_CALL FlashExportFilter::getSupportedServiceNames( ) |
| throw (RuntimeException) |
| { |
| return FlashExportFilter_getSupportedServiceNames(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| } |