fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / sd / source / ui / remotecontrol / ImagePreparer.cxx
blob14d62d78e9769e80f2ccae9b4e118bcf5e5cd66e
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 "ImagePreparer.hxx"
22 #include <comphelper/processfactory.hxx>
23 #include <osl/file.hxx>
24 #include <rtl/ustrbuf.hxx>
25 #include <sax/tools/converter.hxx>
26 #include <rtl/strbuf.hxx>
27 #include <unotools/streamwrap.hxx>
29 #include <svl/itemset.hxx>
30 #include <sfx2/docfile.hxx>
32 #include <com/sun/star/beans/PropertyValue.hpp>
33 #include <com/sun/star/container/XNameAccess.hpp>
34 #include <com/sun/star/document/XFilter.hpp>
35 #include <com/sun/star/document/XImporter.hpp>
36 #include <com/sun/star/document/XExporter.hpp>
37 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
38 #include <com/sun/star/lang/XServiceName.hpp>
39 #include <com/sun/star/presentation/XPresentationPage.hpp>
40 #include <com/sun/star/text/XTextRange.hpp>
42 using namespace ::sd;
43 using namespace ::rtl;
44 using namespace ::osl;
45 using namespace ::com::sun::star;
46 using namespace ::com::sun::star::uno;
48 ImagePreparer::ImagePreparer(
49 const uno::Reference<presentation::XSlideShowController>& rxController,
50 Transmitter *aTransmitter )
51 : xController( rxController ),
52 pTransmitter( aTransmitter )
54 SetTimeout( 50 );
55 mnSendingSlide = 0;
56 Start();
59 ImagePreparer::~ImagePreparer()
61 Stop();
64 void ImagePreparer::Timeout()
66 sal_uInt32 aSlides = xController->getSlideCount();
67 // fprintf( stderr, "ImagePreparer: %d %d %d\n", xController->isRunning(),
68 // (int)mnSendingSlide, (int)aSlides);
69 if ( xController->isRunning() && // not stopped/disposed of.
70 mnSendingSlide < aSlides )
72 sendPreview( mnSendingSlide );
73 sendNotes( mnSendingSlide );
74 mnSendingSlide++;
75 Start();
77 else
78 Stop();
81 void ImagePreparer::sendPreview( sal_uInt32 aSlideNumber )
83 sal_uInt64 aSize;
84 uno::Sequence<sal_Int8> aImageData = preparePreview( aSlideNumber, 320, 240,
85 aSize );
86 if ( !xController->isRunning() )
87 return;
89 OUStringBuffer aStrBuffer;
90 ::sax::Converter::encodeBase64( aStrBuffer, aImageData );
92 OString aEncodedShortString = OUStringToOString(
93 aStrBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
95 // Start the writing
96 OStringBuffer aBuffer;
98 aBuffer.append( "slide_preview\n" );
100 aBuffer.append( OString::valueOf( sal_Int32( aSlideNumber ) ).getStr() );
101 aBuffer.append( "\n" );
103 aBuffer.append( aEncodedShortString.getStr() );
104 aBuffer.append( "\n\n" );
105 pTransmitter->addMessage( aBuffer.makeStringAndClear(),
106 Transmitter::PRIORITY_LOW );
110 uno::Sequence<sal_Int8> ImagePreparer::preparePreview(
111 sal_uInt32 aSlideNumber, sal_uInt32 aWidth, sal_uInt32 aHeight,
112 sal_uInt64 &rSize )
114 OUString aFileURL;
115 FileBase::createTempFile( 0, 0, &aFileURL );
117 uno::Reference< drawing::XGraphicExportFilter > xFilter =
118 drawing::GraphicExportFilter::create( ::comphelper::getProcessComponentContext() );
120 if ( !xController->isRunning() )
121 return uno::Sequence<sal_Int8>();
123 uno::Reference< lang::XComponent > xSourceDoc(
124 xController->getSlideByIndex( aSlideNumber ),
125 uno::UNO_QUERY_THROW );
127 xFilter->setSourceDocument( xSourceDoc );
129 uno::Sequence< beans::PropertyValue > aFilterData(3);
131 aFilterData[0].Name = "PixelWidth";
132 aFilterData[0].Value <<= aWidth;
134 aFilterData[1].Name = "PixelHeight";
135 aFilterData[1].Value <<= aHeight;
137 aFilterData[2].Name = "ColorMode";
138 aFilterData[2].Value <<= sal_Int32(0); // 0: Color, 1: B&W
140 uno::Sequence< beans::PropertyValue > aProps(3);
142 aProps[0].Name = "MediaType";
143 aProps[0].Value <<= OUString( "image/png" );
145 aProps[1].Name = "URL";
146 aProps[1].Value <<= aFileURL;
148 aProps[2].Name = "FilterData";
149 aProps[2].Value <<= aFilterData;
151 xFilter->filter( aProps );
153 // FIXME: error handling.
155 File aFile( aFileURL );
156 aFile.open(0);
157 sal_uInt64 aRead;
158 rSize = 0;
159 aFile.getSize( rSize );
160 uno::Sequence<sal_Int8> aContents( rSize );
162 aFile.read( aContents.getArray(), rSize, aRead );
163 aFile.close();
164 File::remove( aFileURL );
165 return aContents;
169 void ImagePreparer::sendNotes( sal_uInt32 aSlideNumber )
172 OString aNotes = prepareNotes( aSlideNumber );
174 if ( aNotes.isEmpty() )
175 return;
177 // OUStringBuffer aStrBuffer;
178 // ::sax::Converter::encodeBase64( aStrBuffer, aTemp );
180 // OString aNotes = OUStringToOString(
181 // aStrBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
183 if ( !xController->isRunning() )
184 return;
186 // Start the writing
187 OStringBuffer aBuffer;
189 aBuffer.append( "slide_notes\n" );
191 aBuffer.append( OString::valueOf( sal_Int32( aSlideNumber ) ).getStr() );
192 aBuffer.append( "\n" );
194 aBuffer.append( "<html><body>" );
195 aBuffer.append( aNotes );
196 aBuffer.append( "</html></body>" );
197 aBuffer.append( "\n\n" );
198 pTransmitter->addMessage( aBuffer.makeStringAndClear(),
199 Transmitter::PRIORITY_LOW );
202 sal_Bool ExportTo( uno::Reference< drawing::XDrawPage>& aNotesPage, String aUrl );
204 // Code copied from sdremote/source/presenter/PresenterNotesView.cxx
205 OString ImagePreparer::prepareNotes( sal_uInt32 aSlideNumber )
207 OUStringBuffer aRet;
209 if ( !xController->isRunning() )
210 return "";
212 uno::Reference<css::drawing::XDrawPage> aNotesPage;
213 uno::Reference< drawing::XDrawPage > xSourceDoc(
214 xController->getSlideByIndex( aSlideNumber ),
215 uno::UNO_QUERY_THROW );
216 uno::Reference<presentation::XPresentationPage> xPresentationPage(
217 xSourceDoc, UNO_QUERY);
218 if (xPresentationPage.is())
219 aNotesPage = xPresentationPage->getNotesPage();
220 else
221 return "";
224 static const OUString sNotesShapeName (
225 "com.sun.star.presentation.NotesShape" );
226 static const OUString sTextShapeName (
227 "com.sun.star.drawing.TextShape" );
229 uno::Reference<container::XIndexAccess> xIndexAccess ( aNotesPage, UNO_QUERY);
230 if (xIndexAccess.is())
233 // Iterate over all shapes and find the one that holds the text.
234 sal_Int32 nCount (xIndexAccess->getCount());
235 for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex)
238 uno::Reference<lang::XServiceName> xServiceName (
239 xIndexAccess->getByIndex(nIndex), UNO_QUERY);
240 if (xServiceName.is()
241 && xServiceName->getServiceName().equals(sNotesShapeName))
243 uno::Reference<text::XTextRange> xText (xServiceName, UNO_QUERY);
244 if (xText.is())
246 aRet.append(xText->getString());
247 aRet.append("<br/>");
250 else
252 uno::Reference<drawing::XShapeDescriptor> xShapeDescriptor (
253 xIndexAccess->getByIndex(nIndex), UNO_QUERY);
254 if (xShapeDescriptor.is())
256 OUString sType (xShapeDescriptor->getShapeType());
257 if (sType.equals(sNotesShapeName) || sType.equals(sTextShapeName))
259 uno::Reference<text::XTextRange> xText (
260 xIndexAccess->getByIndex(nIndex), UNO_QUERY);
261 if (xText.is())
263 aRet.append(xText->getString());
264 aRet.append("<br/>");
271 // Replace all newlines with <br\> tags
272 for ( sal_Int32 i = 0; i < aRet.getLength(); i++ )
274 if ( aRet[i] == '\n' )
276 aRet[i]= '<';
277 aRet.insert( i+1, "br/>" );
280 return OUStringToOString(
281 aRet.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
284 sal_Bool ExportTo( uno::Reference< drawing::XDrawPage>& aNotesPage, String aUrl )
286 OUString aFilterName( "XHTML Draw File" );
287 uno::Reference< document::XExporter > xExporter;
290 uno::Reference< lang::XMultiServiceFactory > xMan = ::comphelper::getProcessServiceFactory();
291 uno::Reference < lang::XMultiServiceFactory > xFilterFact (
292 xMan->createInstance( "com.sun.star.document.FilterFactory" ), uno::UNO_QUERY );
294 uno::Sequence < beans::PropertyValue > aProps;
295 uno::Reference < container::XNameAccess > xFilters ( xFilterFact, uno::UNO_QUERY );
296 if ( xFilters->hasByName( aFilterName ) )
297 xFilters->getByName( aFilterName ) >>= aProps;
298 else
299 fprintf( stderr, "Couldn't find by name.\n" );
301 OUString aFilterImplName;
302 sal_Int32 nFilterProps = aProps.getLength();
303 for ( sal_Int32 nFilterProp = 0; nFilterProp<nFilterProps; nFilterProp++ )
305 const beans::PropertyValue& rFilterProp = aProps[nFilterProp];
306 if ( rFilterProp.Name.compareToAscii("FilterService") == 0 )
308 rFilterProp.Value >>= aFilterImplName;
309 break;
313 fprintf( stderr, "aName%s\n", OUStringToOString(aFilterImplName, RTL_TEXTENCODING_UTF8).getStr() );
314 if ( !aFilterImplName.isEmpty() )
316 try{
317 xExporter = uno::Reference< document::XExporter >
318 ( xFilterFact->createInstanceWithArguments( aFilterName, uno::Sequence < uno::Any >() ), uno::UNO_QUERY );
319 }catch(const uno::Exception&)
321 xExporter.clear();
322 fprintf( stderr, "Couldn't create instance of filter.\n" );
327 if ( xExporter.is() )
329 try{
330 uno::Reference< lang::XComponent > xComp( aNotesPage, uno::UNO_QUERY_THROW );
331 uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY_THROW );
332 xExporter->setSourceDocument( xComp );
334 com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > aOldArgs ( 2 );
335 aOldArgs[0].Name = "FileName";
336 aOldArgs[0].Value <<= OUString( aUrl );
337 aOldArgs[1].Name = "FilterName";
338 aOldArgs[1].Value <<= OUString("com.sun.star.documentconversion.XSLTFilter");
340 SfxMedium rMedium( aUrl , STREAM_STD_WRITE );
342 const com::sun::star::beans::PropertyValue * pOldValue = aOldArgs.getConstArray();
343 com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > aArgs ( aOldArgs.getLength() );
344 com::sun::star::beans::PropertyValue * pNewValue = aArgs.getArray();
347 // put in the REAL file name, and copy all PropertyValues
348 const OUString sOutputStream ( "OutputStream" );
349 const OUString sStream ( "StreamForOutput" );
350 sal_Bool bHasOutputStream = sal_False;
351 sal_Bool bHasStream = sal_False;
352 sal_Bool bHasBaseURL = sal_False;
353 sal_Int32 i;
354 sal_Int32 nEnd = aOldArgs.getLength();
356 for ( i = 0; i < nEnd; i++ )
358 pNewValue[i] = pOldValue[i];
359 if ( pOldValue[i].Name == "FileName" )
360 pNewValue[i].Value <<= OUString ( rMedium.GetName() );
361 else if ( pOldValue[i].Name == sOutputStream )
362 bHasOutputStream = sal_True;
363 else if ( pOldValue[i].Name == sStream )
364 bHasStream = sal_True;
365 else if ( pOldValue[i].Name == "DocumentBaseURL" )
366 bHasBaseURL = sal_True;
369 if ( !bHasOutputStream )
371 aArgs.realloc ( ++nEnd );
372 aArgs[nEnd-1].Name = sOutputStream;
373 aArgs[nEnd-1].Value <<= uno::Reference < io::XOutputStream > ( new utl::OOutputStreamWrapper ( *rMedium.GetOutStream() ) );
376 // add stream as well, for OOX export and maybe others
377 if ( !bHasStream )
379 aArgs.realloc ( ++nEnd );
380 aArgs[nEnd-1].Name = sStream;
381 aArgs[nEnd-1].Value <<= com::sun::star::uno::Reference < com::sun::star::io::XStream > ( new utl::OStreamWrapper ( *rMedium.GetOutStream() ) );
384 if ( !bHasBaseURL )
386 aArgs.realloc ( ++nEnd );
387 aArgs[nEnd-1].Name = OUString( "DocumentBaseURL" );
388 aArgs[nEnd-1].Value <<= rMedium.GetBaseURL( sal_True );
391 return xFilter->filter( aArgs );
392 }catch(const uno::Exception&)
396 return sal_False;
399 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */