github.com/boki/go-xmp@v1.0.1/models/qt/qt_metadata.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  package qt
    16  
    17  import (
    18  	"fmt"
    19  	"strconv"
    20  	"strings"
    21  
    22  	"trimmer.io/go-xmp/models/tiff"
    23  	"trimmer.io/go-xmp/xmp"
    24  )
    25  
    26  // QuickTime Metadata Keys written by the "mdta" handler using Reverse DNS names.
    27  // - "com.apple.quicktime." for Apple Quicktime default keys
    28  // - "com.apple.proapps." for Apple Professional apps keys
    29  // - "com.arri.camera" for Arri Camera metadata
    30  // - "com.panasonic.professionalplugin" for Panasonic cameras
    31  // - "com.panasonic.p2.metadata.bmp": "BMf*",
    32  // - "com.panasonic.p2.metadata.xml": <xml>
    33  //
    34  
    35  // General Quicktime Metadata keys (from MacOS CoreMedia Framework headers and libs)
    36  //
    37  // VideoOrientation: like TIFF/EXIF Orientation property
    38  // AffineTransform: used in place of a track display matrix, 3x3 float matrix in row major order
    39  // Direction: degree offset from magnetic north
    40  //
    41  type QtMetadata struct {
    42  	// official metadata keys as defined in MacOS 10.11 SDK
    43  	Album                  string         `qt:"com.apple.quicktime.album"                                 qt:"©alb"      xmp:"qt:Album"`
    44  	Arranger               string         `qt:"com.apple.quicktime.arranger"                              qt:"©arg"      xmp:"qt:Arranger"`
    45  	Artist                 string         `qt:"com.apple.quicktime.artist"                                qt:"albr"      xmp:"qt:Artist"`
    46  	Artwork                string         `qt:"com.apple.quicktime.artwork"                               qt:"covr"      xmp:"qt:Artwork"`
    47  	Author                 string         `qt:"com.apple.quicktime.author"                                qt:"©aut"      xmp:"qt:Author"`
    48  	CameraFrameReadoutTime string         `qt:"com.apple.quicktime.camera.framereadouttimeinmicroseconds" qt:"-"         xmp:"qt:CameraFrameReadoutTime"`
    49  	CameraIdentifier       string         `qt:"com.apple.quicktime.camera.identifier"                     qt:"cmid"      xmp:"qt:CameraIdentifier"`
    50  	CollectionUser         string         `qt:"com.apple.quicktime.collection.user"                       qt:"coll"      xmp:"qt:CollectionUser"`
    51  	Comment                string         `qt:"com.apple.quicktime.comment"                               qt:"©cmt"      xmp:"qt:Comment"`
    52  	Composer               string         `qt:"com.apple.quicktime.composer"                              qt:"©wrt"      xmp:"qt:Composer"`
    53  	ContentIdentifier      string         `qt:"com.apple.quicktime.content.identifier"                    qt:"cnID"      xmp:"qt:ContentIdentifier"`
    54  	Copyright              string         `qt:"com.apple.quicktime.copyright"                             qt:"cprt"      xmp:"qt:Copyright"`
    55  	CreationDate           xmp.Date       `qt:"com.apple.quicktime.creationdate"                          qt:"date"      xmp:"qt:CreationDate"`
    56  	Credits                string         `qt:"com.apple.quicktime.credits"                               qt:"©src"      xmp:"qt:Credits"`
    57  	Description            string         `qt:"com.apple.quicktime.description"                           qt:"©des"      xmp:"qt:Description"`
    58  	DirectionFacing        float64        `qt:"com.apple.quicktime.direction.facing"                      qt:"-"         xmp:"qt:DirectionFacing"`
    59  	DirectionMotion        float64        `qt:"com.apple.quicktime.direction.motion"                      qt:"-"         xmp:"qt:DirectionMotion"`
    60  	Director               string         `qt:"com.apple.quicktime.director"                              qt:"©dir"      xmp:"qt:Director"`
    61  	DisplayName            string         `qt:"com.apple.quicktime.displayname"                           qt:"name"      xmp:"qt:DisplayName"`
    62  	EncodedBy              string         `qt:"com.apple.quicktime.encodedby"                             qt:"©enc"      xmp:"qt:EncodedBy"`
    63  	Genre                  string         `qt:"com.apple.quicktime.genre"                                 qt:"©gen"      xmp:"qt:Genre"`
    64  	Information            string         `qt:"com.apple.quicktime.information"                           qt:"©inf"      xmp:"qt:Information"`
    65  	Keywords               xmp.StringList `qt:"com.apple.quicktime.keywords"                              qt:"©key"      xmp:"qt:Keywords"`
    66  	LocationBody           string         `qt:"com.apple.quicktime.location.body"                         qt:"-"         xmp:"-"`
    67  	LocationDate           xmp.Date       `qt:"com.apple.quicktime.location.date"                         qt:"-"         xmp:"-"`
    68  	LocationISO6709        string         `qt:"com.apple.quicktime.location.iso6709"                      qt:"©xyz"      xmp:"-"`
    69  	LocationName           string         `qt:"com.apple.quicktime.location.name"                         qt:"-"         xmp:"-"`
    70  	LocationNote           string         `qt:"com.apple.quicktime.location.note"                         qt:"-"         xmp:"-"`
    71  	LocationRole           LocationRole   `qt:"com.apple.quicktime.location.role"                         qt:"-"         xmp:"-"`
    72  	Make                   string         `qt:"com.apple.quicktime.make"                                  qt:"©mak"      xmp:"qt:Make"`
    73  	Model                  string         `qt:"com.apple.quicktime.model"                                 qt:"©mod"      xmp:"qt:Model"`
    74  	OriginalArtist         string         `qt:"com.apple.quicktime.originalartist"                        qt:"©ope"      xmp:"qt:OriginalArtist"`
    75  	Performer              string         `qt:"com.apple.quicktime.performer"                             qt:"©prf"      xmp:"qt:Performer"`
    76  	PhonogramRights        string         `qt:"com.apple.quicktime.phonogramrights"                       qt:"©phg"      xmp:"qt:PhonogramRights"`
    77  	Producer               string         `qt:"com.apple.quicktime.producer"                              qt:"©prd"      xmp:"qt:Producer"`
    78  	Publisher              string         `qt:"com.apple.quicktime.publisher"                             qt:"©pub"      xmp:"qt:Publisher"`
    79  	USRating               float64        `qt:"com.apple.quicktime.rating.user"                           qt:"rtng"      xmp:"qt:USRating"`
    80  	Software               string         `qt:"com.apple.quicktime.software"                              qt:"©swr"      xmp:"qt:Software"`
    81  	Title                  string         `qt:"com.apple.quicktime.title"                                 qt:"©nam"      xmp:"qt:Title"`
    82  	Year                   int            `qt:"com.apple.quicktime.year"                                  qt:"yrrc"      xmp:"qt:Year"`
    83  
    84  	// more tags not captured above
    85  	Version                  string               `qt:"com.apple.quicktime.version"                                       qt:"VERS" xmp:"qt:Version"`
    86  	PreferredAffineTransform string               `qt:"com.apple.quicktime.preferred-affine-transform"                    qt:"-"    xmp:"qt:PreferredAffineTransform"`
    87  	VideoOrientation         tiff.OrientationType `qt:"com.apple.quicktime.video-orientation"                             qt:"-"    xmp:"qt:VideoOrientation"`
    88  	WindowLocation           Point                `qt:"com.apple.quicktime.windowlocation"                                qt:"WLOC" xmp:"qt:WindowLocation"`
    89  	CoreMotion               string               `qt:"com.apple.quicktime.core-motion"                                   qt:"-"    xmp:"qt:CoreMotion"`
    90  	CameraDebugInfo          string               `qt:"com.apple.quicktime.camera-debug-info"                             qt:"-"    xmp:"qt:CameraDebugInfo"`
    91  	IsMontage                string               `qt:"com.apple.quicktime.is-montage"                                    qt:"-"    xmp:"qt:IsMontage"`
    92  	PixelDensity             string               `qt:"com.apple.quicktime.pixeldensity"                                  qt:"-"    xmp:"qt:PixelDensity"`
    93  	DetectedFace             string               `qt:"com.apple.quicktime.detected-face"                                 qt:"-"    xmp:"qt:DetectedFace"`
    94  	HasEAN13                 Bool                 `qt:"com.apple.quicktime.detected-machine-readable-code.EAN13"          qt:"-"    xmp:"qt:HasEAN13"`
    95  	HasEAN8                  Bool                 `qt:"com.apple.quicktime.detected-machine-readable-code.EAN8"           qt:"-"    xmp:"qt:HasEAN8"`
    96  	HasUPCE                  Bool                 `qt:"com.apple.quicktime.detected-machine-readable-code.UPCE"           qt:"-"    xmp:"qt:HasUPCE"`
    97  	HasCode39                Bool                 `qt:"com.apple.quicktime.detected-machine-readable-code.Code39"         qt:"-"    xmp:"qt:HasCode39"`
    98  	HasCode39Checksum        Bool                 `qt:"com.apple.quicktime.detected-machine-readable-code.Code39Checksum" qt:"-"    xmp:"qt:HasCode39Checksum"`
    99  	HasCode93                Bool                 `qt:"com.apple.quicktime.detected-machine-readable-code.Code93"         qt:"-"    xmp:"qt:HasCode93"`
   100  	HasCode128               Bool                 `qt:"com.apple.quicktime.detected-machine-readable-code.Code128"        qt:"-"    xmp:"qt:HasCode128"`
   101  	HasI2of5                 Bool                 `qt:"com.apple.quicktime.detected-machine-readable-code.I2of5"          qt:"-"    xmp:"qt:HasI2of5"`
   102  	HasITF14                 Bool                 `qt:"com.apple.quicktime.detected-machine-readable-code.ITF14"          qt:"-"    xmp:"qt:HasITF14"`
   103  	HasDataMatrix            Bool                 `qt:"com.apple.quicktime.detected-machine-readable-code.DataMatrix"     qt:"-"    xmp:"qt:HasDataMatrix"`
   104  	HasQR                    Bool                 `qt:"com.apple.quicktime.detected-machine-readable-code.QR"             qt:"-"    xmp:"qt:HasQR"`
   105  	HasAztec                 Bool                 `qt:"com.apple.quicktime.detected-machine-readable-code.Aztec"          qt:"-"    xmp:"qt:HasAztec"`
   106  	HasPDF417                Bool                 `qt:"com.apple.quicktime.detected-machine-readable-code.PDF417"         qt:"-"    xmp:"qt:HasPDF417"`
   107  	Extension                xmp.TagList          `qt:",any"                                                              qt:",any" xmp:"qt:extension"`
   108  
   109  	// composite structs
   110  	Location *Location `qt:"-"  qt:"-"  xmp:"qt:Location"`
   111  }
   112  
   113  func (m *QtMetadata) Namespaces() xmp.NamespaceList {
   114  	return xmp.NamespaceList{NsQuicktime}
   115  }
   116  
   117  func (m *QtMetadata) Can(nsName string) bool {
   118  	return nsName == NsQuicktime.GetName()
   119  }
   120  
   121  func (x *QtMetadata) SyncModel(d *xmp.Document) error {
   122  	return nil
   123  }
   124  
   125  func (x *QtMetadata) SyncFromXMP(d *xmp.Document) error {
   126  	if x.Location != nil {
   127  		x.LocationBody = x.Location.Body
   128  		x.LocationDate = x.Location.Date
   129  		x.LocationISO6709 = strings.Join([]string{
   130  			string(x.Location.Latitude),
   131  			string(x.Location.Longitude),
   132  			strconv.FormatFloat(x.Location.Altitude, 'f', -1, 64),
   133  		}, "+")
   134  		x.LocationName = x.Location.Name
   135  		x.LocationNote = x.Location.Note
   136  		x.LocationRole = x.Location.Role
   137  	}
   138  	return nil
   139  }
   140  
   141  func (x *QtMetadata) SyncToXMP(d *xmp.Document) error {
   142  	if x.Location == nil && x.LocationISO6709 != "" && x.LocationName != "" {
   143  		x.Location = &Location{
   144  			Body: x.LocationBody,
   145  			Date: x.LocationDate,
   146  			Name: x.LocationName,
   147  			Note: x.LocationNote,
   148  			Role: x.LocationRole,
   149  		}
   150  		// "+43.5968+005.4797+362.904/",
   151  		for i, v := range strings.Split(x.LocationISO6709, "+") {
   152  			switch i {
   153  			case 0:
   154  				x.Location.Latitude = xmp.GPSCoord(v)
   155  			case 1:
   156  				x.Location.Longitude = xmp.GPSCoord(v)
   157  			case 2:
   158  				v = strings.TrimSuffix(v, "/")
   159  				x.Location.Altitude, _ = strconv.ParseFloat(v, 64)
   160  			}
   161  		}
   162  	}
   163  	return nil
   164  }
   165  
   166  func (x *QtMetadata) CanTag(tag string) bool {
   167  	_, err := xmp.GetNativeField(x, tag)
   168  	return err == nil
   169  }
   170  
   171  func (x *QtMetadata) GetTag(tag string) (string, error) {
   172  	if v, err := xmp.GetNativeField(x, tag); err != nil {
   173  		return "", fmt.Errorf("%s: %v", NsQuicktime.GetName(), err)
   174  	} else {
   175  		return v, nil
   176  	}
   177  }
   178  
   179  func (x *QtMetadata) SetTag(tag, value string) error {
   180  	if err := xmp.SetNativeField(x, tag, value); err != nil {
   181  		return fmt.Errorf("%s: %v", NsQuicktime.GetName(), err)
   182  	}
   183  	return nil
   184  }