Example #1
0
// Parse returns filled Tag object for the given music file.
func Parse(filename string) (tag Tag, err error) {
	cFilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cFilename))

	// Open file.
	cId3File, err := C.id3_file_open(cFilename, C.ID3_FILE_MODE_READONLY)
	if err != nil {
		return Tag{}, err
	}
	// TODO: Can't find out why we have segfault sometimes on this close.
	//       But it seems that without this close file descriptors do not
	//       leak. So, we can live without it.
	// defer C.id3_file_close(cId3File)

	// Read tag.
	cTag, err := C.id3_file_tag(cId3File)
	if err != nil {
		return Tag{}, err
	}

	tag = Tag{frames: make(map[string]string)}

	// Parse all frames.
	for i := C.uint(0); i < cTag.nframes; i++ {
		cFrame := C.id3_hlp_get_tag_frame(cTag, i)
		cId := C.id3_hlp_get_frame_id(cFrame)
		// XXX: As I understood cId memory will be GCed with id
		//      (they share same memory).
		id := C.GoString(cId)
		cVal := C.id3_hlp_get_frame_string(cFrame)
		val := C.GoString(cVal)

		tag.frames[id] = val
	}

	return tag, nil
}
Example #2
0
// Parse returns filled Tag object for the given music file.
func Parse(filename string) (tag *Tag, err os.Error) {
	cFilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cFilename))

	// Open file.
	cId3File, err := C.id3_file_open(cFilename, C.ID3_FILE_MODE_READONLY)
	if err != nil {
		return nil, err
	}
	defer C.id3_file_close(cId3File)

	tag = new(Tag)
	tag.frames = make(map[string]string)

	// Read tag.
	tag.cTag, err = C.id3_file_tag(cId3File)
	if err != nil {
		return nil, err
	}
	// Tag struct will be released with file's one.

	// Parse all frames.
	for i := _Ctype_uint(0); i < tag.cTag.nframes; i++ {
		cFrame := C.id3_hlp_get_tag_frame(tag.cTag, i)
		cId := C.id3_hlp_get_frame_id(cFrame)
		// XXX: As I understood cId memory will be GCed with id
		//      (they share same memory).
		id := C.GoString(cId)
		cVal := C.id3_hlp_get_frame_string(cFrame)
		val := C.GoString(cVal)

		tag.frames[id] = val
	}

	return tag, nil
}