github.com/boki/go-xmp@v1.0.1/models/qt/types.go (about) 1 // Trimmer Media SDK 2 // 3 // Copyright (c) 2013-2016 KIDTSUNAMI 4 // Author: alex@kidtsunami.com 5 // 6 7 package qt 8 9 import ( 10 "bytes" 11 "fmt" 12 "strconv" 13 "strings" 14 15 "trimmer.io/go-xmp/xmp" 16 ) 17 18 type LocationRole int 19 20 const ( 21 LocationRoleShooting LocationRole = 0 22 LocationRoleReal LocationRole = 1 23 LocationRoleFictional LocationRole = 2 24 ) 25 26 type Bool int // 0 no, 1 yes 27 28 func (b Bool) Value() bool { 29 return b == 1 30 } 31 32 // defined to overwrite UnmarshalText, otherwise similar to xmp.AltString 33 // 34 type MultilangArray xmp.AltString 35 36 func (x *MultilangArray) UnmarshalText(data []byte) error { 37 // TODO: need samples 38 return nil 39 } 40 41 func (x MultilangArray) MarshalXMP(e *xmp.Encoder, node *xmp.Node, m xmp.Model) error { 42 return xmp.MarshalArray(e, node, xmp.AltString(x).Typ(), xmp.AltString(x)) 43 } 44 45 func (x *MultilangArray) UnmarshalXMP(d *xmp.Decoder, node *xmp.Node, m xmp.Model) error { 46 return xmp.UnmarshalArray(d, node, xmp.AltString(*x).Typ(), (*xmp.AltString)(x)) 47 } 48 49 type Location struct { 50 Body string `xmp:"qt:Body,attr"` 51 Date xmp.Date `xmp:"qt:Date,attr"` 52 Longitude xmp.GPSCoord `xmp:"qt:Longitude,attr"` 53 Latitude xmp.GPSCoord `xmp:"qt:Latitude,attr"` 54 Altitude float64 `xmp:"qt:Altitude,attr"` 55 Name string `xmp:"qt:Name,attr"` 56 Note string `xmp:"qt:Note,attr"` 57 Role LocationRole `xmp:"qt:Role,attr"` 58 } 59 60 func (x *Location) UnmarshalText(data []byte) error { 61 // todo: need sample data 62 return nil 63 } 64 65 type Point struct { 66 X int 67 Y int 68 } 69 70 func (x Point) IsZero() bool { 71 return x.X == 0 && x.Y == 0 72 } 73 74 func (x Point) String() string { 75 buf := bytes.Buffer{} 76 buf.WriteString(strconv.FormatInt(int64(x.X), 10)) 77 buf.WriteByte(',') 78 buf.WriteString(strconv.FormatInt(int64(x.Y), 10)) 79 return buf.String() 80 } 81 82 func (x *Point) UnmarshalText(data []byte) error { 83 v := string(data) 84 f := "%d,%d" 85 switch true { 86 case strings.Contains(v, "/"): 87 f = "%d/%d" 88 case strings.Contains(v, ":"): 89 f = "%d:%d" 90 case strings.Contains(v, " "): 91 f = "%d %d" 92 case strings.Contains(v, ";"): 93 f = "%d;%d" 94 } 95 p := Point{} 96 if _, err := fmt.Sscanf(v, f, &p.X, &p.Y); err != nil { 97 return fmt.Errorf("qt: invalid point value '%s': %v", v, err) 98 } 99 *x = p 100 return nil 101 } 102 103 func (x Point) MarshalText() ([]byte, error) { 104 if x.IsZero() { 105 return nil, nil 106 } 107 return []byte(x.String()), nil 108 } 109 110 type ContentRating struct { 111 Standard string `xmp:"qt:Standard,attr"` 112 Rating string `xmp:"qt:Rating,attr"` 113 Score string `xmp:"qt:Score,attr"` 114 Reasons string `xmp:"qt:Reasons,attr"` 115 } 116 117 func (x ContentRating) IsZero() bool { 118 return x.Standard == "" && x.Rating == "" 119 } 120 121 func (x ContentRating) String() string { 122 buf := bytes.Buffer{} 123 buf.WriteByte('(') 124 buf.WriteString(x.Standard) 125 buf.WriteByte('|') 126 buf.WriteString(x.Rating) 127 buf.WriteByte('|') 128 buf.WriteString(x.Score) 129 buf.WriteByte('|') 130 buf.WriteString(x.Reasons) 131 return buf.String() 132 } 133 134 func (x *ContentRating) UnmarshalText(data []byte) error { 135 cr := ContentRating{} 136 v := string(data) 137 v = strings.TrimSpace(v) 138 v = strings.TrimPrefix(v, "(") 139 v = strings.TrimSuffix(v, ")") 140 for i, s := range strings.Split(v, "|") { 141 switch i { 142 case 1: 143 cr.Standard = s 144 case 2: 145 cr.Rating = s 146 case 3: 147 cr.Score = s 148 case 4: 149 cr.Reasons = s 150 } 151 } 152 *x = cr 153 return nil 154 } 155 156 func (x ContentRating) MarshalText() ([]byte, error) { 157 if x.IsZero() { 158 return nil, nil 159 } 160 return []byte(x.String()), nil 161 }