Esempio n. 1
0
File: ogg.go Progetto: mzinin/tagger
func (editor *OggTagEditor) makeNewPages(existingCommentPages []byte, tag Tag) ([]byte, []byte, int) {
	// bitstream number
	var bitstream int = 31013
	if len(existingCommentPages) > oggPageHeaderSize {
		bitstream = utils.ReadInt32Le(existingCommentPages[14:18])
	}

	commentHeader, existingTagData, setupHeader := editor.splitCommentPages(existingCommentPages)
	if len(commentHeader) == 0 {
		commentHeader = make([]byte, 1+len(oggHeaderMagic)+4)
		commentHeader[0] = 3
		copy(commentHeader[1:1+len(oggHeaderMagic)], oggHeaderMagic)
		utils.WriteInt32Le(0, commentHeader[len(oggHeaderMagic):len(oggHeaderMagic)+4])
	}

	unsupportedTagData, unsupportedFields := getUnsupportedVorbisTags(existingTagData)
	newTagData, totalFields := serializeVorbisTag(tag, unsupportedFields)

	tagData := make([]byte, len(commentHeader)+4+len(newTagData)+len(unsupportedTagData)+1)
	copy(tagData, commentHeader)
	utils.WriteInt32Le(totalFields, tagData[len(commentHeader):len(commentHeader)+4])
	copy(tagData[len(commentHeader)+4:], newTagData)
	copy(tagData[len(commentHeader)+4+len(newTagData):], unsupportedTagData)
	tagData[len(tagData)-1] = 1

	newCommentHeader, commentPages := editor.packTagDataIntoFrames(bitstream, 1, tagData)
	newSetupHeader, setupPages := editor.packTagDataIntoFrames(bitstream, commentPages+1, setupHeader)

	return newCommentHeader, newSetupHeader, commentPages + setupPages
}
Esempio n. 2
0
File: ogg.go Progetto: mzinin/tagger
func (editor *OggTagEditor) WriteTag(src, dst string, tag Tag) error {
	err := editor.readFile(src)
	if err != nil {
		return err
	}

	idPage, commentPages, restData := editor.splitFileData(editor.file)
	newCommentPages, newSetupPages, numberOfPages := editor.makeNewPages(commentPages, tag)

	newPrefix := make([]byte, len(idPage)+len(newCommentPages)+len(newSetupPages))
	copy(newPrefix, idPage)
	copy(newPrefix[len(idPage):], newCommentPages)
	copy(newPrefix[len(idPage)+len(newCommentPages):], newSetupPages)

	// fix page numbers and CRCs
	sequence := numberOfPages + 1
	data := restData
	for len(data) > oggPageHeaderSize {
		pageSize := editor.getPageSize(data)

		utils.WriteInt32Le(sequence, data[18:22])                     // number
		utils.WriteUint32Le(0, data[22:26])                           // zero CRC
		utils.WriteUint32Le(editor.crc(data[:pageSize]), data[22:26]) // CRC

		sequence++
		data = data[pageSize:]
	}

	return ioutil.WriteFile(dst, append(newPrefix, restData...), 0666)
}
Esempio n. 3
0
func serializeVorbisTagTextField(text, frameName string, dst []byte, offset int) int {
	fieldSize := len(frameName) + len(text) + 1
	utils.WriteInt32Le(fieldSize, dst[offset:offset+4])
	copy(dst[offset+4:offset+4+len(frameName)], frameName)
	dst[offset+4+len(frameName)] = 0x3d // '='
	copy(dst[offset+5+len(frameName):offset+4+fieldSize], text)
	return offset + 4 + fieldSize
}
Esempio n. 4
0
File: ogg.go Progetto: mzinin/tagger
func (editor *OggTagEditor) fillHeader(dst []byte, bitstream, sequence, totalSize int) (int, int) {
	copy(dst[0:4], oggPageMagic) // magic
	dst[4] = 0                   // version
	dst[5] = 0                   // header type
	dst[6] = 0                   // granule position
	dst[7] = 0
	dst[8] = 0
	dst[9] = 0
	dst[10] = 0
	dst[11] = 0
	dst[12] = 0
	dst[13] = 0
	utils.WriteInt32Le(bitstream, dst[14:18]) // bitstream serial number
	utils.WriteInt32Le(sequence, dst[18:22])  // page sequence number
	dst[22] = 0                               // CRC checksum
	dst[23] = 0
	dst[24] = 0
	dst[25] = 0

	dataSize := totalSize
	if dataSize > maxFrameDataSize {
		dataSize = maxFrameDataSize
	}

	dst[26] = byte(dataSize / 255)
	if dataSize%255 != 0 {
		dst[26]++
	}

	headerSize := 27 + int(dst[26])
	for i := 27; i < headerSize; i++ {
		dst[i] = 0xFF
	}
	if dataSize%255 != 0 {
		dst[headerSize-1] = byte(dataSize % 255)
	}

	return headerSize, dataSize
}
Esempio n. 5
0
func (editor *FlacTagEditor) makeNewCommentBlock(tag Tag, existingCommentBlock []byte) []byte {
	var vendorData []byte = nil
	var unsupportedTagData []byte = nil
	var unsupportedFields int = 0

	if len(existingCommentBlock) >= 8 {
		vendorSize := utils.ReadInt32Le(existingCommentBlock[4:8])
		vendorData = existingCommentBlock[4 : 8+vendorSize]
		unsupportedTagData, unsupportedFields = getUnsupportedVorbisTags(existingCommentBlock[8+vendorSize:])
	}

	newCommentData, totalFields := serializeVorbisTag(tag, unsupportedFields)

	newCommentBlock := make([]byte, 4+len(vendorData)+4+len(newCommentData)+len(unsupportedTagData))
	newCommentBlock[0] = commentBlockType
	utils.WriteInt24Be(len(newCommentBlock)-4, newCommentBlock[1:4])
	copy(newCommentBlock[4:], vendorData)
	utils.WriteInt32Le(totalFields, newCommentBlock[4+len(vendorData):8+len(vendorData)])
	copy(newCommentBlock[8+len(vendorData):], newCommentData)
	copy(newCommentBlock[8+len(vendorData)+len(newCommentData):], unsupportedTagData)

	return newCommentBlock
}