this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

successfully parse vorbis comment

+123 -5
+123 -5
src/formats/flac.odin
··· 1 1 package formats 2 2 3 3 import "core:bufio" 4 + import "core:encoding/endian" 4 5 import "core:fmt" 5 6 import "core:io" 7 + import "core:mem" 6 8 import os "core:os/os2" 9 + import "core:strconv" 10 + import "core:strings" 7 11 import "core:testing" 8 12 9 - 10 13 ReadError :: enum { 11 14 UnknownError, 12 15 UnsupportedFile, 13 16 UnableToOpenFile, 14 17 UnableToFindVorbisComment, 18 + UnableToReadVendorString, 19 + Invalid_Vendor_String, 20 + Unable_To_Read_Field_Length, 15 21 } 16 22 17 23 VorbisComment :: struct { 18 - title: string, 24 + title: string, 25 + album: string, 26 + album_artist: string, 27 + track_number: u8, 28 + artists: [dynamic]string, 19 29 } 20 30 21 31 check_is_flac :: proc(r: ^bufio.Reader) -> bool { ··· 40 50 MAX_METADATA_BLOCK :: 128 41 51 BLOCK_HEADER_SIZE :: 4 42 52 VORBIS_COMMENT :: 4 53 + MAX_VORBIS_FIELDS :: 10000 // Reasonable limit for metadata fields 54 + MAX_FIELD_LENGTH :: 1024 * 1024 // 1MB max per field 43 55 44 56 Header :: struct { 45 57 is_last: bool, ··· 67 79 } 68 80 } 69 81 82 + parse_vorbis_comment :: proc(arr: ^[]byte) -> (c: VorbisComment, err: ReadError) { 83 + fmt.printfln("Vorbis Comment Bytes: %d", len(arr)) 84 + 85 + length := u32(len(arr)) 86 + cursor: u32 = 0 87 + vendor_str_len: u32 88 + num_fields: u32 89 + ok: bool = true 90 + 91 + if cursor + 4 > u32(len(arr)) { 92 + return VorbisComment{}, .UnknownError // TODO: descriptive error 93 + } 94 + 95 + // Read vendor string length 96 + vendor_str_len, ok = endian.get_u32(arr[cursor:cursor + 4], .Little) 97 + if (!ok) { 98 + return VorbisComment{}, .UnableToReadVendorString 99 + } 100 + fmt.printfln("Vendor string length %d", vendor_str_len) 101 + cursor += 4 102 + 103 + if (vendor_str_len > MAX_FIELD_LENGTH || cursor + vendor_str_len > length) { 104 + return VorbisComment{}, .UnableToReadVendorString 105 + } 106 + 107 + // Read vendor string 108 + vendor_str := string(arr[cursor:cursor + vendor_str_len]) 109 + fmt.printfln("Vendor string %s", vendor_str) 110 + cursor += vendor_str_len 111 + 112 + //Read number of fields 113 + if cursor + 4 > u32(len(arr)) { 114 + return VorbisComment{}, .UnknownError // TODO: descriptive error 115 + } 116 + num_fields, ok = endian.get_u32(arr[cursor:cursor + 4], .Little) 117 + if (!ok) { 118 + return VorbisComment{}, .UnknownError 119 + } 120 + fmt.printfln("Number of fields %d", num_fields) 121 + if (num_fields > MAX_VORBIS_FIELDS) { 122 + return VorbisComment{}, .UnknownError 123 + } 124 + cursor += 4 125 + 126 + // Read fields 127 + comment: VorbisComment 128 + for i in 0 ..< num_fields { 129 + 130 + if cursor + 4 > u32(len(arr)) { 131 + return VorbisComment{}, .UnknownError // TODO: descriptive error 132 + } 133 + 134 + field_length: u32 135 + 136 + field_length, ok = endian.get_u32(arr[cursor:cursor + 4], .Little) 137 + if (!ok) { 138 + return VorbisComment{}, .Unable_To_Read_Field_Length 139 + } 140 + 141 + if (field_length > MAX_FIELD_LENGTH || cursor + field_length > length) { 142 + return VorbisComment{}, .UnknownError 143 + } 144 + fmt.printfln("Field length %d", field_length) 145 + 146 + cursor += 4 147 + 148 + field := string(arr[cursor:cursor + field_length]) 149 + fmt.printfln("field %v", field) 150 + 151 + pair := strings.split(field, "=") 152 + defer delete(pair) 153 + if (len(pair) != 2) { 154 + return VorbisComment{}, .UnknownError 155 + } 156 + key := pair[0] 157 + value := pair[1] 158 + 159 + fmt.printfln("key |%v| value |%v| ", key, value) 160 + 161 + switch key { 162 + case "ALBUM": 163 + comment.album = value 164 + case "ARTIST": 165 + append(&comment.artists, value) 166 + case "ALBUM ARTIST": 167 + comment.album_artist = value 168 + case "TITLE": 169 + comment.title = value 170 + case "TRACK NUMBER": 171 + track_number, ok := strconv.parse_int(value) 172 + if !ok { 173 + track_number = 0 174 + } 175 + comment.track_number = u8(track_number) 176 + } 177 + cursor += field_length 178 + } 179 + 180 + if comment.album_artist == "" && len(comment.artists) > 0 { 181 + comment.album_artist = comment.artists[0] 182 + } 183 + 184 + return comment, nil 185 + } 186 + 187 + 70 188 read :: proc(file: ^os.File) -> (c: VorbisComment, err: ReadError) { 71 189 72 190 r: bufio.Reader ··· 117 235 return VorbisComment{}, .UnknownError 118 236 } 119 237 120 - fmt.printfln("\n\n Vorbis Comment Bytes: %s \n\n", vorbisCommentBytes) 121 - 122 - return VorbisComment{title = "Vampire in the Corner"}, nil 238 + return parse_vorbis_comment(&vorbisCommentBytes) 123 239 } 124 240 125 241 if (header.is_last) { ··· 158 274 159 275 160 276 actual, err := read(f) 277 + 278 + fmt.printfln("Actual: %v", actual) 161 279 162 280 expected := "Vampire in the Corner" 163 281