예제 #1
0
파일: common.go 프로젝트: mzinin/tagger
func getUnsupportedVorbisTags(data []byte) ([]byte, int) {
	result := make([]byte, len(data))
	fields := 0
	size := 0

	numberOfFields := utils.ReadInt32Le(data[0:4])
	data = data[4:]

	for i := 0; i < numberOfFields; i++ {
		fieldSize := utils.ReadInt32Le(data[0:4])
		if len(data) < fieldSize+4 {
			break
		}

		pos := bytes.IndexByte(data[4:4+fieldSize], 0x3d)
		if pos == -1 {
			break
		}

		fieldName := strings.ToUpper(string(data[4 : 4+pos]))
		switch fieldName {
		case "TITLE", "ARTIST", "ALBUM", "TRACKNUMBER", "DATE", "GENRE", "METADATA_BLOCK_PICTURE":
			break
		default:
			copy(result[size:size+4+fieldSize], data[:4+fieldSize])
			fields++
			size += 4 + fieldSize
		}

		data = data[4+fieldSize:]
	}

	return result[:size], fields
}
예제 #2
0
파일: ogg.go 프로젝트: 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
}
예제 #3
0
파일: ogg.go 프로젝트: mzinin/tagger
func (editor *OggTagEditor) splitCommentPages(pages []byte) ([]byte, []byte, []byte) {
	var commentHeader []byte = nil
	var tagData []byte = nil
	var setupHeader []byte = nil

	for len(pages) > oggPageHeaderSize {
		pageHeaderSize := oggPageHeaderSize + int(pages[oggPageHeaderSize-1])

		// it's the 1st page, the one with comment header
		if pages[5]&headerTypeContinue == 0 {
			if len(pages) < pageHeaderSize+5+len(oggHeaderMagic) {
				return nil, nil, nil
			}
			commentHeaderSize := utils.ReadInt32Le(pages[pageHeaderSize+1+len(oggHeaderMagic) : pageHeaderSize+5+len(oggHeaderMagic)])
			if len(pages) < pageHeaderSize+5+len(oggHeaderMagic)+commentHeaderSize {
				return nil, nil, nil
			}
			commentHeader = pages[pageHeaderSize : pageHeaderSize+5+len(oggHeaderMagic)+commentHeaderSize]
			pageHeaderSize += 5 + len(oggHeaderMagic) + commentHeaderSize
		}

		pageSize := editor.getPageSize(pages)
		tagData = append(tagData, pages[pageHeaderSize:pageSize]...)
		pages = pages[pageSize:]
	}

	pos := bytes.Index(tagData, []byte(oggHeaderMagic))
	if pos != -1 {
		setupHeader = tagData[pos-1:]
		tagData = tagData[:pos-1]
	}

	return commentHeader, tagData, setupHeader
}
예제 #4
0
파일: flac.go 프로젝트: mzinin/tagger
func (editor *FlacTagEditor) parseCommentBlock(data []byte, tag *Tag) error {
	if len(data) < 8 {
		return errors.New("no flac comment block to parse")
	}

	vendorSize := utils.ReadInt32Le(data[4:8])
	return parseVorbisTags(data[8+vendorSize:], tag)
}
예제 #5
0
파일: common.go 프로젝트: mzinin/tagger
func parseVorbisTags(data []byte, tag *Tag) error {
	if len(data) < 4 {
		return errors.New("vorbis data is too short to contain a tag")
	}

	numberOfFields := utils.ReadInt32Le(data[0:4])
	data = data[4:]

	for i := 0; i < numberOfFields; i++ {
		fieldSize := utils.ReadInt32Le(data[0:4])
		if fieldSize+4 <= len(data) {
			parseVorbisTagField(data[4:4+fieldSize], tag)
			data = data[4+fieldSize:]
		}
	}

	return nil
}
예제 #6
0
파일: flac.go 프로젝트: mzinin/tagger
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
}