void skipMP3(SWFSoundStream stream, float skip) { int frameSize; int skipFrames, l; if ( stream->sampleRate > 32000 ) frameSize = 1152; else frameSize = 576; skipFrames = (int)floor((skip / frameSize) / stream->sampleRate); if(skipFrames <= 0) return; while(skipFrames > 0) { l = nextMP3Frame(stream->source.mp3.input); if (l < 0) { SWF_warn("no more frames to skip \n"); break; } --skipFrames; stream->source.mp3.start += l; } }
/* adds a character * Add a character to a button for given states * possible states: * SWFBUTTON_HIT * SWFBUTTON_DOWN * SWFBUTTON_OVER * SWFBUTTON_UP * states can be combined using the binary or operator * returns a SWFButtonRecord object which can be further modified. */ SWFButtonRecord SWFButton_addCharacter(SWFButton button /* button object */, SWFCharacter character /* character to be added */, byte state /* state description */) { SWFMatrix m; SWFButtonRecord record; SWFCharacter **depsPtr = &CHARACTER(button)->dependencies; int *depCount = &CHARACTER(button)->nDependencies; if ( SWFCharacter_isFinished((SWFCharacter)button) ) { SWF_warn("Can't alter a button after it's been added to another character"); return NULL; } SWFCharacter_getDependencies(character, depsPtr, depCount); SWFCharacter_addDependency((SWFCharacter)button, character); SWFCharacter_setFinished(character); m = newSWFMatrix(1.0, 0, 0, 1.0, 0, 0); record = newSWFButtonRecord(state, character, 0, m); SWFButton_addRecord(button, record); return record; }
void SWFOutput_writeGradientAsFilter(SWFOutput out, SWFGradient gradient) { int i; int nGrads = gradient->nGrads; if(nGrads > 8) { SWF_warn("Can't write more than 8 control points for filter gradients\n"); nGrads = 8; } SWFOutput_writeUInt8(out, nGrads); /* only 1-8 allowed */ for ( i=0; i<nGrads; ++i ) { SWFOutput_writeUInt8(out, gradient->entries[i].r); SWFOutput_writeUInt8(out, gradient->entries[i].g); SWFOutput_writeUInt8(out, gradient->entries[i].b); SWFOutput_writeUInt8(out, gradient->entries[i].a); } for ( i=0; i<nGrads; ++i ) SWFOutput_writeUInt8(out, gradient->entries[i].ratio); }
/* font machinery: if a regular font (outlines in fdb) is used, it is added to the textfield as type Font and later converted to a FontChar while a Font, characters can be added (embedded) an Imported font stays as is, so does a BrowserFont */ void SWFTextField_setFont(SWFTextField field, SWFBlock font) { if(font == NULL) return; if ( BLOCK(font)->type == SWF_BROWSERFONT ) { field->fonttype = BrowserFont; field->font.browserFont = (SWFBrowserFont)font; SWFCharacter_addDependency((SWFCharacter)field, (SWFCharacter)font); field->flags |= SWFTEXTFIELD_HASFONT; } else if ( BLOCK(font)->type == SWF_DEFINEFONT || BLOCK(font)->type == SWF_DEFINEFONT2) { SWFFontCharacter fc = (SWFFontCharacter)font; if(checkSWFFontCharacter(fc)) { SWF_warn("font is empty or has no layout information\n"); return; } field->fonttype = Imported; field->font.fontchar = fc; SWFCharacter_addDependency( (SWFCharacter)field, (SWFCharacter)font); field->flags |= SWFTEXTFIELD_HASFONT | SWFTEXTFIELD_USEFONT; } else if (BLOCK(font)->type == SWF_MINGFONT) { if(!(SWFFont_getFlags((SWFFont)font) & SWF_FONT_HASLAYOUT)) { SWF_warn("font is empty or has no layout information\n"); return; } field->fonttype = Font; field->font.font = (SWFFont)font; field->flags |= SWFTEXTFIELD_HASFONT | SWFTEXTFIELD_USEFONT; } else SWF_warn("SWFTextField_setFont: not a valid font object\n"); }
/* * set blend mode. * See ming.h for possible blend modes * Only if SWF Version >= 8. Sets PlaceObject version to 3 */ void SWFPlaceObject2Block_setBlendMode(SWFPlaceObject2Block block, int mode) { if(mode < 0 || mode > 255) { SWF_warn("SWFPlaceObject2Block_setBlendMode: mode must be in between [0...255]"); return; } setPlaceObjectVersion(block, 3); block->hasBlendFlag = 1; block->blendMode = mode; }
void destroySWFSoundStream(SWFSoundStream stream) { if (stream->freeInput) { if(stream->streamSource == STREAM_MP3) destroySWFInput(stream->source.mp3.input); else if(stream->streamSource == STREAM_FLV) destroyFLVStream(stream->source.flv.stream); else SWF_warn("destroySWFSoundStream: unknown stream\n"); } free(stream); }
static int fillBlock_flv_nelly(SWFSoundStream stream, SWFSoundStreamBlock block) { FLVStream *flv = stream->source.flv.stream; FLVTag *tag = &stream->source.flv.tag; int length, samples, ret; SWFInput input; int tagOffset = stream->source.flv.tagOffset; if(tagOffset < 0) { ret = FLVStream_nextTagType(flv, tag, NULL, FLV_AUDIOTAG); if(ret < 0) { SWF_warn("fillStreamBlock_flv: not a valid flv audio stream\n"); return -1; } } input = FLVTag_getPayloadInput(tag); if(input == NULL) return -1; samples = stream->samplesPerFrame; while (samples > 0) { length = SWFInput_length(input); if (length < 0) return -1; samples -= length * 64; block->length += length; if(samples > 0) { ret = FLVStream_nextTagType(flv, tag, tag, FLV_AUDIOTAG); if(ret < 0) return -1; input = FLVTag_getPayloadInput(tag); if(input == NULL) return -1; } } stream->source.flv.tag = *tag; stream->source.flv.tagOffset = 0; return 0; }
/* * DEPRECATED! * returns the number of movie frames for a given sound stream * * This function returns the number of movie frames necessary to * play the full sound stream. * Works only if the sound stream object was added to a movie and the stream * source is a mp3 file. * * Use SWFSoundStream_getDuration() instead. */ int SWFSoundStream_getFrames(SWFSoundStream stream) { int n, frameSize; if(stream->streamSource == STREAM_FLV || stream->samplesPerFrame == 0) { SWF_warn("SWFSoundStream_getFrames works only if stream was assigned to a movie\n"); return -1; } if ( stream->sampleRate > 32000 ) frameSize = 1152; else frameSize = 576; n = 0; while(nextMP3Frame(stream->source.mp3.input) > 0) n++; SWFSoundStream_rewind(stream); return n * frameSize / stream->samplesPerFrame; }
static int getStreamFlag_flv(SWFSoundStream stream, float frameRate, float skip) { int flags = 0, ret; FLVTag tag, *tag_p = NULL; unsigned int skip_msec; while((ret = FLVStream_nextTag(stream->source.flv.stream, &tag, tag_p)) == 0) { if(tag.tagType == FLV_AUDIOTAG) break; tag_p = &tag; } if(ret < 0) return -1; switch(tag.hdr.audio.samplingRate >> 2) { case 1: stream->sampleRate = 11025; break; case 2: stream->sampleRate = 22050; break; case 3: stream->sampleRate = 44100; break; default: SWF_warn("getStreamFlag_flv: unsupported sampleRate\n"); } stream->samplesPerFrame = (int)floor(stream->sampleRate / frameRate); flags = tag.hdr.audio.samplingRate | tag.hdr.audio.sampleSize; flags |= tag.hdr.audio.channel | tag.hdr.audio.format; stream->flags = flags; /* XXX: fixme */ skip_msec = round(skip * 1000); if(FLVStream_setStreamOffset(stream->source.flv.stream, skip_msec) < 0) return -1; return flags; }
void SWFShape_drawScaledGlyph(SWFShape shape, SWFFont font, unsigned short c, int size) { int i, vx, vy; if(font == NULL) return; SWFShape glyph = SWFFont_getGlyph(font, c); if(glyph == NULL) { SWF_warn("SWFShape_drawScaledGlyph: no glyph for code %i found \n", c); return; } vx = shape->xpos; vy = shape->ypos; for(i = 0; i < glyph->nRecords; i++) addShapeRecord(shape, glyph->records[i], &vx, &vy, size/1024.0); }
/* * This function replaces a displayable character with a new one. * Do not use this function. Use SWFMovie_replace instead! * returns 0 on success */ int SWFMovie_replace_internal(SWFMovie movie, SWFDisplayItem item, SWFMovieBlockType ublock) { SWFBlock block = ublock.block; if(block == NULL || item == NULL) return -1; if ( SWFBlock_getType(block) == SWF_DEFINEBITS || SWFBlock_getType(block) == SWF_DEFINEBITSJPEG2 || SWFBlock_getType(block) == SWF_DEFINEBITSJPEG3 || SWFBlock_getType(block) == SWF_DEFINELOSSLESS || SWFBlock_getType(block) == SWF_DEFINELOSSLESS2 ) { block = (SWFBlock)newSWFShapeFromBitmap((SWFBitmap)block, SWFFILL_TILED_BITMAP); } /* if it's a text object, we need to translate fonts into font characters */ if ( SWFBlock_getType(block) == SWF_DEFINETEXT || SWFBlock_getType(block) == SWF_DEFINETEXT2 ) { SWFMovie_resolveTextFonts(movie, (SWFText)block); } if ( SWFBlock_getType(block) == SWF_DEFINEEDITTEXT) { SWFMovie_resolveTextfieldFont(movie, (SWFTextField)block); } if ( SWFBlock_isCharacter(block) ) { SWFCharacter_setFinished((SWFCharacter)block); SWFMovie_addCharacterDependencies(movie, (SWFCharacter)block); SWFDisplayItem_replace(item, (SWFCharacter)block); return 0; } SWF_warn("SWFMovie_replace: only characters can be replaced\n"); return -1; }
static int getStreamFlag_mp3File(SWFSoundStream stream, float frameRate, float skip) { SWFInput input = stream->source.mp3.input; int start; byte flags; static const int maxSPF = 65535; start = getMP3Flags(input, &flags); if(start < 0) return -1; stream->source.mp3.start = start; stream->sampleRate = SWFSound_getSampleRate(flags); stream->flags = flags; /* XXX: fixme */ stream->samplesPerFrame = (int)floor(stream->sampleRate / frameRate); if ( stream->samplesPerFrame > maxSPF ) { SWF_warn("getStreamFlag_mp3File: computed number of samples per frame (%d) exceed max allowed value of %d\n", stream->samplesPerFrame, maxSPF); } skipMP3(stream, skip); return flags; }
static void fillStreamBlock_flv(SWFSoundStream stream, SWFSoundStreamBlock block) { int ret; if(AUDIO_CODEC(stream) == AUDIO_CODEC_MP3) ret = fillBlock_flv_mp3(stream, block); else if(AUDIO_CODEC(stream) == AUDIO_CODEC_NELLY || AUDIO_CODEC(stream) == AUDIO_CODEC_NELLY_MONO) ret = fillBlock_flv_nelly(stream, block); else { SWF_warn("unsupported codec %i\n", AUDIO_CODEC(stream)); ret = -1; } if(ret < 0) { stream->isFinished = TRUE; SWFSoundStream_rewind(stream); } }
static void fillStreamBlock_mp3(SWFSoundStream stream, SWFSoundStreamBlock block) { int delay, wanted; static const int maxSC = 65535; /* see how many frames we can put in this block, see how big they are */ block->delay = stream->delay; delay = stream->delay + stream->samplesPerFrame; wanted = delay; block->length = getMP3Samples(stream->source.mp3.input, stream->flags, &delay); block->numSamples = delay; if ( block->numSamples > maxSC ) { SWF_warn("fillStreamBlock_mp3: number of samples in block (%d) exceed max allowed value of %d\n", block->numSamples, maxSC); } if(block->length <= 0) { stream->isFinished = TRUE; SWFSoundStream_rewind(stream); } stream->delay = wanted - delay; }
SWFOutput SWFMovie_toOutput(SWFMovie movie, int level) { int swflength; #if USE_ZLIB int status; #endif SWFOutput header, tempbuffer=0, buffer, swfbuffer; SWFBlock lastBlock; unsigned long compresslength; if ( movie->nExports > 0 ) SWFMovie_writeExports(movie); if ( movie->metadata != NULL) { SWFMovie_addBlock(movie, (SWFBlock)movie->metadata); movie->metadata = NULL; // do not destroy with movie if added as block } /* Add a terminating SHOWFRAME tag if not already there */ lastBlock = SWFBlockList_getLastBlock(movie->blockList); if ( ! lastBlock || SWFBlock_getType(lastBlock) != SWF_SHOWFRAME ) { SWFMovie_nextFrame(movie); } while ( movie->nFrames < movie->totalFrames ) SWFMovie_nextFrame(movie); if(movie->symbolClass) SWFMovie_addBlock(movie, (SWFBlock)movie->symbolClass); if(movie->sceneData) SWFMovie_addBlock(movie, (SWFBlock)movie->sceneData); SWFMovie_addBlock(movie, newSWFEndBlock()); // add five for the setbackground block.. swflength = SWFBlockList_completeBlocks(movie->blockList, movie->version); /* XXX - hack */ SWFDisplayList_rewindSoundStream(movie->displayList); header = newSizedSWFOutput(23); SWFOutput_writeRect(header, movie->bounds); SWFOutput_writeUInt16(header, (int)floor(movie->rate*256)); SWFOutput_writeUInt16(header, movie->nFrames); /* SWF >= 8: first block _must_ be SWF_FILEATTRIBUTES */ if(movie->fattrs) writeSWFBlockToMethod((SWFBlock)movie->fattrs, SWFOutputMethod, header); if(movie->backgroundBlock) writeSWFBlockToMethod(movie->backgroundBlock, SWFOutputMethod, header); if(movie->limits) writeSWFBlockToMethod((SWFBlock)movie->limits, SWFOutputMethod, header); SWFOutput_byteAlign(header); swflength += 8 + SWFOutput_getLength(header); // compression level check #if USE_ZLIB if (level < -1) level = -1; if (level > 9) level = 9; #else if ( level != -1 ) { SWF_warn("No zlib support compiled in, " "cannot generate compressed output"); level = -1; } #endif // reserve output buffer if(level >= 0) { // a little bit more than the uncompressed data compresslength = swflength + (swflength/1000) + 15 + 1; swfbuffer = newSizedSWFOutput( compresslength + 8 ); } else swfbuffer = newSizedSWFOutput( swflength ); if (level >= 0) SWFOutput_writeUInt8 (swfbuffer, 'C'); else SWFOutput_writeUInt8 (swfbuffer, 'F'); SWFOutput_writeUInt8 (swfbuffer, 'W'); SWFOutput_writeUInt8 (swfbuffer, 'S'); SWFOutput_writeUInt8 (swfbuffer, movie->version); // Movie length SWFOutput_writeUInt32(swfbuffer, swflength); if(level >= 0) buffer = tempbuffer = newSizedSWFOutput( swflength - 8); else buffer = swfbuffer; SWFOutput_writeToMethod(header, SWFOutputMethod, buffer); destroySWFOutput(header); // fill swfbuffer with blocklist SWFBlockList_writeBlocksToMethod(movie->blockList, SWFOutputMethod, buffer); #if USE_ZLIB if (level >= 0) { status = compress2 ( (Bytef*) SWFOutput_getBuffer(swfbuffer)+8, &compresslength, SWFOutput_getBuffer(tempbuffer), SWFOutput_getLength(tempbuffer), level); if (status == Z_OK) { SWFOutput_truncate(swfbuffer, compresslength+8); destroySWFOutput(tempbuffer); } else SWF_error("compression failed"); } #endif // ndef USE_ZLIB return swfbuffer; }
static int fillBlock_flv_mp3(SWFSoundStream stream, SWFSoundStreamBlock block) { FLVStream *flv = stream->source.flv.stream; FLVTag *tag = &stream->source.flv.tag; int tagOffset = stream->source.flv.tagOffset; int delay, length, frameSize, ret; SWFInput input; static const int maxSC = 65535; block->delay = stream->delay; delay = stream->delay + stream->samplesPerFrame; if(tagOffset < 0) { ret = FLVStream_nextTagType(flv, tag, NULL, FLV_AUDIOTAG); if(ret < 0) { SWF_warn("fillStreamBlock_flv: not a valid flv audio stream\n"); return -1; } } input = FLVTag_getPayloadInput(tag); if(input == NULL) return -1; if(tagOffset > 0) SWFInput_seek(input, tagOffset, SEEK_SET); if ( stream->sampleRate > 32000 ) frameSize = 1152; else frameSize = 576; while ( delay > frameSize) { length = nextMP3Frame(input); if (length < 0) { SWF_warn("parse error: not a valid mp3 frame\n"); return -1; } else if(length == 0) /* eof */ { ret = FLVStream_nextTagType(flv, tag, tag, FLV_AUDIOTAG); if(ret < 0) return -1; input = FLVTag_getPayloadInput(tag); if(input == NULL) return -1; } else { block->numSamples += frameSize; block->length += length; delay -= frameSize; } } if ( block->numSamples > maxSC ) { SWF_warn("fillBlock_flv_mp3: number of samples in block (%d) exceed max allowed value of %d\n", block->numSamples, maxSC); } stream->source.flv.tag = *tag; stream->source.flv.tagOffset = SWFInput_tell(input); stream->delay = delay; return 0; }