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 "swfwriter.hxx"
30 : : #include <vcl/virdev.hxx>
31 : : #include <vcl/gdimtf.hxx>
32 : : #include <basegfx/matrix/b2dhommatrixtools.hxx>
33 : :
34 : : using namespace ::swf;
35 : : using namespace ::std;
36 : : using namespace ::com::sun::star::uno;
37 : : using namespace ::com::sun::star::io;
38 : :
39 : : // -----------------------------------------------------------------------------
40 : :
41 : 0 : static MapMode aTWIPSMode( MAP_TWIP );
42 : 0 : static MapMode a100thmmMode( MAP_100TH_MM );
43 : :
44 : 0 : static sal_Int32 map100thmm( sal_Int32 n100thMM )
45 : : {
46 : 0 : Point aPoint( n100thMM, n100thMM );
47 : 0 : sal_Int32 nX = OutputDevice::LogicToLogic( aPoint, a100thmmMode, aTWIPSMode ).X();
48 : 0 : return nX;
49 : : }
50 : :
51 : : // -----------------------------------------------------------------------------
52 : :
53 : 0 : Writer::Writer( sal_Int32 nTWIPWidthOutput, sal_Int32 nTWIPHeightOutput, sal_Int32 nDocWidthInput, sal_Int32 nDocHeightInput, sal_Int32 nJPEGcompressMode )
54 : : : mpClipPolyPolygon( NULL ),
55 : : mpTag( NULL ),
56 : : mpSprite( NULL ),
57 : : mnNextId( 1 ),
58 : : mnGlobalTransparency(0),
59 : 0 : mnJPEGCompressMode(nJPEGcompressMode)
60 : : {
61 : 0 : mpVDev = new VirtualDevice;
62 : 0 : mpVDev->EnableOutput( sal_False );
63 : :
64 : 0 : maMovieTempFile.EnableKillingFile();
65 : 0 : maFontsTempFile.EnableKillingFile();
66 : :
67 : 0 : mpMovieStream = maMovieTempFile.GetStream( STREAM_WRITE|STREAM_TRUNC );
68 : 0 : mpFontsStream = maFontsTempFile.GetStream( STREAM_WRITE|STREAM_TRUNC );
69 : :
70 : 0 : mnFrames = 0;
71 : :
72 : 0 : mnDocWidth = map100thmm( nDocWidthInput );
73 : 0 : mnDocHeight = map100thmm( nDocHeightInput );
74 : :
75 : 0 : mnDocXScale = (double)nTWIPWidthOutput / mnDocWidth;
76 : 0 : mnDocYScale = (double)nTWIPHeightOutput / mnDocHeight;
77 : :
78 : : #ifndef AUGUSTUS
79 : : // define an invisible button with the size of a page
80 : 0 : Rectangle aRect( 0, 0, (long)( mnDocWidth * mnDocXScale ), (long)( mnDocHeight * mnDocYScale ) );
81 : 0 : Polygon aPoly( aRect );
82 : 0 : FillStyle aFill = FillStyle( Color(COL_WHITE) );
83 : 0 : mnWhiteBackgroundShapeId = defineShape( aPoly, aFill );
84 : :
85 : 0 : ::basegfx::B2DHomMatrix m; // #i73264#
86 : 0 : mnPageButtonId = createID();
87 : 0 : startTag( TAG_DEFINEBUTTON );
88 : 0 : mpTag->addUI16( mnPageButtonId ); // character id for button
89 : :
90 : : // button records
91 : 0 : mpTag->addUI8( 0x08 ); // only hit state
92 : 0 : mpTag->addUI16( mnWhiteBackgroundShapeId ); // shape id of background rectangle
93 : 0 : mpTag->addUI16( 0 ); // depth for button DANGER!
94 : 0 : mpTag->addMatrix( m ); // identity matrix
95 : 0 : mpTag->addUI8( 0 ); // empty color transform
96 : :
97 : : // mpTag->addUI8( 0 ); // end of button records
98 : :
99 : : // action records
100 : 0 : mpTag->addUI8( 0x06 ); // ActionPlay
101 : 0 : mpTag->addUI8( 0 ); // end of action records
102 : :
103 : 0 : endTag();
104 : :
105 : : // place a shape that clips shapes depth 2-3 to document boundaries
106 : : // placeShape( mnWhiteBackgroundShapeId, 1, 0, 0, 4 );
107 : : #endif
108 : 0 : }
109 : :
110 : : // -----------------------------------------------------------------------------
111 : :
112 : 0 : Writer::~Writer()
113 : : {
114 : 0 : delete mpVDev;
115 : 0 : delete mpSprite;
116 : 0 : delete mpTag;
117 : 0 : }
118 : :
119 : : // -----------------------------------------------------------------------------
120 : :
121 : 0 : void ImplCopySvStreamToXOutputStream( SvStream& rIn, Reference< XOutputStream > &xOut )
122 : : {
123 : 0 : sal_uInt32 nBufferSize = 64*1024;
124 : :
125 : 0 : rIn.Seek( STREAM_SEEK_TO_END );
126 : 0 : sal_uInt32 nSize = rIn.Tell();
127 : 0 : rIn.Seek( STREAM_SEEK_TO_BEGIN );
128 : :
129 : 0 : Sequence< sal_Int8 > aBuffer( min( nBufferSize, nSize ) );
130 : :
131 : 0 : while( nSize )
132 : : {
133 : 0 : if( nSize < nBufferSize )
134 : : {
135 : 0 : nBufferSize = nSize;
136 : 0 : aBuffer.realloc( nSize );
137 : : }
138 : :
139 : 0 : sal_uInt32 nRead = rIn.Read( aBuffer.getArray(), nBufferSize );
140 : : DBG_ASSERT( nRead == nBufferSize, "ImplCopySvStreamToXOutputStream failed!" );
141 : 0 : xOut->writeBytes( aBuffer );
142 : :
143 : 0 : if( nRead == 0 )
144 : 0 : break;
145 : :
146 : 0 : nSize -= nRead;
147 : 0 : }
148 : 0 : }
149 : :
150 : : // -----------------------------------------------------------------------------
151 : :
152 : 0 : void Writer::storeTo( Reference< XOutputStream > &xOutStream )
153 : : {
154 : 0 : for(FontMap::iterator i = maFonts.begin(); i != maFonts.end(); ++i)
155 : : {
156 : 0 : FlashFont* pFont = (*i);
157 : 0 : pFont->write( *mpFontsStream );
158 : 0 : delete pFont;
159 : : }
160 : :
161 : : // Endtag
162 : 0 : *mpMovieStream << (sal_uInt16)0;
163 : :
164 : 0 : Tag aHeader( 0xff );
165 : :
166 : 0 : aHeader.addUI8( 'F' );
167 : 0 : aHeader.addUI8( 'W' );
168 : 0 : aHeader.addUI8( 'S' );
169 : 0 : aHeader.addUI8( 5 );
170 : :
171 : 0 : sal_uInt32 nSizePos = aHeader.Tell();
172 : :
173 : 0 : aHeader << (sal_uInt32)0;
174 : :
175 : 0 : Rectangle aDocRect( 0, 0, static_cast<long>(mnDocWidth*mnDocXScale), static_cast<long>(mnDocHeight*mnDocYScale) );
176 : :
177 : 0 : aHeader.addRect( aDocRect );
178 : :
179 : : // frame delay in 8.8 fixed number of frames per second
180 : 0 : aHeader.addUI8( 0 );
181 : 0 : aHeader.addUI8( 12 );
182 : :
183 : 0 : aHeader.addUI16( _uInt16(mnFrames) );
184 : :
185 : 0 : const sal_uInt32 nSize = aHeader.Tell() + mpFontsStream->Tell() + mpMovieStream->Tell();
186 : :
187 : 0 : aHeader.Seek( nSizePos );
188 : 0 : aHeader << (sal_uInt32)nSize;
189 : :
190 : 0 : ImplCopySvStreamToXOutputStream( aHeader, xOutStream );
191 : 0 : ImplCopySvStreamToXOutputStream( *mpFontsStream, xOutStream );
192 : 0 : ImplCopySvStreamToXOutputStream( *mpMovieStream, xOutStream );
193 : 0 : }
194 : :
195 : : // -----------------------------------------------------------------------------
196 : :
197 : 0 : sal_uInt16 Writer::startSprite()
198 : : {
199 : 0 : sal_uInt16 nShapeId = createID();
200 : 0 : mvSpriteStack.push(mpSprite);
201 : 0 : mpSprite = new Sprite( nShapeId );
202 : 0 : return nShapeId;
203 : : }
204 : :
205 : : // -----------------------------------------------------------------------------
206 : :
207 : 0 : void Writer::endSprite()
208 : : {
209 : 0 : if( mpSprite )
210 : : {
211 : 0 : startTag( TAG_END );
212 : 0 : endTag();
213 : :
214 : 0 : mpSprite->write( *mpMovieStream );
215 : 0 : delete mpSprite;
216 : :
217 : 0 : if (!mvSpriteStack.empty())
218 : : {
219 : 0 : mpSprite = mvSpriteStack.top();
220 : 0 : mvSpriteStack.pop();
221 : : }
222 : : else
223 : 0 : mpSprite = NULL;
224 : : }
225 : 0 : }
226 : :
227 : : // -----------------------------------------------------------------------------
228 : :
229 : 0 : void Writer::placeShape( sal_uInt16 nID, sal_uInt16 nDepth, sal_Int32 x, sal_Int32 y, sal_uInt16 nClip, const char* pName )
230 : : {
231 : 0 : startTag( TAG_PLACEOBJECT2 );
232 : :
233 : 0 : BitStream aBits;
234 : :
235 : 0 : aBits.writeUB( nClip != 0, 1 ); // Has Clip Actions?
236 : 0 : aBits.writeUB( 0, 1 ); // reserved
237 : 0 : aBits.writeUB( pName != NULL, 1 ); // has a name
238 : 0 : aBits.writeUB( 0, 1 ); // no ratio
239 : 0 : aBits.writeUB( 0, 1 ); // no color transform
240 : 0 : aBits.writeUB( 1, 1 ); // has a matrix
241 : 0 : aBits.writeUB( 1, 1 ); // places a character
242 : 0 : aBits.writeUB( 0, 1 ); // does not define a character to be moved
243 : :
244 : 0 : mpTag->addBits( aBits );
245 : 0 : mpTag->addUI16( nDepth ); // depth
246 : 0 : mpTag->addUI16( nID ); // character Id
247 : :
248 : : // #i73264#
249 : : const basegfx::B2DHomMatrix aMatrix(basegfx::tools::createTranslateB2DHomMatrix(
250 : 0 : _Int16(static_cast<long>(map100thmm(x)*mnDocXScale)),
251 : 0 : _Int16(static_cast<long>(map100thmm(y)*mnDocYScale))));
252 : 0 : mpTag->addMatrix( aMatrix ); // transformation matrix
253 : :
254 : 0 : if( pName )
255 : 0 : mpTag->addString( pName );
256 : :
257 : 0 : if( nClip != 0 )
258 : 0 : mpTag->addUI16( nClip );
259 : :
260 : 0 : endTag();
261 : 0 : }
262 : :
263 : : #ifdef THEFUTURE
264 : : // -----------------------------------------------------------------------------
265 : :
266 : : void Writer::moveShape( sal_uInt16 nDepth, sal_Int32 x, sal_Int32 y )
267 : : {
268 : : startTag( TAG_PLACEOBJECT2 );
269 : :
270 : : BitStream aBits;
271 : : aBits.writeUB( 0, 1 ); // Has no Clip Actions
272 : : aBits.writeUB( 0, 1 ); // reserved
273 : : aBits.writeUB( 0, 1 ); // has no name
274 : : aBits.writeUB( 0, 1 ); // no ratio
275 : : aBits.writeUB( 0, 1 ); // no color transform
276 : : aBits.writeUB( 1, 1 ); // has a matrix
277 : : aBits.writeUB( 0, 1 ); // places a character
278 : : aBits.writeUB( 1, 1 ); // defines a character to be moved
279 : :
280 : : mpTag->addBits( aBits );
281 : : mpTag->addUI16( nDepth ); // depth
282 : :
283 : : // #i73264#
284 : : const basegfx::B2DHomMatrix aMatrix(basegfx::tools::createTranslateB2DHomMatrix(
285 : : _Int16(static_cast<long>(map100thmm(x)*mnDocXScale)),
286 : : _Int16(static_cast<long>(map100thmm(y)*mnDocYScale))));
287 : : mpTag->addMatrix( aMatrix ); // transformation matrix
288 : :
289 : : endTag();
290 : : }
291 : : #endif
292 : :
293 : : // -----------------------------------------------------------------------------
294 : :
295 : 0 : void Writer::removeShape( sal_uInt16 nDepth )
296 : : {
297 : 0 : startTag( TAG_REMOVEOBJECT2 );
298 : 0 : mpTag->addUI16( nDepth ); // depth
299 : 0 : endTag();
300 : 0 : }
301 : :
302 : : // -----------------------------------------------------------------------------
303 : :
304 : 0 : void Writer::startTag( sal_uInt8 nTagId )
305 : : {
306 : : DBG_ASSERT( mpTag == NULL, "Last tag was not ended");
307 : :
308 : 0 : mpTag = new Tag( nTagId );
309 : 0 : }
310 : :
311 : : // -----------------------------------------------------------------------------
312 : :
313 : 0 : void Writer::endTag()
314 : : {
315 : 0 : sal_uInt8 nTag = mpTag->getTagId();
316 : :
317 : 0 : if( mpSprite && ( (nTag == TAG_END) || (nTag == TAG_SHOWFRAME) || (nTag == TAG_DOACTION) || (nTag == TAG_STARTSOUND) || (nTag == TAG_PLACEOBJECT) || (nTag == TAG_PLACEOBJECT2) || (nTag == TAG_REMOVEOBJECT2) || (nTag == TAG_FRAMELABEL) ) )
318 : : {
319 : 0 : mpSprite->addTag( mpTag );
320 : 0 : mpTag = NULL;
321 : : }
322 : : else
323 : : {
324 : 0 : mpTag->write( *mpMovieStream );
325 : 0 : delete mpTag;
326 : 0 : mpTag = NULL;
327 : : }
328 : 0 : }
329 : :
330 : : // -----------------------------------------------------------------------------
331 : :
332 : 0 : sal_uInt16 Writer::createID()
333 : : {
334 : 0 : return mnNextId++;
335 : : }
336 : :
337 : : // -----------------------------------------------------------------------------
338 : :
339 : 0 : void Writer::showFrame()
340 : : {
341 : 0 : startTag( TAG_SHOWFRAME );
342 : 0 : endTag();
343 : :
344 : 0 : if(NULL == mpSprite)
345 : 0 : mnFrames++;
346 : 0 : }
347 : :
348 : : // -----------------------------------------------------------------------------
349 : :
350 : 0 : sal_uInt16 Writer::defineShape( const GDIMetaFile& rMtf, sal_Int16 x, sal_Int16 y )
351 : : {
352 : 0 : mpVDev->SetMapMode( rMtf.GetPrefMapMode() );
353 : 0 : Impl_writeActions( rMtf );
354 : :
355 : 0 : sal_uInt16 nId = 0;
356 : : {
357 : 0 : CharacterIdVector::iterator aIter( maShapeIds.begin() );
358 : 0 : const CharacterIdVector::iterator aEnd( maShapeIds.end() );
359 : :
360 : 0 : sal_Bool bHaveShapes = aIter != aEnd;
361 : :
362 : 0 : if (bHaveShapes)
363 : : {
364 : 0 : nId = startSprite();
365 : :
366 : 0 : sal_uInt16 iDepth = 1;
367 : 0 : for(; aIter != aEnd; ++aIter)
368 : : {
369 : 0 : placeShape( *aIter, iDepth++, x, y );
370 : : }
371 : :
372 : 0 : endSprite();
373 : : }
374 : : }
375 : :
376 : 0 : maShapeIds.clear();
377 : :
378 : 0 : return nId;
379 : : }
380 : :
381 : : // -----------------------------------------------------------------------------
382 : :
383 : 0 : sal_uInt16 Writer::defineShape( const Polygon& rPoly, const FillStyle& rFillStyle )
384 : : {
385 : 0 : const PolyPolygon aPolyPoly( rPoly );
386 : 0 : return defineShape( aPolyPoly, rFillStyle );
387 : : }
388 : :
389 : : // -----------------------------------------------------------------------------
390 : :
391 : 0 : sal_uInt16 Writer::defineShape( const PolyPolygon& rPolyPoly, const FillStyle& rFillStyle )
392 : : {
393 : 0 : sal_uInt16 nShapeId = createID();
394 : :
395 : : // start a DefineShape3 tag
396 : 0 : startTag( TAG_DEFINESHAPE3 );
397 : :
398 : 0 : mpTag->addUI16( nShapeId );
399 : 0 : mpTag->addRect( rPolyPoly.GetBoundRect() );
400 : :
401 : :
402 : : // FILLSTYLEARRAY
403 : 0 : mpTag->addUI8( 1 ); // FillStyleCount
404 : :
405 : : // FILLSTYLE
406 : 0 : rFillStyle.addTo( mpTag );
407 : :
408 : : // LINESTYLEARRAY
409 : 0 : mpTag->addUI8( 0 ); // LineStyleCount
410 : :
411 : : // Number of fill and line index bits to 1
412 : 0 : mpTag->addUI8( 0x11 );
413 : :
414 : 0 : BitStream aBits;
415 : :
416 : 0 : const sal_uInt16 nCount = rPolyPoly.Count();
417 : : sal_uInt16 i;
418 : 0 : for( i = 0; i < nCount; i++ )
419 : : {
420 : 0 : const Polygon& rPoly = rPolyPoly[ i ];
421 : 0 : if( rPoly.GetSize() )
422 : 0 : Impl_addPolygon( aBits, rPoly, true );
423 : : }
424 : :
425 : 0 : Impl_addEndShapeRecord( aBits );
426 : :
427 : 0 : mpTag->addBits( aBits );
428 : 0 : endTag();
429 : :
430 : 0 : return nShapeId;
431 : : }
432 : :
433 : : // -----------------------------------------------------------------------------
434 : :
435 : 0 : sal_uInt16 Writer::defineShape( const PolyPolygon& rPolyPoly, sal_uInt16 nLineWidth, const Color& rLineColor )
436 : : {
437 : 0 : sal_uInt16 nShapeId = createID();
438 : :
439 : : // start a DefineShape3 tag
440 : 0 : startTag( TAG_DEFINESHAPE3 );
441 : :
442 : 0 : mpTag->addUI16( nShapeId );
443 : 0 : mpTag->addRect( rPolyPoly.GetBoundRect() );
444 : :
445 : :
446 : : // FILLSTYLEARRAY
447 : 0 : mpTag->addUI8( 0 ); // FillStyleCount
448 : :
449 : : // LINESTYLEARRAY
450 : 0 : mpTag->addUI8( 1 ); // LineStyleCount
451 : :
452 : : // LINESTYLE
453 : 0 : mpTag->addUI16( nLineWidth ); // Width of line in twips
454 : 0 : mpTag->addRGBA( rLineColor ); // Color
455 : :
456 : : // Number of fill and line index bits to 1
457 : 0 : mpTag->addUI8( 0x11 );
458 : :
459 : 0 : BitStream aBits;
460 : :
461 : 0 : const sal_uInt16 nCount = rPolyPoly.Count();
462 : : sal_uInt16 i;
463 : 0 : for( i = 0; i < nCount; i++ )
464 : : {
465 : 0 : const Polygon& rPoly = rPolyPoly[ i ];
466 : 0 : if( rPoly.GetSize() )
467 : 0 : Impl_addPolygon( aBits, rPoly, false );
468 : : }
469 : :
470 : 0 : Impl_addEndShapeRecord( aBits );
471 : :
472 : 0 : mpTag->addBits( aBits );
473 : 0 : endTag();
474 : :
475 : 0 : return nShapeId;
476 : : }
477 : :
478 : : #ifdef AUGUSTUS
479 : : enum {NO_COMPRESSION, ADPCM_COMPRESSION, MP3_COMPRESSION } COMPRESSION_TYPE;
480 : : sal_Bool Writer::streamSound( const char * filename )
481 : : {
482 : : SF_INFO info;
483 : : SNDFILE *sf = sf_open(filename, SFM_READ, &info);
484 : :
485 : : if (NULL == sf)
486 : : return sal_False;
487 : : else
488 : : {
489 : : // AS: Start up lame.
490 : : m_lame_flags = lame_init();
491 : :
492 : : // The default (if you set nothing) is a a J-Stereo, 44.1khz
493 : : // 128kbps CBR mp3 file at quality 5. Override various default settings
494 : : // as necessary, for example:
495 : :
496 : : lame_set_num_channels(m_lame_flags,1);
497 : : lame_set_in_samplerate(m_lame_flags,22050);
498 : : lame_set_brate(m_lame_flags,48);
499 : : lame_set_mode(m_lame_flags,MONO);
500 : : lame_set_quality(m_lame_flags,2); /* 2=high 5 = medium 7=low */
501 : :
502 : : // See lame.h for the complete list of options. Note that there are
503 : : // some lame_set_*() calls not documented in lame.h. These functions
504 : : // are experimental and for testing only. They may be removed in
505 : : // the future.
506 : :
507 : : //4. Set more internal configuration based on data provided above,
508 : : // as well as checking for problems. Check that ret_code >= 0.
509 : :
510 : : int ret_code = lame_init_params(m_lame_flags);
511 : :
512 : : if (ret_code < 0)
513 : : throw 0;
514 : :
515 : : int samples_per_frame = 22050 / 12; // AS: (samples/sec) / (frames/sec) = samples/frame
516 : : int mp3buffer_size = static_cast<int>(samples_per_frame*1.25 + 7200 + 7200);
517 : :
518 : :
519 : : startTag(TAG_SOUNDSTREAMHEAD2);
520 : :
521 : : mpTag->addUI8(2<<2 | 1<<1 | 0<<0); // Preferred mixer format ??
522 : :
523 : : BitStream bs;
524 : :
525 : : bs.writeUB(MP3_COMPRESSION,4);
526 : : bs.writeUB(2, 2); // AS: Reserved zero bits.
527 : : bs.writeUB(1, 1); // AS: 16 Bit
528 : : bs.writeUB(0, 1); // AS: Mono.
529 : :
530 : : mpTag->addBits(bs);
531 : :
532 : : mpTag->addUI16(samples_per_frame);
533 : : endTag();
534 : :
535 : : short *sample_buff = new short[static_cast<int>(info.frames)];
536 : : sf_readf_short(sf, sample_buff, info.frames);
537 : :
538 : : unsigned char* mp3buffer = new unsigned char[mp3buffer_size];
539 : :
540 : : // 5. Encode some data. input pcm data, output (maybe) mp3 frames.
541 : : // This routine handles all buffering, resampling and filtering for you.
542 : : // The required mp3buffer_size can be computed from num_samples,
543 : : // samplerate and encoding rate, but here is a worst case estimate:
544 : : // mp3buffer_size (in bytes) = 1.25*num_samples + 7200.
545 : : // num_samples = the number of PCM samples in each channel. It is
546 : : // not the sum of the number of samples in the L and R channels.
547 : : //
548 : : // The return code = number of bytes output in mp3buffer. This can be 0.
549 : : // If it is <0, an error occurred.
550 : :
551 : :
552 : : for (int samples_written = 0; samples_written < info.frames; samples_written += samples_per_frame)
553 : : {
554 : : startTag(TAG_SOUNDSTREAMBLOCK);
555 : :
556 : : int samples_to_write = std::min((int)info.frames - samples_written, samples_per_frame);
557 : :
558 : : // AS: Since we're mono, left and right sample buffs are the same
559 : : // ie, samplebuff (which is why we pass it twice).
560 : : int ret = lame_encode_buffer(m_lame_flags, sample_buff + samples_written,
561 : : sample_buff + samples_written,
562 : : samples_to_write, mp3buffer, mp3buffer_size);
563 : :
564 : : if (ret < 0)
565 : : throw 0;
566 : :
567 : : // 6. lame_encode_flush will flush the buffers and may return a
568 : : // final few mp3 frames. mp3buffer should be at least 7200 bytes.
569 : : // return code = number of bytes output to mp3buffer. This can be 0.
570 : :
571 : : if (mp3buffer_size - ret < 7200)
572 : : throw 0;
573 : :
574 : : int ret2 = lame_encode_flush(m_lame_flags, mp3buffer + ret, mp3buffer_size - ret);
575 : :
576 : : if (ret2 < 0)
577 : : throw 0;
578 : :
579 : :
580 : : SvMemoryStream strm(mp3buffer, ret + ret2, STREAM_READWRITE);
581 : :
582 : : mpTag->addUI16(samples_to_write);
583 : : mpTag->addUI16(0);
584 : : mpTag->addStream(strm);
585 : :
586 : : endTag();
587 : :
588 : : showFrame();
589 : : }
590 : :
591 : :
592 : : delete[] mp3buffer;
593 : :
594 : : delete[] sample_buff;
595 : : sf_close(sf);
596 : :
597 : : // 8. free the internal data structures.
598 : : lame_close(m_lame_flags);
599 : : }
600 : :
601 : : return sal_True;
602 : : }
603 : : #endif // AUGUSTUS
604 : :
605 : :
606 : : // -----------------------------------------------------------------------------
607 : :
608 : 0 : void Writer::stop()
609 : : {
610 : 0 : startTag( TAG_DOACTION );
611 : 0 : mpTag->addUI8( 0x07 );
612 : 0 : mpTag->addUI8( 0 );
613 : 0 : endTag();
614 : 0 : }
615 : :
616 : : // -----------------------------------------------------------------------------
617 : :
618 : 0 : void Writer::waitOnClick( sal_uInt16 nDepth )
619 : : {
620 : 0 : placeShape( _uInt16( mnPageButtonId ), nDepth, 0, 0 );
621 : 0 : stop();
622 : 0 : showFrame();
623 : 0 : removeShape( nDepth );
624 : 0 : }
625 : :
626 : : // -----------------------------------------------------------------------------
627 : :
628 : : /** inserts a doaction tag with an ActionGotoFrame */
629 : 0 : void Writer::gotoFrame( sal_uInt16 nFrame )
630 : : {
631 : 0 : startTag( TAG_DOACTION );
632 : 0 : mpTag->addUI8( 0x81 );
633 : 0 : mpTag->addUI16( 2 );
634 : 0 : mpTag->addUI16( nFrame );
635 : 0 : mpTag->addUI8( 0 );
636 : 0 : endTag();
637 : 0 : }
638 : :
639 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|