github.com/boki/go-xmp@v1.0.1/models/id3/types.go (about) 1 // Copyright (c) 2017-2018 Alexander Eichhorn 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 // not use this file except in compliance with the License. You may obtain 5 // a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations 13 // under the License. 14 15 // http://id3.org/ 16 // http://id3.org/id3v2.4.0-frames 17 18 // FIXME: Version 2.4 of the specification prescribes that all text fields 19 // (the fields that start with a T, except for TXXX) can contain multiple 20 // values separated by a null character. The null character varies by 21 // character encoding. 22 23 package id3 24 25 import ( 26 "bytes" 27 "fmt" 28 "strconv" 29 "strings" 30 "time" 31 32 "trimmer.io/go-xmp/models/xmp_dm" 33 "trimmer.io/go-xmp/xmp" 34 ) 35 36 const ( 37 TIME_FORMAT_23 = "1504" // HHMM 38 DATE_FORMAT_23 = "0102" // DDMM 39 ) 40 41 type Bool int // 0 no, 1 yes 42 43 const ( 44 False Bool = 0 45 True Bool = 1 46 ) 47 48 func (b Bool) Value() bool { 49 return b == 1 50 } 51 52 type Time23 time.Time 53 54 func (x Time23) Value() time.Time { 55 return time.Time(x) 56 } 57 58 func (x Time23) IsZero() bool { 59 return time.Time(x).IsZero() 60 } 61 62 func (x *Time23) UnmarshalText(data []byte) error { 63 value := string(data) 64 if t, err := time.Parse(TIME_FORMAT_23, value); err != nil { 65 return fmt.Errorf("id3: invalid time value '%s'", value) 66 } else { 67 *x = Time23(t) 68 } 69 return nil 70 } 71 72 func (x Time23) MarshalText() ([]byte, error) { 73 if x.IsZero() { 74 return nil, nil 75 } 76 return []byte(time.Time(x).Format(TIME_FORMAT_23)), nil 77 } 78 79 type Date23 time.Time 80 81 func (x Date23) Value() time.Time { 82 return time.Time(x) 83 } 84 85 func (x Date23) IsZero() bool { 86 return time.Time(x).IsZero() 87 } 88 89 func (x *Date23) UnmarshalText(data []byte) error { 90 value := string(data) 91 if t, err := time.Parse(DATE_FORMAT_23, value); err != nil { 92 return fmt.Errorf("id3: invalid date value '%s'", value) 93 } else { 94 *x = Date23(t) 95 } 96 return nil 97 } 98 99 func (x Date23) MarshalText() ([]byte, error) { 100 if x.IsZero() { 101 return nil, nil 102 } 103 return []byte(time.Time(x).Format(DATE_FORMAT_23)), nil 104 } 105 106 // TCON 107 // 108 type GenreV1 byte 109 110 func (x *GenreV1) UnmarshalText(data []byte) error { 111 value := string(data) 112 g, err := ParseGenreV1(value) 113 if err != nil { 114 return err 115 } 116 *x = g 117 return nil 118 } 119 120 func (x GenreV1) MarshalText() ([]byte, error) { 121 return []byte(x.String()), nil 122 } 123 124 // See Genre List at http://id3.org/id3v2.3.0 125 func (x GenreV1) String() string { 126 if v, ok := GenreMap[x]; ok { 127 return v 128 } 129 return strconv.Itoa(int(x)) 130 } 131 132 func ParseGenreV1(s string) (GenreV1, error) { 133 for i, v := range GenreMap { 134 if v == s { 135 return i, nil 136 } 137 } 138 if t, err := strconv.Atoi(s); err == nil { 139 return GenreV1(t), nil 140 } 141 return 0xff, fmt.Errorf("id3: invalid genre '%s'", s) 142 } 143 144 type Genre []string 145 146 func (x *Genre) UnmarshalText(data []byte) error { 147 value := string(data) 148 for _, v := range strings.Split(value, ",") { 149 v = strings.TrimSpace(v) 150 if g, err := ParseGenreV1(v); err == nil { 151 *x = append(*x, g.String()) 152 continue 153 } 154 switch value { 155 case "RX": 156 *x = append(*x, "Remix") 157 case "CR": 158 *x = append(*x, "Cover") 159 default: 160 *x = append(*x, value) 161 } 162 } 163 return nil 164 } 165 166 func (x Genre) String() string { 167 return strings.Join(x, ", ") 168 } 169 170 func (x Genre) MarshalText() ([]byte, error) { 171 return []byte(x.String()), nil 172 } 173 174 // TRCK 175 // 10 176 // 10/12 177 type TrackNum struct { 178 Track int 179 Total int 180 } 181 182 func (x TrackNum) Value() int { 183 return x.Track 184 } 185 186 func (x TrackNum) IsZero() bool { 187 return x.Track == 0 && x.Total == 0 188 } 189 190 func (x *TrackNum) UnmarshalText(data []byte) error { 191 var err error 192 v := string(data) 193 n := TrackNum{} 194 if strings.Contains(v, "/") { 195 _, err = fmt.Sscanf(v, "%d/%d", &n.Track, &n.Total) 196 } else { 197 n.Track, err = strconv.Atoi(v) 198 } 199 if err != nil { 200 return fmt.Errorf("id3: invalid track number '%s': %v", v, err) 201 } 202 *x = n 203 return nil 204 } 205 206 func (x TrackNum) MarshalText() ([]byte, error) { 207 if x.Total == 0 { 208 return []byte(strconv.Itoa(x.Track)), nil 209 } 210 buf := bytes.Buffer{} 211 buf.WriteString(strconv.FormatInt(int64(x.Track), 10)) 212 buf.WriteByte('/') 213 buf.WriteString(strconv.FormatInt(int64(x.Total), 10)) 214 return buf.Bytes(), nil 215 } 216 217 // OWNE 218 type Owner struct { 219 Currency string `xmp:"id3:currency"` 220 Price float32 `xmp:"id3:price"` 221 PurchaseDate xmp.Date `xmp:"id3:purchaseDate"` 222 Seller string `xmp:"id3:seller"` 223 } 224 225 func (x *Owner) UnmarshalText(data []byte) error { 226 // TODO: need samples 227 return nil 228 } 229 230 // ETCO 231 type Marker struct { 232 MarkerType MarkerType `xmp:"id3:type,attr"` 233 Timestamp int64 `xmp:"id3:timestamp,attr"` 234 Unit UnitType `xmp:"id3:unit,attr"` 235 } 236 237 type MarkerList []Marker 238 239 func (x *MarkerList) UnmarshalText(data []byte) error { 240 // TODO: need samples 241 return nil 242 } 243 244 func (x MarkerList) Typ() xmp.ArrayType { 245 return xmp.ArrayTypeOrdered 246 } 247 248 func (x MarkerList) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 249 return xmp.MarshalArray(e, node, x.Typ(), x) 250 } 251 252 func (x *MarkerList) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 253 return xmp.UnmarshalArray(d, node, x.Typ(), x) 254 } 255 256 // SYLT 257 // 258 type TimedLyrics struct { 259 Lang string `xmp:"id3:lang,attr"` 260 Type LyricsType `xmp:"id3:type,attr"` 261 Unit PositionType `xmp:"id3:unit,attr"` 262 Lyrics TimedTextList `xmp:"id3:lyrics,attr"` 263 } 264 265 type TimedLyricsArray []TimedLyrics 266 267 func (x TimedLyricsArray) Typ() xmp.ArrayType { 268 return xmp.ArrayTypeUnordered 269 } 270 271 func (x TimedLyricsArray) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 272 return xmp.MarshalArray(e, node, x.Typ(), x) 273 } 274 275 func (x *TimedLyricsArray) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 276 return xmp.UnmarshalArray(d, node, x.Typ(), x) 277 } 278 279 // see id3 v.24 spec 4.9 280 // - one id3 frame per language and content type 281 // - null-terminated text followed by a timestamp and optionally newline 282 // 283 // "Strang" $00 xx xx "ers" $00 xx xx " in" $00 xx xx " the" $00 xx xx 284 // " night" $00 xx xx 0A "Ex" $00 xx xx "chang" $00 xx xx "ing" $00 xx 285 // xx "glan" $00 xx xx "ces" $00 xx xx 286 // 287 func (x *TimedLyricsArray) UnmarshalText(data []byte) error { 288 // TODO: need samples 289 return nil 290 } 291 292 type TimedText struct { 293 Text string `xmp:"id3:text,attr"` 294 Timestamp int64 `xmp:"id3:timestamp,attr"` 295 } 296 297 type TimedTextList []TimedText 298 299 func (x TimedTextList) Typ() xmp.ArrayType { 300 return xmp.ArrayTypeOrdered 301 } 302 303 func (x TimedTextList) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 304 return xmp.MarshalArray(e, node, x.Typ(), x) 305 } 306 307 func (x *TimedTextList) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 308 return xmp.UnmarshalArray(d, node, x.Typ(), x) 309 } 310 311 // COMM 312 // 313 type Comment struct { 314 Lang string `xmp:"id3:lang,attr"` 315 Type string `xmp:"id3:type,attr"` 316 Text string `xmp:"id3:text,attr"` 317 } 318 319 type CommentArray []Comment 320 321 // TODO: need samples 322 func (x *CommentArray) UnmarshalText(data []byte) error { 323 *x = append(*x, Comment{ 324 Text: string(data), 325 }) 326 return nil 327 } 328 329 func (x CommentArray) Typ() xmp.ArrayType { 330 return xmp.ArrayTypeUnordered 331 } 332 333 func (x CommentArray) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 334 return xmp.MarshalArray(e, node, x.Typ(), x) 335 } 336 337 func (x *CommentArray) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 338 return xmp.UnmarshalArray(d, node, x.Typ(), x) 339 } 340 341 // RVA2 342 // 343 type VolumeAdjust struct { 344 Channel ChannelType `xmp:"id3:channel,attr"` 345 Adjustment float32 `xmp:"id3:adjust,attr"` 346 Bits byte `xmp:"id3:bits,attr"` 347 PeakVolume float32 `xmp:"id3:peak,attr"` 348 } 349 350 type VolumeAdjustArray []VolumeAdjust 351 352 func (x *VolumeAdjustArray) UnmarshalText(data []byte) error { 353 // TODO: need samples 354 return nil 355 } 356 357 func (x VolumeAdjustArray) Typ() xmp.ArrayType { 358 return xmp.ArrayTypeUnordered 359 } 360 361 func (x VolumeAdjustArray) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 362 return xmp.MarshalArray(e, node, x.Typ(), x) 363 } 364 365 func (x *VolumeAdjustArray) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 366 return xmp.UnmarshalArray(d, node, x.Typ(), x) 367 } 368 369 // EQU2 370 // 371 type Equalization struct { 372 Method EqualizationMethod `xmp:"id3:method,attr"` 373 Identification string `xmp:"id3:id,attr"` 374 Adjustments AdjustmentPointList `xmp:"id3:points"` 375 } 376 377 type EqualizationList []Equalization 378 379 func (x *EqualizationList) UnmarshalText(data []byte) error { 380 // TODO: need samples 381 return nil 382 } 383 384 func (x EqualizationList) Typ() xmp.ArrayType { 385 return xmp.ArrayTypeUnordered 386 } 387 388 func (x EqualizationList) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 389 return xmp.MarshalArray(e, node, x.Typ(), x) 390 } 391 392 func (x *EqualizationList) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 393 return xmp.UnmarshalArray(d, node, x.Typ(), x) 394 } 395 396 type AdjustmentPoint struct { 397 Frequency int `xmp:"id3:frequency,attr"` 398 Adjustment float32 `xmp:"id3:adjust,attr"` 399 } 400 401 type AdjustmentPointList []AdjustmentPoint 402 403 func (x AdjustmentPointList) Typ() xmp.ArrayType { 404 return xmp.ArrayTypeOrdered 405 } 406 407 func (x AdjustmentPointList) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 408 return xmp.MarshalArray(e, node, x.Typ(), x) 409 } 410 411 func (x *AdjustmentPointList) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 412 return xmp.UnmarshalArray(d, node, x.Typ(), x) 413 } 414 415 // RVRB 416 type Reverb struct { 417 ReverbLeftMs int `xmp:"id3:reverbLeftMs"` 418 ReverbRightMs int `xmp:"id3:reverbRightMs"` 419 ReverbBouncesLeft byte `xmp:"id3:reverbBouncesLeft"` 420 ReverbBouncesRight byte `xmp:"id3:reverbBouncesRight"` 421 ReverbFeedbackLtoL byte `xmp:"id3:reverbFeedbackLtoL"` 422 ReverbFeedbackLToR byte `xmp:"id3:reverbFeedbackLToR"` 423 ReverbFeedbackRtoR byte `xmp:"id3:reverbFeedbackRtoR"` 424 ReverbFeedbackRtoL byte `xmp:"id3:reverbFeedbackRtoL"` 425 PremixLtoR byte `xmp:"id3:premixLtoR"` 426 PremixRtoL byte `xmp:"id3:premixRtoL"` 427 } 428 429 func (x *Reverb) UnmarshalText(data []byte) error { 430 // TODO: need samples 431 return nil 432 } 433 434 // APIC 435 // 436 type AttachedPicture struct { 437 Mimetype string `xmp:"id3:mimetype,attr"` 438 Type PictureType `xmp:"id3:pictureType,attr"` 439 Description string `xmp:"id3:description,attr"` 440 Data []byte `xmp:"id3:image"` 441 } 442 443 type AttachedPictureArray []AttachedPicture 444 445 func (x *AttachedPictureArray) UnmarshalText(data []byte) error { 446 // TODO: need samples 447 return nil 448 } 449 450 func (x AttachedPictureArray) Typ() xmp.ArrayType { 451 return xmp.ArrayTypeUnordered 452 } 453 454 func (x AttachedPictureArray) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 455 return xmp.MarshalArray(e, node, x.Typ(), x) 456 } 457 458 func (x *AttachedPictureArray) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 459 return xmp.UnmarshalArray(d, node, x.Typ(), x) 460 } 461 462 // GEOB 463 // 464 type EncapsulatedObject struct { 465 Mimetype string `xmp:"id3:mimetype,attr"` 466 Filename string `xmp:"id3:filename,attr"` 467 Description string `xmp:"id3:description,attr"` 468 Data []byte `xmp:"id3:data"` 469 } 470 471 type EncapsulatedObjectArray []EncapsulatedObject 472 473 func (x *EncapsulatedObjectArray) UnmarshalText(data []byte) error { 474 // TODO: need samples 475 return nil 476 } 477 478 func (x EncapsulatedObjectArray) Typ() xmp.ArrayType { 479 return xmp.ArrayTypeUnordered 480 } 481 482 func (x EncapsulatedObjectArray) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 483 return xmp.MarshalArray(e, node, x.Typ(), x) 484 } 485 486 func (x *EncapsulatedObjectArray) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 487 return xmp.UnmarshalArray(d, node, x.Typ(), x) 488 } 489 490 // POPM 491 // 492 type Popularimeter struct { 493 Email string `xmp:"id3:email,attr"` 494 Rating byte `xmp:"id3:rating,attr"` 495 Counter int64 `xmp:"id3:counter,attr"` 496 } 497 498 type PopularimeterArray []Popularimeter 499 500 func (x *PopularimeterArray) UnmarshalText(data []byte) error { 501 // TODO: need samples 502 return nil 503 } 504 505 func (x PopularimeterArray) Typ() xmp.ArrayType { 506 return xmp.ArrayTypeUnordered 507 } 508 509 func (x PopularimeterArray) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 510 return xmp.MarshalArray(e, node, x.Typ(), x) 511 } 512 513 func (x *PopularimeterArray) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 514 return xmp.UnmarshalArray(d, node, x.Typ(), x) 515 } 516 517 // RBUF 518 // 519 type BufferSize struct { 520 BufferSize int64 `xmp:"id3:bufferSize,attr"` 521 Flag byte `xmp:"id3:flag,attr"` 522 NextOffset int64 `xmp:"id3:next,attr"` 523 } 524 525 func (x *BufferSize) UnmarshalText(data []byte) error { 526 // TODO: need samples 527 return nil 528 } 529 530 // AENC 531 // 532 type AudioEncryption struct { 533 Owner string `xmp:"id3:owner,attr"` 534 PreviewStart int `xmp:"id3:previewStart,attr"` 535 PreviewLength int `xmp:"id3:previewLength,attr"` 536 EncryptionInfo []byte `xmp:"id3:encryptionInfo"` 537 } 538 539 func (x *AudioEncryption) UnmarshalText(data []byte) error { 540 // TODO: need samples 541 return nil 542 } 543 544 // LINK 545 // 546 type Link struct { 547 LinkedID string `xmp:"id3:linkedId,attr"` 548 Url string `xmp:"id3:url,attr"` 549 Extra xmp.StringList `xmp:"id3:extra"` 550 } 551 552 type LinkArray []Link 553 554 func (x *LinkArray) UnmarshalText(data []byte) error { 555 // TODO: need samples 556 return nil 557 } 558 559 func (x LinkArray) Typ() xmp.ArrayType { 560 return xmp.ArrayTypeUnordered 561 } 562 563 func (x LinkArray) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 564 return xmp.MarshalArray(e, node, x.Typ(), x) 565 } 566 567 func (x *LinkArray) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 568 return xmp.UnmarshalArray(d, node, x.Typ(), x) 569 } 570 571 // POSS 572 // 573 type PositionSync struct { 574 Unit PositionType `xmp:"id3:unit,attr"` 575 Position int64 `xmp:"id3:position,attr"` 576 } 577 578 // COMR 579 // 580 type Commercial struct { 581 Prices PriceList `xmp:"id3:prices"` 582 ValidUntil Date23 `xmp:"id3:validUntil,attr"` 583 ContactUrl xmp.Url `xmp:"id3:contactUrl"` 584 ReceivedAs DeliveryMethod `xmp:"id3:receivedAs,attr"` 585 SellerName string `xmp:"id3:sellerName,attr"` 586 Description string `xmp:"id3:description,attr"` 587 LogoMimetype string `xmp:"id3:logoMimetype,attr"` 588 LogoImage []byte `xmp:"id3:logoImage"` 589 } 590 591 func (x *Commercial) UnmarshalText(data []byte) error { 592 // TODO: need samples 593 return nil 594 } 595 596 type Price struct { 597 Currency string 598 Amount float32 599 } 600 601 type PriceList []Price 602 603 func (x PriceList) Typ() xmp.ArrayType { 604 return xmp.ArrayTypeUnordered 605 } 606 607 func (x PriceList) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 608 return xmp.MarshalArray(e, node, x.Typ(), x) 609 } 610 611 func (x *PriceList) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 612 return xmp.UnmarshalArray(d, node, x.Typ(), x) 613 } 614 615 // ENCR 616 // 617 type EncryptionMethod struct { 618 OwnerUrl xmp.Url `xmp:"id3:ownerUrl,attr"` 619 Method byte `xmp:"id3:method,attr"` 620 Data []byte `xmp:"id3:data"` 621 } 622 623 type EncryptionMethodArray []EncryptionMethod 624 625 func (x *EncryptionMethodArray) UnmarshalText(data []byte) error { 626 // TODO: need samples 627 return nil 628 } 629 630 func (x EncryptionMethodArray) Typ() xmp.ArrayType { 631 return xmp.ArrayTypeUnordered 632 } 633 634 func (x EncryptionMethodArray) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 635 return xmp.MarshalArray(e, node, x.Typ(), x) 636 } 637 638 func (x *EncryptionMethodArray) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 639 return xmp.UnmarshalArray(d, node, x.Typ(), x) 640 } 641 642 // GRID 643 // 644 type Group struct { 645 OwnerUrl xmp.Url `xmp:"id3:ownerUrl,attr"` 646 Symbol byte `xmp:"id3:symbol,attr"` // 0x80-0xF0 647 Data []byte `xmp:"id3:data"` 648 } 649 650 type GroupArray []Group 651 652 func (x *GroupArray) UnmarshalText(data []byte) error { 653 // TODO: need samples 654 return nil 655 } 656 657 func (x GroupArray) Typ() xmp.ArrayType { 658 return xmp.ArrayTypeUnordered 659 } 660 661 func (x GroupArray) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 662 return xmp.MarshalArray(e, node, x.Typ(), x) 663 } 664 665 func (x *GroupArray) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 666 return xmp.UnmarshalArray(d, node, x.Typ(), x) 667 } 668 669 // PRIV 670 // 671 type PrivateData struct { 672 Owner string `xmp:"id3:owner,attr"` 673 Data []byte `xmp:"id3:data"` 674 } 675 676 type PrivateDataArray []PrivateData 677 678 func (x *PrivateDataArray) UnmarshalText(data []byte) error { 679 // TODO: need samples 680 return nil 681 } 682 683 func (x PrivateDataArray) Typ() xmp.ArrayType { 684 return xmp.ArrayTypeUnordered 685 } 686 687 func (x PrivateDataArray) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 688 return xmp.MarshalArray(e, node, x.Typ(), x) 689 } 690 691 func (x *PrivateDataArray) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 692 return xmp.UnmarshalArray(d, node, x.Typ(), x) 693 } 694 695 // SIGN 696 // 697 type Signature struct { 698 GroupSymbol byte `xmp:"id3:groupSymbol,attr"` // 0x80-0xF0 699 Signature []byte `xmp:"id3:signature"` 700 } 701 702 type SignatureArray []Signature 703 704 func (x *SignatureArray) UnmarshalText(data []byte) error { 705 // TODO: need samples 706 return nil 707 } 708 709 func (x SignatureArray) Typ() xmp.ArrayType { 710 return xmp.ArrayTypeUnordered 711 } 712 713 func (x SignatureArray) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 714 return xmp.MarshalArray(e, node, x.Typ(), x) 715 } 716 717 func (x *SignatureArray) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 718 return xmp.UnmarshalArray(d, node, x.Typ(), x) 719 } 720 721 // ASPI 722 // 723 type AudioSeekIndex struct { 724 Start int64 `xmp:"id3:start,attr"` 725 Length int64 `xmp:"id3:length,attr"` 726 NumberOfPoints int `xmp:"id3:numberOfPoints,attr"` 727 BitsPerPoint byte `xmp:"id3:bitsPerPoint,attr"` 728 Points xmp.IntList `xmp:"id3:points"` 729 } 730 731 func (x *AudioSeekIndex) UnmarshalText(data []byte) error { 732 // TODO: need samples 733 return nil 734 } 735 736 // CHAP 737 // 738 type Chapter xmpdm.Marker 739 740 type ChapterList []Chapter 741 742 func (x *ChapterList) UnmarshalText(data []byte) error { 743 // TODO: need samples 744 return nil 745 } 746 747 func (x ChapterList) Typ() xmp.ArrayType { 748 return xmp.ArrayTypeOrdered 749 } 750 751 func (x ChapterList) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 752 return xmp.MarshalArray(e, node, x.Typ(), x) 753 } 754 755 func (x *ChapterList) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 756 return xmp.UnmarshalArray(d, node, x.Typ(), x) 757 } 758 759 // CTOC 760 // 761 type TocEntry struct { 762 Flags int `xmp:"id3:flags"` 763 IDList xmp.StringList `xmp:"id3:idlist"` 764 Info string `xmp:"id3:info"` 765 } 766 767 type TocEntryList []TocEntry 768 769 func (x *TocEntryList) UnmarshalText(data []byte) error { 770 // TODO: need samples 771 return nil 772 } 773 774 func (x TocEntryList) Typ() xmp.ArrayType { 775 return xmp.ArrayTypeOrdered 776 } 777 778 func (x TocEntryList) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 779 return xmp.MarshalArray(e, node, x.Typ(), x) 780 } 781 782 func (x *TocEntryList) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 783 return xmp.UnmarshalArray(d, node, x.Typ(), x) 784 }